Skip to content

Commit 414ce00

Browse files
lwshangclaude
andauthored
feat(static-site): publish v0.3.0 (#31)
Publishes the `static-site` recipe at v0.3.0, pinning the canister and sync-plugin wasm from dfinity/certified-assets's v0.3.0 release. The committed `recipe.hbs` is the asset attached to that release, verbatim — verify it matches: https://github.com/dfinity/certified-assets/releases/download/v0.3.0/recipe.hbs After merge, tag `static-site-v0.3.0` in this repo to cut the recipe release. --- ### Also included: one-time registry registration for a brand-new recipe `static-site` is new to this registry, so beyond the recipe files this PR also: - **Adds the `static-site-v*` trigger** to `.github/workflows/release-recipe.yml`. Without it, tagging `static-site-v0.3.0` after merge would not fire `release-recipe.yml`, so no recipe release would be cut. - **Lists `@dfinity/static-site`** in the root `README.md` (Available Recipes table, naming-convention list, and releases links) for discoverability. After merge, tag `static-site-v0.3.0` to cut the recipe release. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8dda3d0 commit 414ce00

4 files changed

Lines changed: 191 additions & 0 deletions

File tree

.github/workflows/release-recipe.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
- "motoko-v*"
88
- "asset-canister-v*"
99
- "prebuilt-v*"
10+
- "static-site-v*"
1011

1112
permissions:
1213
contents: write

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Official build recipe templates for Internet Computer (ICP) canisters. Recipes p
1212
| [**Motoko**](recipes/motoko/README.md) | Compile Motoko source code using the moc compiler |
1313
| [**Pre-built**](recipes/prebuilt/README.md) | Use pre-compiled WASM files with metadata injection |
1414
| [**Asset Canister**](recipes/asset-canister/README.md) | Deploy the official IC assets canister for frontend apps |
15+
| [**Static Site**](recipes/static-site/README.md) | Deploy a static frontend to a certified assets canister, with sync handled for you |
1516

1617
## Quick Start
1718

@@ -36,6 +37,7 @@ Recipes follow the `@dfinity/<recipe-name>@<version>` naming pattern:
3637
- `@dfinity/motoko@<version>` - Motoko canister recipe
3738
- `@dfinity/pre-built@<version>` - Pre-built WASM recipe
3839
- `@dfinity/asset-canister@<version>` - Asset canister recipe
40+
- `@dfinity/static-site@<version>` - Static site (certified assets) recipe
3941

4042
### Using Specific Versions
4143

@@ -69,6 +71,7 @@ Each recipe is versioned independently. View release history by recipe type:
6971
- [Motoko releases](https://github.com/dfinity/icp-cli-recipes/releases?q=motoko&expanded=true)
7072
- [Pre-built releases](https://github.com/dfinity/icp-cli-recipes/releases?q=prebuilt&expanded=true)
7173
- [Asset Canister releases](https://github.com/dfinity/icp-cli-recipes/releases?q=asset-canister&expanded=true)
74+
- [Static Site releases](https://github.com/dfinity/icp-cli-recipes/releases?q=static-site&expanded=true)
7275

7376
Releases follow semantic versioning and include auto-generated changelogs.
7477

recipes/static-site/README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Static Site Recipe
2+
3+
Deploy a static frontend to the [`dfinity/certified-assets`](https://github.com/dfinity/certified-assets) canister, with response certification and asset synchronization handled for you.
4+
5+
Each released version of this recipe pins a **matched pair** of the certified-assets canister wasm and its sync plugin. The two must share the same version, so — unlike a generic pre-built recipe — there is no user-selectable canister `version`; choose it via the recipe version in the `type` field instead.
6+
7+
## Usage
8+
9+
Reference this recipe in an `icp.yaml` (or `canister.yaml`) file:
10+
11+
```yaml
12+
canisters:
13+
- name: frontend
14+
recipe:
15+
type: "@dfinity/static-site@<version>"
16+
configuration:
17+
dir: dist
18+
```
19+
20+
> Replace `<version>` with a release version (e.g. `v1.0.0`). See [available versions](https://github.com/dfinity/icp-cli-recipes/releases?q=static-site&expanded=true).
21+
22+
## Configuration Parameters
23+
24+
| Parameter | Type | Required | Description | Default |
25+
|-----------|------|----------|-------------|---------|
26+
| dir | string | Yes | The single directory of built assets to synchronize to the canister | - |
27+
| build | array | No | Shell commands run before sync to produce the asset directory (e.g. `npm run build`) | [] |
28+
| presync | array | No | Shell commands run at sync time (after the canister exists), with the deployed canister IDs in the environment — see [Pre-sync environment](#pre-sync-environment) | [] |
29+
| metadata | array | No | Name/value pairs injected into the canister wasm via `ic-wasm` | [] |
30+
31+
> The sync plugin owns the canister's full URL space and accepts **exactly one** asset directory, so `dir` is a single string rather than a list.
32+
33+
## Prerequisites
34+
35+
- The asset directory must already exist or be produced by the `build` commands.
36+
- Internet connection to download the pinned canister and plugin wasm.
37+
- `ic-wasm` (bundled with icp-cli) — only required when using the `metadata` option.
38+
39+
> **Note:** If you followed the [icp-cli installation guide](https://github.com/dfinity/icp-cli#installation), `ic-wasm` is already installed.
40+
41+
## Examples
42+
43+
### Basic
44+
45+
```yaml
46+
canisters:
47+
- name: website
48+
recipe:
49+
type: "@dfinity/static-site@<version>"
50+
configuration:
51+
dir: build
52+
```
53+
54+
### With a build step and metadata
55+
56+
```yaml
57+
canisters:
58+
- name: spa-frontend
59+
recipe:
60+
type: "@dfinity/static-site@<version>"
61+
configuration:
62+
build:
63+
- npm ci
64+
- npm run build
65+
dir: dist
66+
metadata:
67+
- name: "frontend:framework"
68+
value: "react"
69+
```
70+
71+
### With a pre-sync build that needs canister IDs
72+
73+
Build in `presync` rather than `build` when the frontend must embed a canister
74+
ID — those IDs only exist once the canister is created, which is *after* `build`
75+
runs:
76+
77+
```yaml
78+
canisters:
79+
- name: frontend
80+
recipe:
81+
type: "@dfinity/static-site@<version>"
82+
configuration:
83+
dir: dist
84+
presync:
85+
- npm ci
86+
# `$ICP_CLI_CID_BACKEND` is the `backend` canister's principal.
87+
- VITE_CANISTER_ID_BACKEND=$ICP_CLI_CID_BACKEND npm run build
88+
```
89+
90+
## Build Process
91+
92+
When this recipe runs:
93+
94+
1. (If `build` is set) runs your build commands to produce the asset directory. This runs *before* the canister exists, so no canister IDs are available yet.
95+
2. Downloads the pinned certified-assets canister wasm (verified against its `sha256`).
96+
3. (If `metadata` is set) injects each name/value pair into the wasm with `ic-wasm`.
97+
4. Installs the canister.
98+
5. (If `presync` is set) runs your pre-sync commands — the canister IDs now exist and are exported as environment variables (see [Pre-sync environment](#pre-sync-environment)).
99+
6. Runs the pinned sync plugin to upload and certify the assets in `dir`.
100+
101+
## Pre-sync environment
102+
103+
`presync` commands run via `sh -c` in your project directory, after the canister
104+
is created but before its assets upload. Unlike `build` (which runs earlier, when
105+
only `ICP_WASM_OUTPUT_PATH` is available), `presync` sees the deployed canister IDs:
106+
107+
| Variable | Value |
108+
|----------|-------|
109+
| `ICP_CLI_CID` | This (frontend) canister's principal. |
110+
| `ICP_CLI_CID_<NAME>` | Each project canister's principal, keyed by its upper-cased name with non-alphanumeric characters replaced by `_` (e.g. `backend` → `ICP_CLI_CID_BACKEND`). |
111+
| `ICP_CLI_NETWORK` | The target network name. |
112+
| `ICP_CLI_ENVIRONMENT` | The target environment name. |
113+
114+
This is what lets a client-side app (Vite, Next static export, etc.) embed the
115+
canister IDs it will call, at build time.
116+
117+
## Asset Synchronization
118+
119+
The sync plugin diffs your local directory against the canister and uploads only what changed. It serves:
120+
121+
- **Static files** — HTML, CSS, JS, images, fonts, etc., with response certification.
122+
- **Content encoding** — gzip/Brotli negotiation per request.
123+
- **Redirects & headers** — driven by `_redirects` / `_headers` files in the asset directory.
124+
- **404 handling** — a certified fallback plus your own `/404.html` if present.
125+
126+
## Common Issues
127+
128+
**Version mismatch between plugin and canister** — re-deploy with the same recipe version so the canister and plugin are the matched pair this recipe pins.
129+
130+
**Assets directory not found** — ensure the directory in `dir` exists or is produced by your `build` commands.
131+
132+
**`ic-wasm` not found** — only the `metadata` option needs it; install it or drop the `metadata` config.
133+
134+
## Related Recipes
135+
136+
- [Pre-built Recipe](../prebuilt/README.md) — for arbitrary pre-compiled wasm.
137+
- [Rust Recipe](../rust/README.md) — for backend Rust canisters.
138+
- [Motoko Recipe](../motoko/README.md) — for backend Motoko canisters.
139+
140+
## Release History
141+
142+
See the [release history](https://github.com/dfinity/icp-cli-recipes/releases?q=static-site&expanded=true) for changelogs and version updates.

recipes/static-site/recipe.hbs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{{! Deploy static assets to the dfinity/certified-assets canister. }}
2+
{{! `dir: string` Required. The single directory of built assets to synchronize. }}
3+
{{! `build: [string]` Optional. Commands run before sync to produce the asset directory. }}
4+
{{! `presync: [string]` Optional. Commands run at sync time (after the canister exists), before assets upload, with the deployed canister IDs in the environment: ICP_CLI_CID, ICP_CLI_CID_<NAME>, ICP_CLI_NETWORK, ICP_CLI_ENVIRONMENT. }}
5+
{{! `metadata: [{name, value}]` Optional. Pairs injected into the canister wasm via ic-wasm. }}
6+
7+
build:
8+
steps:
9+
{{#if metadata}}
10+
- type: script
11+
commands:
12+
- sh -c 'command -v ic-wasm >/dev/null 2>&1 || { echo >&2 "ic-wasm not found. See https://github.com/dfinity/ic-wasm"; exit 1; }'
13+
{{/if}}
14+
{{#if build}}
15+
- type: script
16+
commands:
17+
{{#each build}}
18+
- {{ this }}
19+
{{/each}}
20+
{{/if}}
21+
- type: pre-built
22+
url: https://github.com/dfinity/certified-assets/releases/download/v0.3.0/canister-release.wasm.gz
23+
sha256: 9363c3f89d0eb9a2dec3111b1123d8ece17d4f76ae9d64e5605cfa0c3e63c427
24+
{{#if metadata}}
25+
- type: script
26+
commands:
27+
{{#each metadata}}
28+
- sh -c 'ic-wasm "$ICP_WASM_OUTPUT_PATH" -o "$ICP_WASM_OUTPUT_PATH" metadata "{{ name }}" -d "{{ value }}" --keep-name-section'
29+
{{/each}}
30+
{{/if}}
31+
32+
sync:
33+
steps:
34+
{{#if presync}}
35+
- type: script
36+
commands:
37+
{{#each presync}}
38+
- {{ this }}
39+
{{/each}}
40+
{{/if}}
41+
- type: plugin
42+
url: https://github.com/dfinity/certified-assets/releases/download/v0.3.0/plugin-release.wasm
43+
sha256: b0985ced2ff8c8e74f8a78ba5ae1c77122bab4afddd7d7f77e89d8e86eb872ff
44+
dirs:
45+
- {{ dir }}

0 commit comments

Comments
 (0)