diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8294309..7e87c04 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,4 +1,4 @@ -name: Publish examples +name: Publish recipes on: pull_request: @@ -20,7 +20,7 @@ on: workflow_dispatch: inputs: only: - description: "Publish only this example slug (optional)" + description: "Publish only this recipe slug (optional)" required: false permissions: @@ -38,7 +38,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - - run: bun scripts/build-manifest.mjs + - run: bun test scripts/catalog.test.mjs - uses: actions/configure-pages@v5 if: github.event_name != 'pull_request' - uses: actions/upload-pages-artifact@v3 diff --git a/README.md b/README.md index 6b3034c..511e5ac 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# Spacefast Examples +# Spacefast Recipes -Forty-seven real, buildable example websites — a band site, a calorie tracker, a -playable game, a restaurant menu, an internal sales dashboard, and more. Each one -is self-contained and ships with the exact prompt that produces it. +Forty-eight polished, copy-paste recipes — for a band site, a calorie tracker, a +playable game, a restaurant menu, a technical plan, and more. Each recipe ships +with the live website its prompt produces. -Every example exists to answer one question: _given the prompt, can any AI agent -build this site and publish it to Spacefast?_ They also power the public gallery -at [spacefast.com/examples](https://spacefast.com/examples). +Every recipe exists to answer one question: _given the prompt, can any AI agent +build my version and publish it to Spacefast?_ They power the public recipe gallery +at [spacefast.com/recipes](https://spacefast.com/recipes). ## Layout @@ -19,41 +19,43 @@ examples/ README.md ← implementation notes and live link ``` -This repository is the canonical source for the gallery. Prompts and metadata +This historically named repository is the canonical source for Recipes. Prompts and metadata are compiled into a public JSON feed by GitHub Actions: -The Spacefast website and the badges on the live examples read that feed. Do not +The Spacefast website and the badges on live recipe outputs read that feed. Do not copy prompts or gallery metadata into another repository. ## The badge -Every published example loads the shared Spacefast badge. The panel is always +Every published recipe output loads the shared Spacefast badge. The panel is always open, and the shared script reads the current prompt from the canonical feed: ```html ``` -Do not vendor `badge.js` or embed a prompt in an example build. Keeping the badge -shared means a prompt or badge improvement reaches every example without another -47-site publish. +Do not vendor `badge.js` or embed a prompt in a recipe build. Keeping the badge +shared means a prompt or badge improvement reaches every output without another +site publish. The catalog intentionally retains the historical `data-example` +attribute until the production shared badge deploys `data-recipe` support; this keeps +new and already-published outputs functional throughout the rollout. ## Publishing GitHub Actions (`.github/workflows/publish.yml`) validates the full catalog, publishes the JSON feed to GitHub Pages, and rebuilds and publishes changed -examples to their existing Spacefast spaces. It authenticates with the -team-owned `SPACEFAST_DEPLOY_KEY` repository secret. Static examples are -published as-is; examples with a `package.json` are built first. +recipe outputs to their existing Spacefast spaces. It authenticates with the +team-owned `SPACEFAST_DEPLOY_KEY` repository secret. Static recipe outputs are +published as-is; recipes with a `package.json` are built first. -To add an example: copy `TEMPLATE.md` into `examples//prompt.md`, fill it in, +To add a recipe: copy `TEMPLATE.md` into `examples//prompt.md`, fill it in, drop the site in `examples//site/`, and add `meta.json` using -`meta.example.json` as the schema. Run `bun scripts/build-manifest.mjs` locally; -CI does the same validation and handles the rest. +`meta.example.json` as the schema. Run `bun test scripts/catalog.test.mjs` locally; +CI runs the same catalog and output validation and handles the rest. The directory slug is also the Spacefast space slug by default. If that hostname -is reserved or the example deliberately publishes elsewhere, add `publish_slug` -to `meta.json` and make `live_url` match it. The gallery route and badge continue +is reserved or the recipe deliberately publishes elsewhere, add `publish_slug` +to `meta.json` and make `live_url` match it. The recipe route and badge continue to use the directory slug. diff --git a/TEMPLATE.md b/TEMPLATE.md index 1e423de..7490170 100644 --- a/TEMPLATE.md +++ b/TEMPLATE.md @@ -68,7 +68,7 @@ account, install, or extra instructions needed:** **Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: -[direct agent/API publishing](https://spacefast.com/docs/agents) · -[files and folders](https://spacefast.com/docs/publishing) · -[claiming](https://spacefast.com/docs/anonymous-publish) · -[updates and rollback](https://spacefast.com/docs/rollback) +[agent setup](https://spacefast.com/setup) · +[files and folders](https://spacefast.com/help/publishing) · +[claiming](https://spacefast.com/help/anonymous-publish) · +[updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/2048/prompt.md b/examples/2048/prompt.md index 6dd1c24..c4e842b 100644 --- a/examples/2048/prompt.md +++ b/examples/2048/prompt.md @@ -56,4 +56,4 @@ Build me a **fully playable 2048 sliding-tile puzzle game** as a vanilla-JS app ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/app/prompt.md b/examples/app/prompt.md index 520aa7b..c207120 100644 --- a/examples/app/prompt.md +++ b/examples/app/prompt.md @@ -88,4 +88,4 @@ browser (no backend, no accounts, all state in `localStorage`). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/arcade/prompt.md b/examples/arcade/prompt.md index d752bca..1b25400 100644 --- a/examples/arcade/prompt.md +++ b/examples/arcade/prompt.md @@ -56,4 +56,4 @@ Build me a **website for my retro arcade bar, with a playable mini-game as the h ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/band/prompt.md b/examples/band/prompt.md index c222f3d..9b3765f 100644 --- a/examples/band/prompt.md +++ b/examples/band/prompt.md @@ -59,4 +59,4 @@ Build me a **bold, full-bleed one-page website for my band** as a vanilla-JS app ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/barber/prompt.md b/examples/barber/prompt.md index c3326df..fc6e7bd 100644 --- a/examples/barber/prompt.md +++ b/examples/barber/prompt.md @@ -70,4 +70,4 @@ build step, no framework — just `index.html`, `styles.css`, and a little `scri ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/blog/prompt.md b/examples/blog/prompt.md index 46b6a0b..1963d3a 100644 --- a/examples/blog/prompt.md +++ b/examples/blog/prompt.md @@ -79,4 +79,4 @@ feed (run `bun install && bun run build` at the end and confirm `dist/` exists). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/calories/prompt.md b/examples/calories/prompt.md index 9048324..fe2debe 100644 --- a/examples/calories/prompt.md +++ b/examples/calories/prompt.md @@ -80,4 +80,4 @@ everything in `localStorage` so my diary is still there when I come back. ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/changelog/prompt.md b/examples/changelog/prompt.md index 9ba7c0a..b22261f 100644 --- a/examples/changelog/prompt.md +++ b/examples/changelog/prompt.md @@ -81,4 +81,4 @@ and a `feed.xml`, no build step, no framework). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/cli/prompt.md b/examples/cli/prompt.md index 90a0888..a280e75 100644 --- a/examples/cli/prompt.md +++ b/examples/cli/prompt.md @@ -83,4 +83,4 @@ install command, a star badge, and syntax-highlighted code samples — as a smal ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/conference/prompt.md b/examples/conference/prompt.md index b2c24ee..5c9fc9d 100644 --- a/examples/conference/prompt.md +++ b/examples/conference/prompt.md @@ -76,4 +76,4 @@ conference** as an **Astro site** (static output, no SSR, no backend). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/dashboard/prompt.md b/examples/dashboard/prompt.md index 322ccbf..78cf89d 100644 --- a/examples/dashboard/prompt.md +++ b/examples/dashboard/prompt.md @@ -74,4 +74,4 @@ team pins to the office TV and glances at all day — as a self-contained static ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/deck/prompt.md b/examples/deck/prompt.md index 998b0ed..e0107f7 100644 --- a/examples/deck/prompt.md +++ b/examples/deck/prompt.md @@ -60,4 +60,4 @@ vanilla-JS app — a single `index.html` plus a small CSS and JS file, with ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/docs/prompt.md b/examples/docs/prompt.md index 9904c63..a996b6d 100644 --- a/examples/docs/prompt.md +++ b/examples/docs/prompt.md @@ -84,4 +84,4 @@ in the shared root layout so every page includes it): ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/foodtruck/prompt.md b/examples/foodtruck/prompt.md index df5e955..9f04554 100644 --- a/examples/foodtruck/prompt.md +++ b/examples/foodtruck/prompt.md @@ -54,4 +54,4 @@ Build me a **mobile-first website for my food truck whose centerpiece is a weekl ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/fundraiser/prompt.md b/examples/fundraiser/prompt.md index 74ef53f..13d6ba7 100644 --- a/examples/fundraiser/prompt.md +++ b/examples/fundraiser/prompt.md @@ -59,4 +59,4 @@ Build me a **one-page fundraising campaign site for a local cause** as a vanilla ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/game/prompt.md b/examples/game/prompt.md index 5526779..bfe53bd 100644 --- a/examples/game/prompt.md +++ b/examples/game/prompt.md @@ -54,4 +54,4 @@ Build me a **playable neon brick-breaker arcade game** (paddle, bouncing ball, d ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/garden/prompt.md b/examples/garden/prompt.md index 97ed0cc..42d5c7e 100644 --- a/examples/garden/prompt.md +++ b/examples/garden/prompt.md @@ -92,4 +92,4 @@ CSS with a touch of vanilla JavaScript (no build step, no framework — just an ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/generative-art/prompt.md b/examples/generative-art/prompt.md index 11798f9..6f62344 100644 --- a/examples/generative-art/prompt.md +++ b/examples/generative-art/prompt.md @@ -61,4 +61,4 @@ zero dependencies). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/habits/prompt.md b/examples/habits/prompt.md index f7c90ba..bbf02c7 100644 --- a/examples/habits/prompt.md +++ b/examples/habits/prompt.md @@ -55,4 +55,4 @@ Build me a **habit tracker with GitHub-style contribution heatmaps** as a **Vite ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/hackathon/prompt.md b/examples/hackathon/prompt.md index dff0d36..56f0efb 100644 --- a/examples/hackathon/prompt.md +++ b/examples/hackathon/prompt.md @@ -71,4 +71,4 @@ Build me an **energetic landing page for a student hackathon** as a vanilla-JS a ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/invitation/prompt.md b/examples/invitation/prompt.md index 16b1bae..9836e96 100644 --- a/examples/invitation/prompt.md +++ b/examples/invitation/prompt.md @@ -84,4 +84,4 @@ small components, no SSR adapter — that builds to static files with `astro bui ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/links/prompt.md b/examples/links/prompt.md index 8271991..8cf60da 100644 --- a/examples/links/prompt.md +++ b/examples/links/prompt.md @@ -56,4 +56,4 @@ self-contained HTML file with CSS (no build step, no framework). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/listing/prompt.md b/examples/listing/prompt.md index 6966fc7..178335d 100644 --- a/examples/listing/prompt.md +++ b/examples/listing/prompt.md @@ -77,4 +77,4 @@ Vite + React app. ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/memorial/prompt.md b/examples/memorial/prompt.md index 0296dc8..a41c266 100644 --- a/examples/memorial/prompt.md +++ b/examples/memorial/prompt.md @@ -57,4 +57,4 @@ plain HTML & CSS site (a single `index.html`, no framework and no build step). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/menu/prompt.md b/examples/menu/prompt.md index 87b92b1..02e0c32 100644 --- a/examples/menu/prompt.md +++ b/examples/menu/prompt.md @@ -77,4 +77,4 @@ with a touch of vanilla JavaScript (no build step, no framework — just an ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/newsletter/prompt.md b/examples/newsletter/prompt.md index 1b0a8db..5c84c3c 100644 --- a/examples/newsletter/prompt.md +++ b/examples/newsletter/prompt.md @@ -75,4 +75,4 @@ web pages with a prominent subscribe form. ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/notes/prompt.md b/examples/notes/prompt.md index 4ed078c..baf46d5 100644 --- a/examples/notes/prompt.md +++ b/examples/notes/prompt.md @@ -81,4 +81,4 @@ content collections, `astro build` to static HTML — no server, no database). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/party/prompt.md b/examples/party/prompt.md index 11e45b5..32cda5a 100644 --- a/examples/party/prompt.md +++ b/examples/party/prompt.md @@ -57,4 +57,4 @@ just `astro build` to a `dist/` folder). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/photos/prompt.md b/examples/photos/prompt.md index f5bf219..c7435ed 100644 --- a/examples/photos/prompt.md +++ b/examples/photos/prompt.md @@ -71,4 +71,4 @@ small static **Astro site** (no SSR, no adapters — just `astro build`). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/portfolio/prompt.md b/examples/portfolio/prompt.md index 6127373..4bc3765 100644 --- a/examples/portfolio/prompt.md +++ b/examples/portfolio/prompt.md @@ -73,4 +73,4 @@ framework, no image files; draw every sprite procedurally on a ``). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/proposal/prompt.md b/examples/proposal/prompt.md index 4cfaa5c..06db814 100644 --- a/examples/proposal/prompt.md +++ b/examples/proposal/prompt.md @@ -84,4 +84,4 @@ page with scope, timeline, pricing tiers, and a working accept/sign button — a ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/qr/prompt.md b/examples/qr/prompt.md index 5632b71..bbf914a 100644 --- a/examples/qr/prompt.md +++ b/examples/qr/prompt.md @@ -88,4 +88,4 @@ JavaScript (a single `index.html` plus a CSS and JS file, no build step). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/recipes/prompt.md b/examples/recipes/prompt.md index e389fdd..c5cd1e4 100644 --- a/examples/recipes/prompt.md +++ b/examples/recipes/prompt.md @@ -55,4 +55,4 @@ Build me a **weeknight recipe blog with a filterable recipe index and printable, ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/report/prompt.md b/examples/report/prompt.md index 027a52e..eb3aeb1 100644 --- a/examples/report/prompt.md +++ b/examples/report/prompt.md @@ -78,4 +78,4 @@ and the Stack Overflow Developer Survey — as an **Astro site** (static, no SSR ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/resume/prompt.md b/examples/resume/prompt.md index 2d93088..a16e778 100644 --- a/examples/resume/prompt.md +++ b/examples/resume/prompt.md @@ -73,4 +73,4 @@ opens straight in a browser. ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/revenue-review/prompt.md b/examples/revenue-review/prompt.md index 6b4b4a9..ebe3bd1 100644 --- a/examples/revenue-review/prompt.md +++ b/examples/revenue-review/prompt.md @@ -77,4 +77,4 @@ forecast — as a **Vite + React app**. ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/roi/prompt.md b/examples/roi/prompt.md index 18e5767..2979ca7 100644 --- a/examples/roi/prompt.md +++ b/examples/roi/prompt.md @@ -73,4 +73,4 @@ framework and no build step). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/saas/prompt.md b/examples/saas/prompt.md index 83001a8..6e9a0a3 100644 --- a/examples/saas/prompt.md +++ b/examples/saas/prompt.md @@ -60,4 +60,4 @@ HTML/CSS). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/savings/prompt.md b/examples/savings/prompt.md index 297851f..4282a92 100644 --- a/examples/savings/prompt.md +++ b/examples/savings/prompt.md @@ -79,4 +79,4 @@ Build me a **savings-goal calculator** as a vanilla-JS app (a single static site ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/soon/prompt.md b/examples/soon/prompt.md index 663e1eb..e443424 100644 --- a/examples/soon/prompt.md +++ b/examples/soon/prompt.md @@ -74,4 +74,4 @@ Build me a **single-screen "coming soon" teaser page** as a vanilla-JS app ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/status/prompt.md b/examples/status/prompt.md index 677ec02..27d77fa 100644 --- a/examples/status/prompt.md +++ b/examples/status/prompt.md @@ -55,4 +55,4 @@ Build me a **public status page for my API / hosting product** — the kind of p ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/studio/prompt.md b/examples/studio/prompt.md index b72a7dc..19010f4 100644 --- a/examples/studio/prompt.md +++ b/examples/studio/prompt.md @@ -74,4 +74,4 @@ Build me a **portfolio site for my brand & web design studio** as a vanilla- ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/technical-plan/README.md b/examples/technical-plan/README.md new file mode 100644 index 0000000..df32aa2 --- /dev/null +++ b/examples/technical-plan/README.md @@ -0,0 +1,15 @@ +# Technical planning + +Northstar Sync is a decision-ready technical plan for adding offline-first project +sync to a collaborative field-operations product. The static site turns a realistic +engineering RFC into a readable planning artifact: executive recommendation, scope +boundaries, architecture and data flow, phased milestones, ranked risks, recorded +decisions, and owned open questions. + +The demo is plain HTML and CSS with no build step. Open `site/index.html` directly, +or serve `site/` with any static file server. It is responsive, keyboard-friendly, +and designed to print cleanly for an architecture review. See `prompt.md` to build +your own version from the recipe. + +The intended catalog URL is . This worktree does +not publish it. diff --git a/examples/technical-plan/meta.json b/examples/technical-plan/meta.json new file mode 100644 index 0000000..182d554 --- /dev/null +++ b/examples/technical-plan/meta.json @@ -0,0 +1,27 @@ +{ + "name": "Northstar Sync — Technical Plan", + "title": "Technical planning", + "slug": "technical-plan", + "vertical": "Data, internal & startup", + "tech": "Plain HTML & CSS", + "summary": "A decision-ready technical plan for a cross-platform offline sync initiative — problem and scope, system architecture, milestones, risks, decisions, and open questions.", + "order": 4, + "live_url": "https://technical-plan.view.fast/", + "setup_questions": [ + "What are you planning, who is it for, and what user or business problem should it solve?", + "What systems, teams, constraints, and non-negotiable requirements are already known?", + "What delivery window or milestone dates matter, and how should success be measured?", + "Which decisions are already made, and which questions still need an owner?" + ], + "photo_terms": [], + "sections": [ + "Executive readout with recommendation, confidence, owners, timing, and success measures", + "Problem statement, goals, non-goals, users, constraints, and scope boundaries", + "System architecture with components, data flow, trust boundaries, and operational notes", + "Phased milestones with exit criteria, dependencies, owners, and target dates", + "Ranked risk register with likelihood, impact, mitigations, triggers, and owners", + "Decision log with chosen options, rationale, consequences, and revisit conditions", + "Open questions with owners, due dates, and what each answer unblocks" + ], + "based_on": "A real engineering RFC and delivery plan prepared for a cross-functional architecture review, shaped into a readable website that executives, product partners, and implementers can use to make decisions." +} diff --git a/examples/technical-plan/prompt.md b/examples/technical-plan/prompt.md new file mode 100644 index 0000000..4866801 --- /dev/null +++ b/examples/technical-plan/prompt.md @@ -0,0 +1,103 @@ +Build me a **decision-ready technical plan website** — a clear, credible artifact a +team can use to agree on scope, architecture, delivery, risks, and unresolved +decisions — as a **plain HTML & CSS** site with no framework and no build step. + +**Before you build, ask me these questions in one message and wait for my answers. +If I skip anything, choose a sensible default and tell me what you chose:** + +1. What are we planning, who is it for, and what user or business problem should it solve? +2. What systems, teams, constraints, and non-negotiable requirements are already known? +3. What delivery window or milestone dates matter, and how should success be measured? +4. Which decisions are already made, and which questions still need an owner? + +**Then build a complete, polished, responsive plan with:** + +- An **executive readout**: a one-paragraph recommendation plus compact metadata for + status, owner, reviewers, target window, and confidence. Follow it with 3–4 + measurable success criteria. +- A precise **problem statement** and a scope section that separates goals, + non-goals, target users, constraints, assumptions, and explicit boundaries. +- A readable **architecture section**: system context, named components, data flow, + storage and trust boundaries, failure behavior, observability, and a diagram made + with semantic HTML/CSS or accessible inline SVG. Make every label consistent with + the prose. +- A phased **milestone plan** with target dates, owners, dependencies, concrete + deliverables, and exit criteria. Include discovery/prototyping, foundations, + rollout, and hardening rather than pretending everything ships at once. +- A ranked **risk register** with likelihood, impact, mitigation, trigger, and a + named owner for every risk. Include product, technical, security/privacy, and + delivery risks where relevant. +- A **decision log** that records the option chosen, alternatives considered, + rationale, consequences, and the condition that would justify revisiting it. +- An **open-questions queue** with an owner, due date, and a note on what each answer + unblocks. Distinguish real unknowns from decisions that have already been made. +- A short **review checklist** and next-step footer so a meeting can end with clear + actions instead of another round of vague comments. + +**Design & content notes:** + +- Treat it like a high-quality engineering RFC, not a marketing landing page: + restrained warm-neutral canvas, deep ink, one calm green accent, crisp typography, + subtle dividers, and generous whitespace. Use color for meaning, never decoration. +- Add a compact document navigation that stays useful on desktop and becomes a + touch-friendly, horizontally scrollable section index on small screens. +- Use internally consistent, realistic content based on my answers — never "lorem + ipsum." Pick one plausible product initiative and keep component names, dates, + owners, metrics, dependencies, and risks consistent across every section. +- Make the recommendation opinionated. Surface tradeoffs and rejected alternatives; + do not present every option as equally good. +- Use tables only where comparison matters (milestones and risks). Keep them + responsive without shrinking text below a readable size, and include captions and + proper row/column headers. +- Keep it accessible: semantic landmarks and headings, a skip link, visible keyboard + focus, descriptive link text, strong contrast, no color-only status signals, and a + print stylesheet that preserves the plan's structure. + +**Add this exact line right before `` so the site carries its badge:** + +```html + +``` + +**When the site is ready, publish it to Spacefast with the direct API — no account, +install, or extra instructions needed:** + +1. Use `./site` as the publish folder. Put only the finished public files there. + Confirm it has `index.html` at its root and no secrets, source-only files, `.git`, + or `.spacefast` state. +2. First publish: send every file as multipart form data. This Bash/Zsh block + preserves relative paths and works for one file or a whole folder: + ```bash + PUBLISH_ROOT=./site + publish_files=() + while IFS= read -r -d "" file; do + relative=${file#"$PUBLISH_ROOT"/} + publish_files+=(-F "files=@$file;filename=$relative") + done < <(find "$PUBLISH_ROOT" -type f -print0) + curl -sS "${publish_files[@]}" "https://api.spacefast.com/v1/publish?wait=1" + ``` +3. From the `{ "data": ... }` receipt, give me `data.space.liveUrl`, + `data.version.immutableUrl`, `data.claim.url`, and `data.claim.expiresAt`. + Remind me to claim within 6 hours. Keep `data.claim.token` secret. +4. Save `data.space.id` and `data.claim.token` locally (for example in an ignored, + mode-600 `.spacefast/state.json`). For an update, rebuild the `publish_files` + array and publish to the same space: + ```bash + SPACEFAST_SPACE_ID= + SPACEFAST_TOKEN= + curl -sS -H "Authorization: Bearer $SPACEFAST_TOKEN" \ + -F "spaceId=$SPACEFAST_SPACE_ID" "${publish_files[@]}" \ + "https://api.spacefast.com/v1/publish?wait=1" + ``` + If an update after claiming returns `space_claimed_credential_available`, + exchange the saved claim token once at + `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save + `data.credential.accessToken`, and retry with that access token. + +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, +`sf publish ./site --wait` does the same job. A zip of the publish folder is also +supported, but neither the CLI nor a zip is required. Docs: +[agent setup](https://spacefast.com/setup) · +[files and folders](https://spacefast.com/help/publishing) · +[claiming](https://spacefast.com/help/anonymous-publish) · +[updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/technical-plan/site/index.html b/examples/technical-plan/site/index.html new file mode 100644 index 0000000..f46ff35 --- /dev/null +++ b/examples/technical-plan/site/index.html @@ -0,0 +1,499 @@ + + + + + + + Northstar Sync — Technical Plan + + + + +
+ + +
+
+
+

Proposed · decision requested

+

Technical plan: offline project sync

+

+ Ship reliable offline capture for field teams without turning every client into a + distributed database. Use an append-only local queue, server-authoritative conflict + resolution, and a measured rollout behind workspace-level controls. +

+
+
+
+
Owner
+
Maya Chen, Staff Engineer
+
+
+
Reviewers
+
Mobile, API, Security, Support
+
+
+
Target
+
Private beta · 30 October 2026
+
+
+
Confidence
+
Medium
+
+
+
+ +
+

Recommendation

+

Approve the queue-and-replay architecture and phased beta plan.

+

+ It keeps the API authoritative, reuses our existing event log, and limits the first + release to task updates and inspection notes. Defer attachments and simultaneous + document editing until field telemetry proves the sync loop is stable. +

+
+ +
+

Success means the field app stays trustworthy.

+
+
+
99.9%
+
of queued mutations settle within 60 seconds of reconnecting
+
+
+
< 0.1%
+
of mutations require a person to resolve a conflict
+
+
+
72 hours
+
of fully offline work supported on a standard device
+
+
+
Zero
+
silent data-loss incidents during the private beta
+
+
+
+ +
+
+

01

+
+

Problem

+

Field work fails where connectivity is weakest—and recovery is invisible.

+
+
+
+
+

What users experience

+

+ Northstar’s inspection teams work in basements, utility corridors, and rural + facilities. Today, a dropped request looks like a saved task until the screen is + refreshed. Supervisors discover missing notes hours later, after the technician + has left the site. +

+
+
+

Why now

+

+ Offline reliability is the top blocker in 18 of 31 enterprise evaluations this + quarter. The mobile team also plans to replace its ad-hoc request cache in Q4; + doing both as one designed system avoids a second migration. +

+
+
+
+ +
+
+

02

+
+

Scope

+

The beta is deliberately narrow enough to observe and reverse.

+
+
+
+
+

In scope

+
    +
  • Create and update tasks, inspection notes, and status changes offline
  • +
  • Cache the last 30 days of assigned project data per device
  • +
  • Show pending, synced, conflicted, and failed states on every mutation
  • +
  • Remote disable, queue diagnostics, and workspace-level rollout controls
  • +
+
+
+

Not in this release

+
    +
  • Offline attachment uploads or media transcoding
  • +
  • Collaborative rich-text editing or peer-to-peer device sync
  • +
  • Full project export, billing changes, or account administration
  • +
  • Desktop web offline mode
  • +
+
+
+
+
+
Goals
+
Prevent silent data loss, make sync state visible, and preserve one server-authoritative project history.
+
+
+
Target users
+
Field technicians working through long connectivity gaps and supervisors reviewing their completed inspections.
+
+
+
Assumptions and boundaries
+
Devices reconnect within 72 hours; server APIs remain reachable after reconnect; attachments and rich-text collaboration stay out of beta.
+
+
+
Security
+
Encrypt queued payloads with a device-bound key and erase them on remote sign-out.
+
+
+
Compatibility
+
Support the current and previous two mobile releases during the beta.
+
+
+
Operations
+
No new stateful service in the critical path before general availability.
+
+
+
+ +
+
+

03

+
+

Architecture

+

Clients record intent locally; the existing API remains the source of truth.

+
+
+
+
+ Mutation flow from offline capture to authoritative project state. Dashed boundaries + indicate device-local components. +
+
    +
  1. + On device + Northstar mobile + Validates input and assigns an idempotency key. +
  2. +
  3. + Encrypted SQLite + Mutation queue + Stores ordered intent plus its base revision. +
  4. +
  5. + Existing service + Sync API + Authenticates, deduplicates, and applies policy. +
  6. +
  7. + System of record + Project event log + Appends accepted changes and emits canonical state. +
  8. +
+
+
+
+

Replay and ordering

+

+ A device replays one project queue at a time in creation order. Different projects + may sync concurrently, capped at three to protect battery and API capacity. +

+
+
+

Conflict policy

+

+ Status transitions use domain rules; scalar task fields use revision-aware + last-write-wins; note bodies fork visibly when both sides changed. +

+
+
+

Failure handling

+

+ Retry transient failures with jitter. Stop on authorization or validation errors, + preserve the draft, and show the user a specific recovery action. +

+
+
+

Observability

+

+ Record queue age, attempts, settle time, conflict class, and client version. Never + include note text or customer payloads in telemetry. +

+
+
+
+ +
+
+

04

+
+

Milestones

+

Each phase ends with evidence, not percentage-complete reporting.

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Delivery phases and exit criteria
PhaseTargetOwnerDeliverable and exit criterionDepends on
1 · Prove7 AugMayaReplay prototype passes airplane-mode and duplicate-request fault tests.Security key review
2 · Foundations4 SepIshanQueue, sync endpoint, telemetry, and remote kill switch work in staging.Event log capacity test
3 · Team pilot2 OctPriyaTwenty internal users complete a five-day scripted field trial with no lost intent.Support runbook
4 · Private beta30 OctJonFive design partners meet settle-time and conflict targets for two weeks.Partner agreements
5 · Harden4 DecMayaGo/no-go review has SLO evidence, rollback drill results, and a GA scope proposal.Beta telemetry
+
+
+ +
+
+

05

+
+

Risks

+

Ranked by current exposure after mitigation.

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Risk register
RiskLikelihoodImpactMitigation and triggerOwner
Conflict rules surprise usersLikelyHighTest with real work orders; pause rollout if manual resolution exceeds 0.1%.Priya
Queue payload exposed on a lost deviceUnlikelyCriticalDevice-bound encryption and remote wipe; block beta on failed key extraction test.Elena
Reconnect storm overloads the APIPossibleHighJitter, concurrency caps, and load test at 10× forecast before the team pilot.Ishan
Support cannot diagnose stuck workPossibleMediumRedacted queue diagnostics and a drill; delay beta if median diagnosis exceeds 15 minutes.Jon
Attachment demand expands scopeLikelyLowPublish the boundary in beta onboarding; revisit only after core SLOs hold for four weeks.Priya
+
+
+ +
+
+

06

+
+

Decisions

+

Recorded choices keep settled tradeoffs from reopening by accident.

+
+
+
    +
  1. +
    D-01 · Accepted
    +

    Keep the server authoritative

    +
    +
    Alternative
    Replicate project state and resolve it primarily on each client.
    +
    Rationale
    Queued commands fit current domain rules and operations skills.
    +
    Consequences
    The API stays authoritative; offline queries remain deliberately limited.
    +
    Revisit when
    Desktop and mobile both require multi-day offline editing.
    +
    +
  2. +
  3. +
    D-02 · Accepted
    +

    Use encrypted SQLite, not a custom log file

    +
    +
    Alternative
    Maintain a smaller custom append-only file format.
    +
    Rationale
    Transactions, migrations, and bounded queries matter more than binary size.
    +
    Consequences
    The client accepts modest storage and binary overhead for safer recovery.
    +
    Revisit when
    Measured storage overhead exceeds 15% on supported devices.
    +
    +
  4. +
  5. +
    D-03 · Accepted
    +

    Fork conflicting notes instead of merging text

    +
    +
    Alternative
    Automatically merge note bodies with CRDT or operational transforms.
    +
    Rationale
    A visible duplicate is safer than an invented merge for compliance records.
    +
    Consequences
    Users resolve rare forks explicitly; rich-text collaboration stays out of beta.
    +
    Revisit when
    A structured merge can demonstrate zero semantic loss in field trials.
    +
    +
  6. +
  7. +
    D-04 · Proposed
    +

    Gate rollout by workspace

    +
    +
    Alternative
    Gate by account, user cohort, or mobile application version.
    +
    Rationale
    Workspace controls align support, telemetry, and customer consent.
    +
    Consequences
    Phase 1 must freeze a workspace-control API and a minimal admin surface.
    +
    Revisit when
    Pilot telemetry shows workspace-level targeting is too coarse.
    +
    +
  8. +
+
+ +
+
+

07

+
+

Open questions

+

Every unknown has an owner, a date, and a decision it unblocks.

+
+
+
    +
  • +
    +

    How long may regulated customers retain encrypted offline notes?

    +

    Unblocks the queue retention default and remote-wipe policy.

    +
    +
    Owner
    Elena
    Due
    31 Jul
    +
  • +
  • +
    +

    Can beta partners exclude specific projects from device caching?

    +

    Unblocks workspace controls and partner onboarding copy.

    +
    +
    Owner
    Priya
    Due
    5 Aug
    +
  • +
  • +
    +

    What API headroom is reserved for reconnect traffic?

    +

    Unblocks concurrency caps and the Phase 2 capacity test.

    +
    +
    Owner
    Ishan
    Due
    7 Aug
    +
  • +
  • +
    +

    Which five partners represent the hardest connectivity conditions?

    +

    Unblocks the private-beta cohort and field test plan.

    +
    +
    Owner
    Jon
    Due
    14 Aug
    +
  • +
+
+ +
+
+

08

+
+

Review checklist

+

Close the review only when the plan is specific enough to execute and reverse.

+
+
+
    +
  • Scope, non-goals, target users, assumptions, and success measures are explicit.
  • +
  • Architecture labels match the prose, with failure behavior and trust boundaries named.
  • +
  • Every milestone has an owner, dependency, deliverable, and evidence-based exit criterion.
  • +
  • Every risk and open question has an owner, trigger or due date, and a clear unblock.
  • +
  • Accepted decisions record alternatives, consequences, and a condition for revisiting.
  • +
+
+ +
+
+

Review outcome requested

+

Approve the architecture, beta boundary, and Phase 1 staffing.

+
+
    +
  • Architecture Council records D-04 by 24 July.
  • +
  • Security closes the device-key review by 31 July.
  • +
  • Mobile and API begin the replay prototype on 27 July.
  • +
+
+
+
+ + + diff --git a/examples/technical-plan/site/styles.css b/examples/technical-plan/site/styles.css new file mode 100644 index 0000000..9036192 --- /dev/null +++ b/examples/technical-plan/site/styles.css @@ -0,0 +1,893 @@ +:root { + color-scheme: light; + --canvas: #f3f1ea; + --surface: #fbfaf6; + --ink: #1d2927; + --muted: #60706c; + --line: rgba(29, 41, 39, 0.14); + --accent: #1d6b5b; + --accent-soft: #dce9e3; + --warm: #a65136; + --radius: 12px; +} + +* { + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + margin: 0; + background: var(--canvas); + color: var(--ink); + font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font-size: 16px; + line-height: 1.65; + -webkit-font-smoothing: antialiased; +} + +a { + color: inherit; +} + +a:focus-visible, +[tabindex]:focus-visible { + outline: 3px solid var(--warm); + outline-offset: 3px; +} + +.skip-link { + position: fixed; + top: 12px; + left: 12px; + z-index: 20; + padding: 10px 14px; + border-radius: 6px; + background: var(--ink); + color: white; + transform: translateY(-180%); +} + +.skip-link:focus { + transform: translateY(0); +} + +.document-shell { + display: grid; + grid-template-columns: 268px minmax(0, 1fr); + max-width: 1320px; + min-height: 100vh; + margin: 0 auto; +} + +.document-sidebar { + position: sticky; + top: 0; + align-self: start; + min-width: 0; + height: 100vh; + padding: 36px 30px; + border-right: 1px solid var(--line); +} + +.document-mark { + display: grid; + width: 42px; + height: 42px; + place-items: center; + border-radius: 50%; + background: var(--ink); + color: var(--canvas); + font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; + font-size: 13px; + font-weight: 700; + letter-spacing: 0.08em; +} + +.document-identity { + display: grid; + gap: 3px; + padding: 20px 0 26px; + border-bottom: 1px solid var(--line); +} + +.eyebrow, +.document-title, +.document-version, +.sidebar-note, +.section-number { + margin: 0; +} + +.eyebrow, +.section-number { + color: var(--accent); + font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; + font-size: 12px; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.document-title { + font-size: 18px; + font-weight: 650; +} + +.document-version, +.sidebar-note { + color: var(--muted); + font-size: 13px; +} + +.document-sidebar nav { + display: grid; + gap: 2px; + padding: 22px 0; +} + +.document-sidebar nav a { + padding: 7px 9px; + border-radius: 6px; + color: var(--muted); + font-size: 14px; + text-decoration: none; +} + +.document-sidebar nav a:hover { + background: rgba(29, 107, 91, 0.08); + color: var(--ink); +} + +.sidebar-note { + max-width: 24ch; + padding-top: 20px; + border-top: 1px solid var(--line); +} + +main { + min-width: 0; + padding: 72px clamp(30px, 6vw, 88px) 120px; +} + +main > * { + max-width: 900px; + margin-right: auto; + margin-left: auto; +} + +.plan-header { + display: grid; + grid-template-columns: minmax(0, 1fr) 250px; + gap: 58px; + padding-bottom: 54px; + border-bottom: 1px solid var(--line); +} + +h1, +h2, +h3, +p { + text-wrap: pretty; +} + +h1, +h2, +h3 { + margin-top: 0; + font-weight: 650; + letter-spacing: -0.025em; + line-height: 1.16; + text-wrap: balance; +} + +h1 { + max-width: 19ch; + margin-bottom: 24px; + font-size: clamp(42px, 6vw, 70px); +} + +h2 { + font-size: clamp(27px, 3vw, 36px); +} + +h3 { + font-size: 18px; +} + +.lede { + max-width: 63ch; + margin: 0; + color: var(--muted); + font-size: 19px; + line-height: 1.65; +} + +.plan-meta { + display: grid; + align-content: start; + gap: 0; + margin: 4px 0 0; +} + +.plan-meta div { + padding: 13px 0; + border-top: 1px solid var(--line); +} + +.plan-meta div:last-child { + border-bottom: 1px solid var(--line); +} + +dt { + color: var(--ink); + font-weight: 650; +} + +dd { + margin: 2px 0 0; + color: var(--muted); +} + +.plan-meta dt { + font-size: 12px; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.plan-meta dd { + font-size: 14px; +} + +.status { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 2px 8px; + border-radius: 999px; + font-size: 13px; + font-weight: 650; +} + +.status::before { + width: 7px; + height: 7px; + border-radius: 50%; + background: currentColor; + content: ""; +} + +.status-high { + background: #f0d8d0; + color: #7b311f; +} + +.status-medium { + background: #eee2bb; + color: #685418; +} + +.status-low { + background: var(--accent-soft); + color: #175749; +} + +.decision-callout { + margin-top: 44px; + padding: 30px; + border-left: 4px solid var(--accent); + border-radius: 0 var(--radius) var(--radius) 0; + background: var(--accent-soft); +} + +.decision-callout h2 { + max-width: 30ch; + margin: 10px 0 14px; + font-size: clamp(25px, 3vw, 34px); +} + +.decision-callout > p:last-child { + max-width: 70ch; + margin: 0; +} + +.success-section { + padding: 72px 0 24px; +} + +.success-section > h2 { + max-width: 26ch; + margin-bottom: 32px; +} + +.success-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + margin: 0; +} + +.success-grid div { + min-width: 0; + padding: 0 18px; + border-left: 1px solid var(--line); +} + +.success-grid div:first-child { + padding-left: 0; + border-left: 0; +} + +.success-grid div:last-child { + padding-right: 0; +} + +.success-grid dt { + font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; + font-size: 23px; + font-variant-numeric: tabular-nums; +} + +.success-grid dd { + margin-top: 8px; + font-size: 14px; + line-height: 1.5; +} + +main > section[id] { + padding-top: 94px; +} + +.section-heading { + display: flex; + align-items: flex-start; + gap: 22px; + padding-bottom: 26px; + border-bottom: 1px solid var(--line); +} + +.section-number { + flex: 0 0 auto; + padding-top: 8px; +} + +.section-heading h2 { + margin-bottom: 8px; +} + +.section-heading p:last-child { + max-width: 56ch; + margin: 0; + color: var(--muted); +} + +.two-column, +.scope-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 46px; + padding-top: 34px; +} + +.two-column p { + margin-bottom: 0; + color: var(--muted); +} + +.scope-grid > div { + padding: 26px; + border: 1px solid var(--line); + border-radius: var(--radius); + background: rgba(251, 250, 246, 0.6); +} + +.scope-grid h3 { + margin-bottom: 18px; +} + +ul, +ol { + padding-left: 1.25rem; +} + +.scope-grid ul { + display: grid; + gap: 10px; + margin: 0; +} + +.scope-grid li::marker { + color: var(--accent); +} + +.constraints { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 28px; + margin: 34px 0 0; +} + +.constraints div { + padding-top: 18px; + border-top: 1px solid var(--line); +} + +.constraints dd { + margin-top: 7px; + font-size: 14px; +} + +.architecture-map { + margin: 34px 0 0; + padding: 28px; + border-radius: var(--radius); + background: var(--ink); + color: white; +} + +.architecture-map figcaption { + max-width: 66ch; + margin-bottom: 24px; + color: rgba(255, 255, 255, 0.68); + font-size: 14px; +} + +.architecture-flow { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 14px; + margin: 0; + padding: 0; + list-style: none; + counter-reset: flow; +} + +.architecture-flow li { + position: relative; + display: flex; + min-width: 0; + flex-direction: column; + gap: 7px; + padding: 18px; + border: 1px solid rgba(255, 255, 255, 0.18); + border-radius: 9px; + background: rgba(255, 255, 255, 0.06); + counter-increment: flow; +} + +.architecture-flow li:not(:last-child)::after { + position: absolute; + top: 50%; + right: -13px; + z-index: 2; + color: #87c6b7; + content: "→"; + font-weight: 700; + transform: translateY(-50%); +} + +.architecture-flow .device-boundary { + border-style: dashed; +} + +.architecture-flow strong { + font-size: 16px; +} + +.architecture-flow span:last-child { + color: rgba(255, 255, 255, 0.68); + font-size: 13px; + line-height: 1.5; +} + +.node-label { + color: #87c6b7; + font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; + font-size: 11px; + letter-spacing: 0.05em; + text-transform: uppercase; +} + +.architecture-notes { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0 38px; + padding-top: 26px; +} + +.architecture-notes article { + padding: 22px 0; + border-bottom: 1px solid var(--line); +} + +.architecture-notes h3, +.architecture-notes p { + margin-bottom: 0; +} + +.architecture-notes p { + color: var(--muted); +} + +.table-scroll { + margin-top: 30px; + overflow-x: auto; +} + +table { + width: 100%; + min-width: 760px; + border-collapse: collapse; + font-size: 14px; +} + +caption { + padding-bottom: 12px; + color: var(--muted); + font-size: 14px; + text-align: left; +} + +th, +td { + padding: 16px 14px; + border-bottom: 1px solid var(--line); + vertical-align: top; + text-align: left; +} + +th { + font-weight: 650; +} + +thead th { + color: var(--muted); + font-size: 12px; + letter-spacing: 0.03em; + white-space: nowrap; +} + +tbody th { + width: 17%; +} + +.decision-log { + display: grid; + gap: 0; + margin: 30px 0 0; + padding: 0; + list-style: none; +} + +.decision-log li { + display: grid; + grid-template-columns: 132px 220px minmax(0, 1fr); + gap: 24px; + padding: 24px 0; + border-bottom: 1px solid var(--line); +} + +.decision-log h3, +.decision-log dl { + margin: 0; +} + +.decision-log dl { + display: grid; + grid-template-columns: max-content minmax(0, 1fr); + gap: 5px 12px; + color: var(--muted); +} + +.decision-log dt { + color: var(--ink); + font-weight: 650; +} + +.decision-log dd { + margin: 0; +} + +.decision-id { + color: var(--accent); + font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; + font-size: 12px; + font-weight: 700; +} + +.question-list { + margin: 30px 0 0; + padding: 0; + list-style: none; +} + +.question-list > li { + display: grid; + grid-template-columns: minmax(0, 1fr) 190px; + gap: 30px; + padding: 24px 0; + border-bottom: 1px solid var(--line); +} + +.question-list h3, +.question-list p, +.question-list dl { + margin: 0; +} + +.question-list p { + margin-top: 7px; + color: var(--muted); +} + +.question-list dl { + display: grid; + grid-template-columns: auto 1fr; + align-content: start; + gap: 3px 12px; + font-size: 13px; +} + +.question-list dd { + margin: 0; +} + +.review-checklist { + display: grid; + gap: 12px; + margin: 30px 0 0; +} + +.review-checklist li::marker { + color: var(--accent); +} + +.plan-footer { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(300px, 0.8fr); + gap: 54px; + margin-top: 112px; + padding: 38px; + border-radius: var(--radius); + background: var(--accent-soft); +} + +.plan-footer h2 { + max-width: 24ch; + margin: 10px 0 0; + font-size: 28px; +} + +.plan-footer ul { + display: grid; + gap: 9px; + margin: 0; +} + +@media (max-width: 1040px) { + .document-shell { + grid-template-columns: 220px minmax(0, 1fr); + } + + .document-sidebar { + padding: 28px 20px; + } + + main { + padding-right: 40px; + padding-left: 40px; + } + + .plan-header { + grid-template-columns: 1fr; + gap: 30px; + } + + .plan-meta { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .plan-meta div:nth-child(odd) { + padding-right: 20px; + } + + .plan-meta div:nth-child(even) { + padding-left: 20px; + } + + .architecture-flow { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .architecture-flow li::after { + display: none; + } + + .decision-log li { + grid-template-columns: 110px 180px minmax(0, 1fr); + } +} + +@media (max-width: 760px) { + html { + scroll-padding-top: 148px; + } + + .document-shell { + display: block; + } + + .document-sidebar { + position: sticky; + top: 0; + z-index: 10; + display: grid; + height: auto; + padding: 12px 18px 0; + border-right: 0; + border-bottom: 1px solid var(--line); + background: rgba(243, 241, 234, 0.96); + backdrop-filter: blur(12px); + } + + .document-mark, + .document-version, + .sidebar-note { + display: none; + } + + .document-identity { + padding: 0; + border: 0; + } + + .document-title { + font-size: 16px; + } + + .document-sidebar nav { + display: flex; + gap: 4px; + margin: 7px -18px 0; + padding: 7px 18px 10px; + overflow-x: auto; + scrollbar-width: thin; + } + + .document-sidebar nav a { + flex: 0 0 auto; + min-height: 44px; + padding: 10px 12px; + font-size: 15px; + } + + main { + padding: 50px 20px 86px; + } + + h1 { + font-size: 43px; + } + + .lede { + font-size: 18px; + } + + .success-grid, + .constraints { + grid-template-columns: 1fr; + } + + .success-grid div, + .success-grid div:first-child, + .success-grid div:last-child { + padding: 16px 0; + border-top: 1px solid var(--line); + border-left: 0; + } + + .success-grid div:last-child { + border-bottom: 1px solid var(--line); + } + + .success-grid dd, + .constraints dd, + .architecture-map figcaption, + .architecture-flow span:last-child, + .plan-meta dd { + font-size: 16px; + } + + main > section[id] { + padding-top: 76px; + } + + .two-column, + .scope-grid, + .architecture-notes, + .architecture-flow, + .plan-footer { + grid-template-columns: 1fr; + } + + .two-column, + .scope-grid { + gap: 24px; + } + + .decision-log li { + grid-template-columns: 1fr; + gap: 8px; + } + + .question-list > li { + grid-template-columns: 1fr; + gap: 16px; + } + + .plan-footer { + gap: 28px; + padding: 26px; + } +} + +@media print { + body { + background: white; + color: black; + font-size: 11pt; + } + + .document-shell { + display: block; + max-width: none; + } + + .document-sidebar, + .skip-link, + script { + display: none; + } + + main { + padding: 0; + } + + main > section[id] { + break-inside: avoid; + padding-top: 42px; + } + + .plan-header { + grid-template-columns: 1fr 220px; + } + + .architecture-map { + border: 1px solid #333; + background: white; + color: black; + } + + .architecture-map figcaption, + .architecture-flow span:last-child { + color: #444; + } + + .architecture-flow li { + border-color: #888; + background: white; + } + + .node-label, + .architecture-flow li:not(:last-child)::after { + color: #333; + } +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } +} diff --git a/examples/tip/prompt.md b/examples/tip/prompt.md index 398356b..1fb7501 100644 --- a/examples/tip/prompt.md +++ b/examples/tip/prompt.md @@ -66,4 +66,4 @@ CSS and a JS file, no build step, no framework). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/word-game/prompt.md b/examples/word-game/prompt.md index 8cf179e..df3831e 100644 --- a/examples/word-game/prompt.md +++ b/examples/word-game/prompt.md @@ -75,4 +75,4 @@ no framework and no build step. ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/wp-astro/prompt.md b/examples/wp-astro/prompt.md index 76caacf..672e5db 100644 --- a/examples/wp-astro/prompt.md +++ b/examples/wp-astro/prompt.md @@ -55,4 +55,4 @@ Build me a **headless WordPress blog** as an **Astro site** that fetches posts f ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/wp-react/prompt.md b/examples/wp-react/prompt.md index ffe6024..350940f 100644 --- a/examples/wp-react/prompt.md +++ b/examples/wp-react/prompt.md @@ -82,4 +82,4 @@ fetches the content at runtime, no backend, no server-side rendering). ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./dist --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/examples/zine/prompt.md b/examples/zine/prompt.md index 3cb9238..8f0a4a4 100644 --- a/examples/zine/prompt.md +++ b/examples/zine/prompt.md @@ -67,4 +67,4 @@ unconventional, magazine-style spreads** as a **plain HTML & CSS** site (one ``` If an update after claiming returns `space_claimed_credential_available`, exchange the saved claim token once at `POST https://api.spacefast.com/v1/anonymous-claim/exchange`, save `data.credential.accessToken`, and retry with that access token. -**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/docs/agents) · [files and folders](https://spacefast.com/docs/publishing) · [claiming](https://spacefast.com/docs/anonymous-publish) · [updates and rollback](https://spacefast.com/docs/rollback) +**Optional shortcuts and reference only:** if the `sf` CLI is already installed, `sf publish ./site --wait` does the same job. A zip of the publish folder is also supported, but neither the CLI nor a zip is required. Docs: [direct agent/API publishing](https://spacefast.com/setup) · [files and folders](https://spacefast.com/help/publishing) · [claiming](https://spacefast.com/help/anonymous-publish) · [updates and rollback](https://spacefast.com/help/versions) diff --git a/meta.example.json b/meta.example.json index 791116f..2cf5bc9 100644 --- a/meta.example.json +++ b/meta.example.json @@ -1,15 +1,15 @@ { - "name": "The branded name shown on the detail page", + "name": "The branded recipe output name shown on the detail page", "title": "Short generic title used in compact lists", "slug": "example-slug", "vertical": "Personal & creative", "tech": "plain HTML", - "summary": "One sentence describing what the example builds.", + "summary": "One sentence describing what the recipe builds.", "order": 100, "live_url": "https://example-slug.view.fast/", "setup_questions": ["Question the agent asks before building"], "photo_terms": ["search terms for real images"], "sections": ["Hero", "Main content", "Footer"], - "based_on": "What real-world site or pattern inspired this example", + "based_on": "What real-world site or pattern inspired this recipe", "notes": "Optional implementation context for maintainers." } diff --git a/scripts/build-manifest.mjs b/scripts/build-manifest.mjs index d31b750..167cc81 100644 --- a/scripts/build-manifest.mjs +++ b/scripts/build-manifest.mjs @@ -38,7 +38,12 @@ for (const slug of slugs) { } if (!prompt) throw new Error(`${slug}/prompt.md: prompt must not be empty`); if (/^#\s/.test(prompt)) { - throw new Error(`${slug}/prompt.md: prompt must start with the request, not an example title`); + throw new Error(`${slug}/prompt.md: prompt must start with the request, not a recipe title`); + } + if (!prompt.includes(`data-example="${slug}"`)) { + throw new Error( + `${slug}/prompt.md: prompt must retain the deployment-safe data-example badge attribute`, + ); } const order = Number(meta.order); @@ -76,7 +81,7 @@ await mkdir(outputRoot, { recursive: true }); await Bun.write(path.join(outputRoot, "manifest.json"), `${JSON.stringify(items)}\n`); await Bun.write( path.join(outputRoot, "index.html"), - 'Spacefast examples datamanifest.json\n', + 'Spacefast recipes datamanifest.json\n', ); -console.log(`Built ${items.length} canonical examples into dist/manifest.json.`); +console.log(`Built ${items.length} canonical recipes into dist/manifest.json.`); diff --git a/scripts/catalog.test.mjs b/scripts/catalog.test.mjs new file mode 100644 index 0000000..56ec16e --- /dev/null +++ b/scripts/catalog.test.mjs @@ -0,0 +1,160 @@ +import { afterAll, beforeAll, describe, expect, test } from "bun:test"; +import path from "node:path"; + +const root = path.resolve(import.meta.dirname, ".."); +const bun = process.execPath; +let manifestBuild; + +async function inspectHtml(html, selectors) { + const results = new Map(selectors.map((selector) => [selector, []])); + const rewriter = new HTMLRewriter(); + for (const selector of selectors) { + let active; + rewriter.on(selector, { + element(element) { + active = { + attributes: Object.fromEntries(element.attributes), + text: "", + }; + results.get(selector).push(active); + }, + text(chunk) { + if (active) active.text += chunk.text; + if (chunk.lastInTextNode) active = undefined; + }, + }); + } + await rewriter.transform(new Response(html)).text(); + return results; +} + +beforeAll(async () => { + manifestBuild = Bun.spawn({ + cmd: [bun, "scripts/build-manifest.mjs"], + cwd: root, + stdout: "pipe", + stderr: "pipe", + }); + await manifestBuild.exited; +}); + +afterAll(() => { + manifestBuild?.kill(); +}); + +describe("canonical recipe catalog", () => { + test("builds a recipe feed containing Technical planning", async () => { + expect(manifestBuild.exitCode).toBe(0); + const manifest = await Bun.file(path.join(root, "dist/manifest.json")).json(); + expect(manifest).toContainEqual( + expect.objectContaining({ + slug: "technical-plan", + title: "Technical planning", + liveUrl: "https://technical-plan.view.fast/", + }), + ); + for (const recipe of manifest) { + expect(recipe.prompt, recipe.slug).toContain(`data-example="${recipe.slug}"`); + } + }); + + test("labels the public feed as recipes while retaining its historical URL", async () => { + const document = await inspectHtml( + await Bun.file(path.join(root, "dist/index.html")).text(), + ["title", 'a[href="./manifest.json"]'], + ); + + expect(document.get("title")?.[0]?.text).toBe("Spacefast recipes data"); + expect(document.get('a[href="./manifest.json"]')?.[0]?.text).toBe("manifest.json"); + }); + + test("validates published outputs during the badge compatibility rollout", async () => { + const legacy = Bun.spawn({ + cmd: [bun, "scripts/validate-publish-dir.mjs", "status", "examples/status/site"], + cwd: root, + stdout: "pipe", + stderr: "pipe", + }); + const canonical = Bun.spawn({ + cmd: [ + bun, + "scripts/validate-publish-dir.mjs", + "technical-plan", + "examples/technical-plan/site", + ], + cwd: root, + stdout: "pipe", + stderr: "pipe", + }); + + expect(await legacy.exited).toBe(0); + expect(await canonical.exited).toBe(0); + }); +}); + +describe("Technical planning recipe output", () => { + test("renders a decision-ready, accessible plan with every required planning section", async () => { + const html = await Bun.file( + path.join(root, "examples/technical-plan/site/index.html"), + ).text(); + const sectionIds = [ + "problem", + "scope", + "architecture", + "milestones", + "risks", + "decisions", + "open-questions", + "review-checklist", + ]; + const selectors = [ + "html", + "title", + "meta[name=viewport]", + "main h1", + ...sectionIds.flatMap((id) => [`main section#${id} h2`, `nav a[href="#${id}"]`]), + "#milestones tbody tr", + "#risks thead th", + "#risks tbody tr", + "#scope .constraints dt", + "#decisions li", + "#decisions dt", + "#open-questions li", + "#review-checklist li", + 'script[src="https://spacefast.com/badge.js"][data-example="technical-plan"]', + ]; + const document = await inspectHtml(html, selectors); + + expect(document.get("html")?.[0]?.attributes.lang).toBe("en"); + expect(document.get("title")?.[0]?.text).toBe("Northstar Sync — Technical Plan"); + expect(document.get("meta[name=viewport]")?.length).toBe(1); + expect(document.get("main h1")?.[0]?.text).toContain("Technical plan"); + for (const id of sectionIds) { + expect(document.get(`main section#${id} h2`)?.length, id).toBe(1); + expect(document.get(`nav a[href="#${id}"]`)?.length, id).toBe(1); + } + expect(document.get("#milestones tbody tr")?.length).toBeGreaterThanOrEqual(4); + expect(document.get("#risks tbody tr")?.length).toBeGreaterThanOrEqual(4); + expect(document.get("#risks thead th")?.map((entry) => entry.text)).toEqual([ + "Risk", + "Likelihood", + "Impact", + "Mitigation and trigger", + "Owner", + ]); + expect(document.get("#scope .constraints dt")?.map((entry) => entry.text)).toEqual( + expect.arrayContaining(["Goals", "Target users", "Assumptions and boundaries"]), + ); + expect(document.get("#decisions li")?.length).toBeGreaterThanOrEqual(3); + expect(document.get("#decisions dt")?.map((entry) => entry.text)).toEqual( + expect.arrayContaining(["Alternative", "Rationale", "Consequences", "Revisit when"]), + ); + expect(document.get("#open-questions li")?.length).toBeGreaterThanOrEqual(3); + expect(document.get("#review-checklist li")?.length).toBeGreaterThanOrEqual(4); + expect( + document.get( + 'script[src="https://spacefast.com/badge.js"][data-example="technical-plan"]', + )?.length, + ).toBe(1); + }); +}); diff --git a/scripts/validate-publish-dir.mjs b/scripts/validate-publish-dir.mjs index f104985..2c49da9 100644 --- a/scripts/validate-publish-dir.mjs +++ b/scripts/validate-publish-dir.mjs @@ -31,7 +31,7 @@ for (const file of htmlFiles) { const html = await Bun.file(file).text(); if ( !html.includes("https://spacefast.com/badge.js") || - !html.includes(`data-example="${slug}"`) + (!html.includes(`data-recipe="${slug}"`) && !html.includes(`data-example="${slug}"`)) ) { throw new Error(`${slug}: ${path.relative(root, file)} does not load the shared badge`); }