You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/deploying.md
+61-23Lines changed: 61 additions & 23 deletions
Original file line number
Diff line number
Diff line change
@@ -1,40 +1,48 @@
1
1
# Deploying
2
2
3
-
When time comes to share your project, you have many options for deploying it for others to see. Framework is compatible with many static site hosts and automation environments. In this guide we’ll focus on deploying to Observable manually, then with GitHub Actions.
3
+
You can host your built Framework project on any static site hosting service, or self-host it with any static site server. This guide covers deploying to [Observable](https://observablehq.com), which is the easiest way to host your Framework project as support is built-in. We’ll also cover setting up automated deploys with GitHub Actions.
4
4
5
-
## Manually deploying to Observable
5
+
<divclass="tip">
6
6
7
-
If you don’t already have a project to deploy, you can create one by following [getting-started](./getting-started). First, make sure that your project builds without error:
7
+
If you don’t already have a project ready to deploy, create one by following our [Getting started guide](./getting-started).
8
+
9
+
</div>
10
+
11
+
## Manual deploys
12
+
13
+
First, make sure that your project builds without error:
8
14
9
15
```sh
10
-
$ npm run build
16
+
npm run build
11
17
```
12
18
13
-
Once that is done you can deploy to Observable with the command
19
+
Once that is done you can deploy to Observable:
14
20
15
21
```sh
16
-
$ npm run deploy
22
+
npm run deploy
17
23
```
18
24
19
-
The first time you run this command, you will be prompted for details needed to set up the project on the server, such as the project's _slug_ (which determines its URL), and the access level. If you don’t already have an Observable account or aren’t signedin, this command will also guide you through setting that up.
25
+
The first time you deploy a project, you will be prompted to configure the project’s _slug_ (which determines its URL), access level, and other details. If you don’t yet have an Observable account or aren’t signed-in, you will also be prompted to sign-up or sign-in.
20
26
21
-
When the deploy command finishes, it prints a link to observablehq.cloud where you can view your deployed project. If you choose “private” as the access level, you can now share that link with anyone who is a member of your workspace. If you chose “public”, you can share that link with anyone and they’ll be able to see your Framework project.
27
+
When the deploy command finishes, it prints a link to observablehq.cloud where you can view your deployed project. If you choose *private* as the access level, that link will only be accessible to members of your Observable workspace. (You can invite people to your workspace by going to observablehq.com.) If you chose *public*, you can share your project link with anyone.
22
28
23
-
<divclass="note">The deploy command creates a file at <code>docs/.observablehq/deploy.json</code> with information on where to deploy the project. It is required for automated deploys. You should commit it to git to make it available to GitHub Actions. (If you have configured a source root besides <code>docs/</code>, the file will be placed there instead.)</div>
29
+
<divclass="note">The deploy command creates a file at <code>docs/.observablehq/deploy.json</code> with information on where to deploy the project. This file is required for automated deploys. You will need to commit this file to git to deploy via GitHub Actions. (If you have configured a source root besides <code>docs</code>, the file will be placed there instead.)</div>
24
30
25
-
## Automated deploys to Observable
31
+
## Automated deploys
26
32
27
-
To set up automatic deploys, we’ll be using [GitHub actions](https://github.com/features/actions). In your git repository, create and commit a file at `.github/workflows/deploy.yml`. Here is a starting example:
33
+
To set up automatic deploys (also known as *continuous deployment* or *CD*), we recommend [GitHub Actions](https://github.com/features/actions). In your git repository, create and commit a file at `.github/workflows/deploy.yml`. Here is a starting example:
28
34
29
35
```yaml
30
36
name: Deploy
37
+
31
38
on:
32
39
# Run this workflow whenever a new commit is pushed to main.
33
40
push: {branches: [main]}
34
41
# Run this workflow once per day, at 10:15 UTC
35
42
schedule: [{cron: "15 10 * * *"}]
36
-
# Run this workflow when triggered manually in GitHub's UI.
43
+
# Run this workflow when triggered manually in GitHub’s UI.
37
44
workflow_dispatch: {}
45
+
38
46
jobs:
39
47
deploy:
40
48
runs-on: ubuntu-latest
@@ -54,15 +62,39 @@ jobs:
54
62
OBSERVABLE_TOKEN: ${{ secrets.OBSERVABLE_TOKEN }}
55
63
```
56
64
57
-
When deploying automatically, you won’t be able to login with a browser the way you did for manual deploys. Instead, you will authenticate via the environment variable `OBSERVABLE_TOKEN`, using an API key from Observable.
65
+
When deploying automatically, you can’t sign-in in your browser the way you did for manual deploys; instead, your GitHub action will authenticate using an Observable API key (also known as a *token* and referred to as `OBSERVABLE_TOKEN` above).
66
+
67
+
To create an API key:
68
+
69
+
1. Go to [observablehq.com](https://observablehq.com).
70
+
2. In the left sidebar, click **Settings**.
71
+
3. In the right sidebar, click **API / Notebook Keys**.
72
+
4. Click **New API Key**.
73
+
5. Check the **Deploy new versions of projects** checkbox.
74
+
6. Give your key a description, such as “Deploy via GitHub Actions”.
75
+
7. Click **Create API Key**.
58
76
59
-
To create a token, go to https://observablehq.com and open your workspace settings. Choose “API keys”. From there, create a new key, and assign it the "Deploy new versions of projects" scope.
77
+
<div class="caution">
60
78
61
-
That token is the equivalent of a password giving write access to your hosted project. **Do not commit it to git** (and, if it is exposed in any way, take a minute to revoke it and create a new one instead—or contact support).
79
+
The token you create is the equivalent of a password giving write access to your hosted project. **Do not commit it to git** or share it with anyone you don’t trust. If you accidentally expose your key, you can go back to your settings to immediately revoke it (and create a new key).
62
80
63
-
To pass this information securely to the Github action (so it can effectively be authorized to deploy the project to Observable), we’ll use GitHub secrets. Sign in to the settings of your GitHub account, and add a secret named `OBSERVABLE_TOKEN`. See [GitHub’s documentation](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) for more information about secrets.
81
+
</div>
64
82
65
-
This `deploy.yml` will automatically build and deploy your project once per day (to keep your data up-to-date), as well as whenever you push a new version of the code to your repository (so you can make changes at any time).
83
+
In a moment, you’ll copy-paste your new Observable API key, so leave this window open for now. (If you accidentally close the window, you can delete the old key and create a new one. For security, API keys are only shown once upon creation.)
84
+
85
+
To authenticate with Observable and to access the Observable API key securely from our Github action, we’ll use a [GitHub secret](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
86
+
87
+
To create a GitHub secret, in a new window:
88
+
89
+
1. Go to your GitHub repository.
90
+
2. In the top navigation, click **Settings**.
91
+
3. In the left sidebar, click **Secrets and variables**, then **Actions**.
92
+
4. Click **New repository secret**.
93
+
5. In the **Name** field, enter `OBSERVABLE_TOKEN`.
94
+
6. In the **Secret** field, paste the API key you created on Observable.
95
+
7. Click **Add secret**.
96
+
97
+
After you’ve performed these steps, the `deploy.yml` above will automatically build and deploy your project once per day (to keep your data up-to-date), as well as whenever you push a new version of the code to your repository (so you can make changes at any time).
66
98
67
99
### Caching
68
100
@@ -85,16 +117,22 @@ jobs:
85
117
# ...
86
118
```
87
119
88
-
This uses one cache per calendar day (in the “America/Los_Angeles” time zone). If you deploy multiple times in a day, the results of your data loaders will be reused on the second and subsequent runs. You can customize the `date` and `cache-data` steps to change the cadence of the caching. For example you could use `date +'%Y-%U'` to cache data for a week or `date +'%Y-%m-%dT%H` to cache it for only an hour.
120
+
This uses one cache per calendar day (in the `America/Los_Angeles` time zone). If you deploy multiple times in a day, the results of your data loaders will be reused on the second and subsequent runs. You can customize the `date` and `cache-data` steps to change the cadence of the caching. For example you could use `date +'%Y-%U'` to cache data for a week or `date +'%Y-%m-%dT%H` to cache it for only an hour.
89
121
90
-
<div class="note">You’ll need to change the paths used in this config if <code>observablehq.config.js</code> points to a different <code>root</code>.</div>
122
+
<div class="note">You’ll need to edit the paths above if you’ve configured a source root other than <code>docs</code>.</div>
91
123
92
-
## Deploying to other services
124
+
## Other hosting services
93
125
94
-
The output of Observable Framework is set of static files that can be hosted by many services. To build a hostable copy of your project, run:
126
+
Observable Framework builds a set of static files that can be hosted by any static site hosting services. To build your project, run:
95
127
96
128
```sh
97
-
$ npm run build
129
+
npm run build
98
130
```
99
131
100
-
Then you can upload the contents of your `dist/` directory to your static webhost of choice. Some webhosts may need the `cleanUrls` option <a href="https://github.com/observablehq/framework/releases/tag/v1.3.0" target="_blank" class="observablehq-version-badge" data-version="^1.3.0" title="Added in v1.3.0"></a> set to false in your project configuration file. For details and other options, see [configuration](./config).
132
+
Then upload the contents of your `dist` directory to your static service of choice.
133
+
134
+
<div class="tip">By default, Framework generates “clean” URLs by dropping the `.html` extension from page links. Not all webhosts support this; some need the <a href="./config#cleanUrls"><b>cleanUrls</b> config option</a> set to false.</div>
135
+
136
+
<div class="tip">When deploying to GitHub Pages without using GitHub’s related actions (<a href="https://github.com/actions/configure-pages">configure-pages</a>,
137
+
<a href="https://github.com/actions/deploy-pages">deploy-pages</a>, and
138
+
<a href="https://github.com/actions/upload-pages-artifact">upload-pages-artifact</a>), you may need to create a <code>.nojekyll</code> file in your <code>dist</code> folder after building. See GitHub’s documentation on <a href="https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages#static-site-generators">static site generators</a> for more.</div>
Copy file name to clipboardExpand all lines: docs/getting-started.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -209,7 +209,7 @@ Next, `cd` into your new project folder.
209
209
210
210
Framework’s local development server lets you preview your site in the browser as you make rapid changes. The preview server generates pages on-the-fly: as you edit files in your editor, changes are instantly streamed to your browser.
211
211
212
-
<divclass="tip">You can work offline with the preview server, but you must be connected to the internet to <ahref="./javascript/imports">import libraries</a> from npm. In the future, we intend to support self-hosting imported libraries; please upvote <ahref="https://github.com/observablehq/framework/issues/20">#20</a> and <ahref="https://github.com/observablehq/framework/issues/360">#360</a> if you are interested in this feature.</div>
212
+
<divclass="tip">You can develop offline, but you must connect to the internet to <ahref="./javascript/imports">import new libraries</a> from npm. Framework self-hosts imports: modules are downloaded from npm and stored in a local cache the first time you import them, and are included in <code>dist</code> when you build your project. In the future, we also plan to support importing from <code>node_modules</code>; please upvote <ahref="https://github.com/observablehq/framework/issues/360">#360</a> if you are interested in this feature.</div>
The `FileAttachment` function takes a path and returns a file handle. This handle exposes the file’s name and [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types).
13
+
The `FileAttachment` function takes a path and returns a file handle. This handle exposes the file’s name, [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types), and last modification date as the number of milliseconds since UNIX epoch.
14
14
15
15
```js echo
16
16
FileAttachment("volcano.json")
@@ -32,7 +32,7 @@ volcano
32
32
33
33
### Static analysis
34
34
35
-
The `FileAttachment` function can _only_ be passed a static string literal; constructing a dynamic path such as `FileAttachment("my" + "file.csv")` is invalid syntax. Static analysis is used to invoke [data loaders](../loaders) at build time, and ensures that only referenced files are included in the generated output during build. In the future [#260](https://github.com/observablehq/framework/issues/260), it will also allow content hashes for cache breaking during deploy.
35
+
The `FileAttachment` function can _only_ be passed a static string literal; constructing a dynamic path such as `FileAttachment("my" + "file.csv")` is invalid syntax. Static analysis is used to invoke [data loaders](../loaders) at build time, and ensures that only referenced files are included in the generated output during build. This also allows a content hash in the file name for cache breaking during deploy.
36
36
37
37
If you have multiple files, you can enumerate them explicitly like so:
38
38
@@ -52,6 +52,8 @@ const frames = [
52
52
53
53
None of the files in `frames` above are loaded until a [content method](#supported-formats) is invoked, for example by saying `frames[0].image()`.
54
54
55
+
For missing files, `file.lastModified` is undefined. The `file.mimeType` is determined by checking the file extension against the [`mime-db` media type database](https://github.com/jshttp/mime-db); it defaults to `application/octet-stream`.
56
+
55
57
## Supported formats
56
58
57
59
`FileAttachment` supports a variety of methods for loading file contents:
<div class="note">We’d also like to download imported modules from the CDN during build, making the built site entirely self-contained; see <a href="https://github.com/observablehq/framework/issues/20">#20</a>. This would further enable subresource integrity hashes; see <a href="https://github.com/observablehq/framework/issues/306">#306</a>.</div>
111
+
<div class="note">Framework automatically downloads <code>npm:</code> imports from npm during preview and build, making the built site entirely self-contained. If you prefer not to self-host a module, and instead load it from an external server at runtime, import a full URL instead of using the <code>npm:</code> protocol.</div>
Copy file name to clipboardExpand all lines: docs/routing.md
+8-8Lines changed: 8 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -157,14 +157,14 @@ The resulting output root is:
157
157
.
158
158
├─ dist
159
159
│ ├─ _import
160
-
│ │ └─ chart.js
160
+
│ │ └─ chart.c79c2048.js
161
161
│ ├─ _observablehq
162
162
│ │ └─ ... # additional assets for serving the site
163
163
│ └─ index.html
164
164
└─ ...
165
165
```
166
166
167
-
The import declaration is automatically rewritten during build to point to `./_import/chart.js` instead of `./chart.js`. (In the future [#260](https://github.com/observablehq/framework/issues/260), Observable Framework will add a content hash to the imported module name for cache-breaking.)
167
+
The import declaration is automatically rewritten during build to point to `./_import/chart.c79c2048.js` instead of `./chart.js`. The content hash `c79c2048` ensures cache-breaking during deploy, and allows assets to be marked as `cache-control: immutable` to improve performance.
168
168
169
169
Use a leading slash to denote paths relative to the source root, such as `/chart.js` instead of `./chart.js`. This allows you to use the same path to import a module from anywhere, even in nested folders. Observable Framework always generates relative links so that the generated site can be served under a base path.
170
170
@@ -186,18 +186,18 @@ Any files referenced by `FileAttachment` will automatically be copied to the `_f
186
186
.
187
187
├─ dist
188
188
│ ├─ _file
189
-
│ │ └─ quakes.csv
189
+
│ │ └─ quakes.e5f2eb94.csv
190
190
│ ├─ _observablehq
191
191
│ │ └─ ... # additional assets for serving the site
192
192
│ └─ index.html
193
193
└─ ...
194
194
```
195
195
196
-
`FileAttachment` references are automatically rewritten during build; for example, a reference to `quakes.csv` might be replaced with `_file/quakes.csv`. (In the future [#260](https://github.com/observablehq/framework/issues/260), Observable Framework will add a content hash to the attached file name for cache-breaking.) Only the files you reference statically are copied to the output root (`dist`), so nothing extra or unused is included in the built site.
196
+
`FileAttachment` references are automatically rewritten during build; for example, a reference to `quakes.csv` might be replaced with `_file/quakes.e5f2eb94.csv`. (As with imports, file names are given a content hash, here `e5f2eb94`, to improve performance.) Only the files you reference statically are copied to the output root (`dist`), so nothing extra or unused is included in the built site.
197
197
198
198
[Imported modules](#imports) can use `FileAttachment`, too. In this case, the path to the file is _relative to the importing module_ in the same fashion as `import`; this is accomplished by resolving relative paths at runtime with [`import.meta.url`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta).
199
199
200
-
Some additional assets are automatically promoted to file attachments and copied to `_file`. For example, if you have a `<link rel="stylesheet" href="style.css">` declared statically in a Markdown page, the `style.css` file will be copied to `_file`, too. The HTML elements eligible for file attachments are `audio`, `img`, `link`, `picture`, and `video`.
200
+
Some additional assets are automatically promoted to file attachments and copied to `_file`. For example, if you have a `<link rel="stylesheet" href="style.css">` declared statically in a Markdown page, the `style.css` file will be copied to `_file`, too (and the file name given a content hash). The HTML elements eligible for file attachments are `audio`, `img`, `link`, `picture`, and `video`.
201
201
202
202
## Data loaders
203
203
@@ -223,7 +223,7 @@ This will produce the following output root:
223
223
.
224
224
├─ dist
225
225
│ ├─ _file
226
-
│ │ └─ quakes.json
226
+
│ │ └─ quakes.99da78d9.json
227
227
│ ├─ _observablehq
228
228
│ │ └─ ... # additional assets for serving the site
229
229
│ └─ index.html
@@ -240,7 +240,7 @@ File attachments can be also be pulled from archives. The following archive exte
240
240
-`.tar` - for [tarballs](<https://en.wikipedia.org/wiki/Tar_(computing)>)
241
241
-`.tar.gz` and `.tgz` - for [compressed tarballs](https://en.wikipedia.org/wiki/Gzip)
242
242
243
-
For example, say you have a `quakes.zip` archive that includes yearly files for observed earthquakes. If you reference `FileAttachment("quakes/2021.csv")` in code, Observable Framework will pull the `2021.csv` from `quakes.zip`. So this source root:
243
+
For example, say you have a `quakes.zip` archive that includes yearly files for observed earthquakes. If you reference `FileAttachment("quakes/2021.csv")`, Framework will pull the `2021.csv` from `quakes.zip`. So this source root:
244
244
245
245
```ini
246
246
.
@@ -257,7 +257,7 @@ Becomes this output:
257
257
├─ dist
258
258
│ ├─ _file
259
259
│ │ └─ quakes
260
-
│ │ └─ 2021.csv
260
+
│ │ └─ 2021.e5f2eb94.csv
261
261
│ ├─ _observablehq
262
262
│ │ └─ ... # additional assets for serving the site
0 commit comments