fimo 2.4.0-staging.1 → 2.4.0-staging.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/assets/skills/fimo-cli/SKILL.md +3 -2
  2. package/assets/skills/fimo-cli/references/agent-setup.md +2 -1
  3. package/assets/skills/fimo-cli/references/agents.md +13 -1
  4. package/assets/skills/fimo-cli/references/branches.md +4 -4
  5. package/assets/skills/fimo-cli/references/deploy.md +3 -6
  6. package/assets/skills/fimo-cli/references/domains.md +5 -5
  7. package/assets/skills/fimo-cli/references/forms.md +4 -2
  8. package/assets/skills/fimo-cli/references/hosting.md +5 -4
  9. package/assets/skills/fimo-cli/references/preview.md +1 -1
  10. package/assets/skills/fimo-cli/references/projects.md +5 -5
  11. package/assets/skills/fimo-cli/references/site-checks.md +73 -0
  12. package/assets/skills/fimo-code/SKILL.md +1 -0
  13. package/assets/skills/fimo-code/references/assets.md +4 -2
  14. package/assets/skills/fimo-code/references/best-practices/next.md +0 -2
  15. package/assets/skills/fimo-code/references/content/schema.md +4 -1
  16. package/assets/skills/fimo-code/references/design.md +2 -2
  17. package/assets/skills/fimo-code/references/frameworks/astro.md +37 -1
  18. package/assets/skills/fimo-code/references/frameworks/compatibility.md +5 -5
  19. package/assets/skills/fimo-code/references/frameworks/hosting.md +23 -2
  20. package/assets/skills/fimo-code/references/frameworks/next/app-router.md +7 -21
  21. package/assets/skills/fimo-code/references/frameworks/next/seo.md +168 -0
  22. package/assets/skills/fimo-code/references/frameworks/next.md +1 -1
  23. package/assets/skills/fimo-code/references/frameworks/seo-head.md +78 -0
  24. package/assets/skills/fimo-code/references/frameworks/sveltekit.md +57 -4
  25. package/assets/skills/fimo-migration/SKILL.md +33 -33
  26. package/assets/skills/fimo-migration/references/content.md +1 -1
  27. package/assets/skills/fimo-migration/references/frameworks/nextjs.md +7 -0
  28. package/assets/skills/fimo-migration/references/import-contract.md +4 -6
  29. package/assets/skills/fimo-migration/references/manifest.md +4 -3
  30. package/assets/skills/fimo-migration/references/qa.md +6 -0
  31. package/assets/skills/fimo-migration/references/questions-and-improvements.md +1 -1
  32. package/assets/skills/fimo-migration/references/workflow.md +7 -5
  33. package/assets/skills/fimo-studio/references/agents.md +7 -1
  34. package/assets/skills/fimo-studio/references/billing-and-credits.md +21 -7
  35. package/assets/skills/fimo-studio/references/seo-settings.md +2 -0
  36. package/dist/cli/bundle.json +2 -2
  37. package/dist/cli/index.js +502 -986
  38. package/dist/runtime/astro/server-runtime.js +2 -2
  39. package/dist/runtime/paths/get-fimo-paths.js +1 -1
  40. package/dist/runtime/seo/head.d.ts +31 -0
  41. package/dist/runtime/seo/head.js +47 -0
  42. package/dist/runtime/seo/index.d.ts +2 -0
  43. package/dist/runtime/seo/index.js +1 -0
  44. package/dist/runtime/seo/resolver.d.ts +16 -2
  45. package/dist/runtime/seo/resolver.js +10 -0
  46. package/dist/runtime/seo/server.d.ts +13 -0
  47. package/dist/runtime/seo/server.js +23 -0
  48. package/dist/runtime/shared/branch-identity.d.ts +3 -5
  49. package/dist/runtime/shared/branch-identity.js +3 -5
  50. package/dist/runtime/shared/fimo-config.server.d.ts +2 -0
  51. package/dist/runtime/shared/fimo-config.server.js +18 -14
  52. package/dist/scripts/export-static.d.ts +3 -4
  53. package/dist/scripts/export-static.js +3 -20
  54. package/dist/scripts/sync-schemas.js +12 -5
  55. package/package.json +12 -8
  56. package/templates/astro/.fimo/config.json +1 -0
  57. package/templates/astro/AGENTS.md +1 -1
  58. package/templates/astro/astro.config.mjs +1 -0
  59. package/templates/astro/package.json +2 -2
  60. package/templates/astro/src/layouts/Base.astro +20 -4
  61. package/templates/astro/src/pages/[locale]/index.astro +1 -1
  62. package/templates/astro/src/pages/[locale]/projects/[slug].astro +4 -1
  63. package/templates/astro/src/pages/index.astro +1 -1
  64. package/templates/astro/src/pages/projects/[slug].astro +4 -1
  65. package/templates/nextjs/AGENTS.md +1 -1
  66. package/templates/nextjs/package.json +3 -3
  67. package/templates/nextjs/src/app/layout.tsx +5 -3
  68. package/templates/nextjs/src/app/page.tsx +6 -0
  69. package/templates/react-router/package.json +4 -4
  70. package/templates/sveltekit/AGENTS.md +1 -1
  71. package/templates/sveltekit/package.json +2 -2
  72. package/templates/sveltekit/src/routes/+layout.server.ts +4 -0
  73. package/templates/sveltekit/src/routes/+layout.svelte +12 -0
  74. package/templates/sveltekit/src/routes/[[locale=locale]]/+page.svelte +0 -5
  75. package/templates/vite/package.json +4 -4
  76. package/assets/skills/fimo-migration/scripts/build-canonical-manifest.mjs +0 -595
@@ -91,6 +91,7 @@ Load the matching reference when the user's request fires its trigger. Recipes t
91
91
  - "Deploy / publish / go live / push my changes" → `references/deploy.md`
92
92
  - "Add a redirect / security headers / CSP / HSTS / clean URLs / trailing slash" → `references/hosting.md`
93
93
  - "Get the preview URL / open the preview / what's the URL for this Branch / refresh the preview link / I just want to see the site / the preview URL stopped working" → `references/preview.md`
94
+ - "Check the site in a browser / is my site accessible / a11y or WCAG check / measure LCP or Web Vitals / why is the page slow / inspect network requests or console errors / Lighthouse score" → `references/site-checks.md`
94
95
  - "Schedule a command / cron / nightly publish / recurring checks / `fimo schedules`" → `references/schedules.md`
95
96
  - "Set env vars / configure API keys / add project secrets / local `.env.local` / `fimo vars` / `fimo secrets`" → `references/project-vars-and-secrets.md`
96
97
  - "React to form submissions / publish changes / agent runs / analytics reports / media activity / send events to Resend, Slack, GitHub, Zapier, or an HTTP endpoint / configure or debug outbound webhooks" → `references/webhooks.md`
@@ -100,7 +101,7 @@ Load the matching reference when the user's request fires its trigger. Recipes t
100
101
  - "List history / create a restore point / recover content and code / restore a previous version / snapshot usage or retention" → `references/history.md`
101
102
  - "Create a Branch / feature Branch / switch Branches / merge Branches / diff two Branches / Branch status / what changed on this Branch / sync from parent / cut a release / tag a version / go to prod" → `references/branches.md`
102
103
  - "List my projects / clone an existing project locally / check out a project / delete this project / unpublish / rename the project / manage projects across the org" → `references/projects.md`
103
- - "Migrate an existing Webflow / Framer / Squarespace / Wix / Carrd site from only a published URL" → load the `fimo-migration` skill and start with `fimo migrate <url> [dir]` to prepare the agent-ready migration draft
104
+ - "Migrate an existing Webflow / Framer / Squarespace / Wix / Carrd site from only a published URL" → load the `fimo-migration` skill, set the target up with `fimo migrate init <dir>`, and read the published site yourself with a browser — the CLI does not crawl it
104
105
  - "Migrate from an exported project, source repository, Webflow code export plus CMS CSVs, Framer CMS CSVs, Squarespace XML/CSV, Wix CSVs, Carrd/static export, or downloaded site files" → load the `fimo-migration` skill and use the source repo/export as the migration source of truth
105
106
  - "How do AI agents read my site / markdown for agents" → `references/deploy.md`
106
107
  - "Modify the URL of the website / change my project's address / connect a custom domain (e.g. blog.example.com) / rename the Fimo-provided `*.fimo.site` subdomain / buy a new domain through Fimo / set up a domain" → `references/domains.md`
@@ -145,7 +146,7 @@ These fire at specific moments in the project lifecycle. **Surface them proactiv
145
146
  - **Using `fimo deploy --publish` casually** — `--publish` makes the site live to the public. Plain `fimo deploy` (preview) is the default. Use `--publish` only when the user says "ship it" / "go live" / "publish".
146
147
  - **Bare `fimo init` in a non-interactive shell** — will hang. Always pass `[dir]`, `--no-install` (or `--install`), `--no-skills` (or `--skills`), and `--org`/`--agents` as needed explicitly when scripted.
147
148
  - **Hardcoding content / strings / images in code** — that's what schemas, `t()`, and the media library are for. See the `fimo-code` skill's anti-patterns.
148
- - **Adding another deploy tool (Vercel, Netlify, Cloudflare Pages)** — Fimo handles deploys; don't bolt another platform on.
149
+ - **Adding another deploy tool**. Fimo handles deploys; don't bolt another platform on.
149
150
  - **Committing secrets** — hidden values use `fimo secrets`; public browser-safe values use `fimo vars`. Local env files are ignored and must not become deploy inputs.
150
151
  - **Hardcoding tokens in flags** — use the credentials written by `fimo login` (one file per backend at `~/.config/fimo/credentials/<host>-<hash>.json`).
151
152
  - **Treating the daily allowance as extra credits** — the allowance section appears only for legacy Premium organizations, and `fimo credits` already includes its spendable credits in "Available now"; it is accounting context, not an amount to add.
@@ -33,6 +33,7 @@ fimo login # connect your account when ready
33
33
  ```bash
34
34
  fimo skills install # interactive: pick agents, install the global bootstrap
35
35
  fimo skills install --agents=claude-code,cursor # explicit list
36
+ fimo skills install --agents=hermes # Hermes default profile, or the active HERMES_HOME
36
37
  fimo skills install -a claude-code -a cursor # repeatable form
37
38
  fimo skills sync # re-ensure the bootstrap + clean up stale old skills
38
39
  fimo skills uninstall # remove the global bootstrap
@@ -80,7 +81,7 @@ Every command that takes agents accepts the same selection inputs:
80
81
  - `-a claude-code -a cursor` — repeatable short form
81
82
  - No flag → interactive multi-select. The picker has two sections:
82
83
  - **Universal** — agents that read `AGENTS.md` natively (Codex, OpenCode, Aider, …). Always covered, not toggleable.
83
- - **Additional** — agents that get the global bootstrap skill installed. The 6 popular ones (`claude-code`, `cursor`, `codex`, `opencode`, `windsurf`, `gemini-cli`) appear at the top of an 8-item scrollable viewport; the full list of 50+ supported agents is below the fold. Agents already set up on the machine are pre-checked.
84
+ - **Additional** — agents that get the global bootstrap skill installed. The popular ones (`claude-code`, `cursor`, `codex`, `opencode`, `windsurf`, `gemini-cli`, `hermes`) appear at the top of the picker; the full list of supported agents remains available below them. Agents already set up on the machine are pre-checked.
84
85
  - `--agents=none` (only `fimo init`) — skip the global skill entirely.
85
86
 
86
87
  In headless contexts (CI, agent-spawned commands), pass the flag explicitly. Env-var detection (only Claude Code's `CLAUDECODE` / `CLAUDE_CODE_ENTRYPOINT`) silently targets `claude-code` if the flag is omitted; every other agent must be named explicitly with `--agents` in a headless shell, or the command exits with "No agents detected and no --agents flag passed."
@@ -271,7 +271,19 @@ fimo agents runs <name> [--limit <n>] [--cursor <cursor>] [--all-pages] [--branc
271
271
  fimo agents report <name> [--session <id>] [--branch <branch>] [--project <id>] [-C <dir>]
272
272
  ```
273
273
 
274
- - **`run <name>`** — fire the agent's `manual` trigger on the server; prints a `sessionId` on success. Skips with `no-manual-trigger` when `config.yaml` declares none, or `trigger-not-wired` when the push-to-main sync recorded the trigger but refused to wire it (see the wiring note below). **Pre-flight drift check**: if `.fimo/agents/<name>/` (or the legacy root bundle) has uncommitted git changes, the command refuses — the server would dispatch the _deployed_ version, so deploy first. Pass `--skip-drift-check` to dispatch the deployed bundle anyway. Defaults `--branch` to `main`.
274
+ - **`run <name>`** — fire the agent's `manual` trigger on the server; prints a `sessionId` on success. A refusal you must act on exits **1** with a stable code (`--json` puts it in `error.code`, and the raw server reason in `error.details.skipped`):
275
+
276
+ | Code | Means | Fix |
277
+ | --------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------- |
278
+ | `AGENT_NOT_DEPLOYED` | no bundle for this agent on `main` | `fimo deploy` |
279
+ | `AGENT_CONFIG_INVALID` | the deployed bundle does not parse, so the sync registered none of its triggers | `fimo agents validate <name>`, fix, `fimo deploy` |
280
+ | `NO_MANUAL_TRIGGER` | the deployed `config.yaml` really declares no `manual` trigger | add `- type: manual`, `fimo deploy` |
281
+ | `MANUAL_TRIGGER_NOT_SYNCED` | `main` declares it, the background sync has not registered it yet | wait a few seconds, retry |
282
+ | `TRIGGER_NOT_WIRED` | registered but not live (see the wiring note below) | `fimo agents list` for the reason |
283
+ | `INSUFFICIENT_CREDITS` | the org is under the credit floor a run needs | `fimo credits` |
284
+
285
+ A refusal that clears on its own (`agent-paused`, `run-in-progress`, `task-branch-budget`) exits **0** and prints `Dispatch was skipped: <reason>`. **Pre-flight drift check**: if `.fimo/agents/<name>/` (or the legacy root bundle) has uncommitted git changes, the command refuses — the server would dispatch the _deployed_ version, so deploy first. Pass `--skip-drift-check` to dispatch the deployed bundle anyway. Defaults `--branch` to `main`.
286
+
275
287
  - **`runs <name>`** — list past run sessions for the agent in a compact table (id, started, duration, status, trigger, Branch, credits — settled credit consumption, `—` until a run settles). Default `--limit 20`; `--branch` filters to one Branch. The response uses the canonical `branch` field.
276
288
  - **`report <name>`** — print a run's structured **report**: its durable outcome summary (for a read-only agent like `seo-audit` this _is_ the audit; for a write agent it's a "what I changed" summary). A run that returns plain text without calling `finish_run` receives a small structured fallback document. With no `--session`, the most recent run for `<name>` is used (combine with `--branch` to scope); `--session <id>` targets a specific run. Output is projected Markdown, so it stays readable in the terminal and pipes cleanly (e.g. `fimo agents report seo-audit | glow`). If the run hasn't finished, or produced no report, it says so (and shows the stop reason when there is one).
277
289
 
@@ -36,7 +36,7 @@ fimo --branch <name> <command> # peek at another Branch for one command (does n
36
36
  | `fimo diff [from] [to]` | `git diff` | Two-Branch diff across all surfaces. Defaults `from` = current Branch, `to` = `main`. `--surface <name>` limits to one; `--json`; `--no-color`. |
37
37
  | `fimo status` | `git status` | Multi-surface status for the current Branch vs its parent. See below. |
38
38
  | `fimo merge <from>` | `git merge` | Merge another Branch into the current one (multi-surface, atomic, interactive conflict resolver). See below. |
39
- | `fimo publish` | — | Publish the synced Production source revision with a stable Fimo publication ID. See "Publishing" below. |
39
+ | `fimo publish` | — | Publish the revision already on the Fimo remote (no push) with a stable Fimo publication ID. See "Publishing" below. |
40
40
 
41
41
  All of these accept the global `--branch` override. `diff`, `status`, `merge`, and `publish` additionally accept `-C, --cwd <dir>` to point at a project directory.
42
42
 
@@ -98,10 +98,10 @@ Syncs the current Branch's data plane from its parent (or `--from <ancestor>`).
98
98
 
99
99
  Two different "go live" mechanisms — don't confuse them:
100
100
 
101
- - **`fimo publish [--label <text>] [--notes <md>]`** — publishes the synced Production source revision. Fimo assigns the immutable publication ID; the label and notes are optional annotations. `--skip-validate` is an operator override.
102
- - **`fimo deploy --publish`** — the project-publish path. Pushes the current Production source code and flips the project live in one shot. See `references/deploy.md`.
101
+ - **`fimo publish [--label <text>] [--notes <md>]`** — publishes the revision already on the Fimo remote without pushing. Fimo assigns the immutable publication ID; labels and notes are optional annotations. `--skip-validate` is an operator override.
102
+ - **`fimo deploy --publish`** — pushes the current Production source Branch and flips the project live. See `references/deploy.md`.
103
103
 
104
- Use `fimo publish` when the Production source Branch is already synced; use `fimo deploy --publish` when the local revision still needs to be pushed first. Both only run from the configured Production source Branch. Existing projects use `main`.
104
+ Choose `fimo deploy --publish` when local changes need to go live; choose `fimo publish` when the remote revision is the intended release. Both only run from the configured Production source Branch. Existing projects use `main`.
105
105
 
106
106
  ## Anti-patterns
107
107
 
@@ -54,7 +54,7 @@ Use the publication ID returned by the failed command: run `fimo publish inspect
54
54
  A failed `fimo deploy --json` names the cause in `error.details.failure_code` and the phase in `error.details.phase`: `pull` (Git synchronization into the sandbox), `install` (dependency install), `restart` (dev-server start), or `readiness` (the final preview check); `acquire` and `sync-env` are the sandbox and environment steps before them. When the failed process produced output, the same error carries `error.details.exit_code` and a bounded, redacted `error.details.log_tail` (newest line last). Read that tail first: it is the failed process's own output, and a replacement sandbox that failed is discarded, so `fimo logs` shows the preview that is still serving rather than the attempt that failed. The top-level codes remain compatible:
55
55
 
56
56
  - `SANDBOX_SYNC_FAILED` — the revision never became ready. Fix what the tail reports (a manifest or lockfile for `install`, the Git state for `pull`), then deploy again. When `error.details.failure_code` is `install_policy_blocked`, follow the typed repair in `error.details.repair`.
57
- - `PREVIEW_NOT_READY` — the revision landed and the dev server never served the page. Fix what the tail reports; when there is no tail, read `fimo logs --json`.
57
+ - `PREVIEW_NOT_READY` — the revision landed and the preview never proved ready. `error.message` names what the readiness probe last saw: a dev server that died, or the optimized dependency the public preview route was still delivering and what the dev server said about it over loopback. Fix what the tail reports; when there is no tail, act on the message before reading `fimo logs --json`, which shows a dev server that may be healthy.
58
58
 
59
59
  `--no-wait` skips only the final readiness check. Pull, install, and dev-server failures are still reported with the same fields.
60
60
 
@@ -123,12 +123,9 @@ There's nothing special about this — it's the same `fimo deploy` you'd run lat
123
123
 
124
124
  ## Publishing: `fimo deploy --publish` vs `fimo publish`
125
125
 
126
- Two different "go live" mechanisms — pick deliberately:
126
+ Use `fimo deploy --publish` to push and publish local changes. Use `fimo publish` to publish the revision already on the Fimo remote without pushing. Both target the configured Production source Branch.
127
127
 
128
- - **`fimo deploy --publish`** — push what's on the Production source Branch now and flip the project live in one shot. The simple "ship it" path. Runs from that Branch only.
129
- - **`fimo publish [--label <text>] [--notes <md>]`** — publish the synced Production source revision without pushing. Fimo assigns the immutable publication ID; a label and notes are optional human annotations. See `references/branches.md`.
130
-
131
- When unsure, use `fimo deploy --publish` so the local revision is pushed before it goes live. Use `fimo publish` when the Production source Branch is already synced.
128
+ Check the reported source commit and warnings before reporting completion. If local work is excluded or the built commit cannot be confirmed, follow the CLI's hint.
132
129
 
133
130
  ## Markdown for AI agents
134
131
 
@@ -51,8 +51,8 @@ Global flags: `--project <id>` / `-C, --cwd <dir>` for project resolution, `--or
51
51
  When a user says "I want to change my website's URL," ask which case fits:
52
52
 
53
53
  - **"It's fine as-is, just nicer"** → `rename-default` or `suggest-default`. Free, instant, no DNS.
54
- - **"I own example.com already"** → `add example.com`. Premium. They configure CNAME at their registrar.
55
- - **"I want to buy a domain"** → `search` → `pricing` → `buy`. Premium + the registered-domains feature flag has to be on (it's not enabled in every environment).
54
+ - **"I own example.com already"** → `add example.com`. Pay as you go or higher. They configure CNAME at their registrar.
55
+ - **"I want to buy a domain"** → `search` → `pricing` → `buy`. The registered-domains feature flag and an eligible plan must be on (the flag is not enabled in every environment).
56
56
 
57
57
  If they aren't sure, run `fimo domains suggest-default` first — it's free, takes one step, and a good fallback if they don't want to commit to a domain purchase.
58
58
 
@@ -60,7 +60,7 @@ If they aren't sure, run `fimo domains suggest-default` first — it's free, tak
60
60
 
61
61
  After the automatic first-preview deploy on a newly created project, offer a cleaner free `*.fimo.site` URL before the first public publish when there is no custom domain and the current default slug still looks generated or was never explicitly chosen. Choosing it now lets the first public launch use the clean URL. Skip the offer if the user already chose the default slug, attached a custom domain, or declined.
62
62
 
63
- The default URL is free and needs no DNS. A custom domain is the separate Premium workflow above. A default slug can be reserved before publication, but it returns "Project Not Found" until the site is published. Renaming changes the address that will become public, so never silently claim a suggestion:
63
+ The default URL is free and needs no DNS. A custom domain uses the Pay as you go (or higher) workflow above. A default slug can be reserved before publication, but it returns "Project Not Found" until the site is published. Renaming changes the address that will become public, so never silently claim a suggestion:
64
64
 
65
65
  1. Run `fimo domains suggest-default --base "<brand>" --json` to get candidates.
66
66
  2. Show the candidates and ask the user to choose one explicitly.
@@ -72,7 +72,7 @@ Choosing the slug does not publish the site. The first successful `fimo deploy -
72
72
 
73
73
  The CLI never charges directly. Two distinct money paths:
74
74
 
75
- 1. **Premium subscription** — gates `add`, `buy`, `owned`, `refresh`, `remove` for custom domains. The user upgrades through the Fimo web app (Hyperline-hosted checkout). When a free user runs a gated command they get a 403 with the upgrade URL — surface it as-is to the user.
75
+ 1. **Pay as you go or higher** — gates custom-domain operations. A valid card activates Pay as you go through the Fimo web app (Hyperline-hosted checkout). When a Free user runs a gated command they get a 403 with the billing URL; surface it as-is to the user.
76
76
  2. **Domain registration** — `fimo domains buy` creates a Hyperline invoice with `payment_method_strategy: 'external'` and returns a `checkoutUrl`. The user opens that URL in a browser to pay. **No money moves until they pay the invoice.** That's why `--yes` on `buy` is safe: it queues an invoice; the human still has to consent at checkout.
77
77
 
78
78
  Domain prices come from name.com via the registrar reseller. They vary by TLD and can change. Pricing is in USD (cents in the API, formatted as dollars in CLI output).
@@ -121,7 +121,7 @@ Propagation: typically 15–30 minutes, up to 48 hours rarely.
121
121
  ## Common errors
122
122
 
123
123
  - **"Project Not Found" on a new URL or custom domain.** The route exists but the site was never published — run `fimo deploy --publish`.
124
- - **"Custom domains require a Premium plan."** — the operation is paid; the message includes the org billing URL. Free users can still run `list`, `rename-default`, `suggest-default`, `search`, and `pricing`.
124
+ - **"Custom domains require Pay as you go or higher."** — add a card at `/app/billing`, then retry. Free users can still run `list`, `rename-default`, `suggest-default`, `search`, and `pricing`.
125
125
  - **"Domain purchase is not enabled on this account."** — the registered-domains feature flag is off on this API instance. Contact support.
126
126
  - **"This URL is not available."** — slug or hostname collides with another project or is reserved.
127
127
  - **"That's a Fimo-owned domain."** — user tried `add <something>.fimo.site`. Use `rename-default` instead.
@@ -24,7 +24,7 @@ fimo forms delete <id> # delete a form
24
24
 
25
25
  Notification recipients for form submissions are configured in the Fimo web UI, not via CLI.
26
26
 
27
- ## Reading submissions
27
+ ## Reading and deleting submissions
28
28
 
29
29
  After a form is live and users have filled it out, inspect submissions from the terminal:
30
30
 
@@ -32,6 +32,7 @@ After a form is live and users have filled it out, inspect submissions from the
32
32
  fimo forms submissions list <formIdOrName> [--limit 50] [--cursor CURSOR] [--all-pages] [--search "<q>"] [--sort asc|desc]
33
33
  fimo forms submissions get <formIdOrName> <submissionId>
34
34
  fimo forms submissions stats <formIdOrName>
35
+ fimo forms submissions delete <formIdOrName> <submissionId>
35
36
  ```
36
37
 
37
38
  The list response includes `nextCursor` when another page exists. `--offset` remains a compatibility alias for existing scripts.
@@ -39,7 +40,8 @@ The list response includes `nextCursor` when another page exists. `--offset` rem
39
40
  - `<formIdOrName>` accepts either the form's UUID or its `name` (the same name in the JSON file). Names that don't resolve to exactly one form return an error.
40
41
  - `list` returns `{ data: [...], total }`. Newest-first by default; pass `--sort asc` to reverse.
41
42
  - `search` matches against submission contents server-side.
42
- - All three are read-only — there's no CLI command to create or delete a submission. Submissions are created by the form intake endpoint when a user submits the published site's form.
43
+ - `delete` removes one submission permanently and prints the deleted record. There is no undo, no bulk delete, and no confirmation prompt — confirm with the user before running it. An unknown or already-deleted id fails with `Submission not found`.
44
+ - There's no CLI command to create a submission. Submissions are created by the form intake endpoint when a user submits the published site's form.
43
45
 
44
46
  Use this when the user asks "who filled out the contact form?", "how many signups did we get this week?", or "show me the latest submission". For older submissions or bulk export, point them at the dashboard — there's no batch export endpoint yet.
45
47
 
@@ -57,9 +57,9 @@ them are present.
57
57
  {
58
58
  "redirects": [
59
59
  {
60
- "source": "/(.*)",
61
- "has": [{ "type": "header", "key": "x-vercel-ip-country", "value": "GB" }],
62
- "destination": "/uk/:path*"
60
+ "source": "/offers",
61
+ "has": [{ "type": "header", "key": "x-promo", "value": "summer" }],
62
+ "destination": "/summer-sale"
63
63
  }
64
64
  ],
65
65
  "rewrites": [
@@ -74,12 +74,13 @@ them are present.
74
74
 
75
75
  | `type` | Matches on |
76
76
  | -------- | ---------------------------------------------------- |
77
- | `header` | a request header, including CDN-injected geo headers |
77
+ | `header` | a request header |
78
78
  | `cookie` | a cookie |
79
79
  | `query` | a query parameter |
80
80
  | `host` | the hostname the request arrived on — takes no `key` |
81
81
 
82
82
  Omit `value` to match on presence alone, as the `consent` cookie above does.
83
+ The redirect example requires the request to include `x-promo: summer`.
83
84
 
84
85
  **Prefer doing this in the application when it can.** Middleware, a loader, or a
85
86
  server component can be run and tested locally; a condition here only takes
@@ -24,7 +24,7 @@ JSON output contains only the Branch identity and hosted URL:
24
24
  "project_id": "prj_abc",
25
25
  "branch": "main",
26
26
  "env": "main",
27
- "preview_url": "https://fimo-preview-example.vercel.app"
27
+ "preview_url": "https://preview.example.com"
28
28
  }
29
29
  }
30
30
  ```
@@ -43,10 +43,10 @@ fimo rename "<Site Name>" # local edit: set seo.siteName in the project c
43
43
 
44
44
  ## Publish commands
45
45
 
46
- | Command | Effect |
47
- | ----------------------- | -------------------------------------------------------------------------- |
48
- | `fimo deploy --publish` | Push the current Production source + flip the project live in one shot. |
49
- | `fimo projects publish` | Flip the project live (no git push). |
50
- | `fimo publish` | Flip the synced Production source revision live; optional label and notes. |
46
+ | Command | Effect |
47
+ | ----------------------- | ----------------------------------------------------------------------- |
48
+ | `fimo deploy --publish` | Push the current Production source + flip the project live in one shot. |
49
+ | `fimo projects publish` | Flip the project live (no git push). |
50
+ | `fimo publish` | Flip the revision already on the Fimo remote live (no git push). |
51
51
 
52
52
  See `references/deploy.md` and `references/branches.md` for the full picture.
@@ -0,0 +1,73 @@
1
+ # Site checks
2
+
3
+ Start from a URL the agent can actually reach, then use the inspection tools
4
+ available in its runtime. This reference owns Fimo target selection and the
5
+ meaning of the evidence. Browser and audit tools own their commands.
6
+
7
+ ## 1. Pick a target and name it
8
+
9
+ - An already-running local development server.
10
+ - An existing hosted Fimo preview: run `fimo preview url --json` and use
11
+ `data.sandbox_url` (see `references/preview.md`).
12
+ - A URL the user supplied, including an existing published site.
13
+
14
+ Never run `fimo deploy` just to retrieve a preview URL. Do not run `fimo
15
+ publish` or `fimo deploy --publish` merely to create a measurement target.
16
+ For any other deployment or publishing decision, follow the current run's
17
+ authority rules and `references/deploy.md`.
18
+
19
+ A local server or preview can prove how that target renders and behaves. Its
20
+ timings describe that environment, not the published site. A supplied public
21
+ URL can describe the live version, but one synthetic run is not field data.
22
+
23
+ ## 2. Use the tools that exist
24
+
25
+ Inspect the available tools and skills before choosing a method.
26
+
27
+ - If `agent-browser` is available, load its skill and version-matched `core`
28
+ guidance before using it.
29
+ - Otherwise use equivalent browser automation, accessibility, HTTP, network,
30
+ profiling, or performance tools exposed by the current runtime.
31
+ - HTTP-only tools can prove fetchability, status, headers, and raw content.
32
+ They cannot prove visual layout, interactions, or accessibility.
33
+ - Fimo CLI does not produce Lighthouse reports, and `agent-browser` Web Vitals
34
+ are not Lighthouse scores. If the environment provides Lighthouse, use its
35
+ own guidance and name the target. If it does not, report that limitation and
36
+ use only measurements that can actually run.
37
+
38
+ ## 3. Pick the lens the question needs
39
+
40
+ | The user asks | Evidence to obtain |
41
+ | --------------------------------------------------------------- | --------------------------------------------- |
42
+ | Does the page render, is the copy right, is an image broken | browser snapshot and screenshot |
43
+ | Does this flow work, does the form submit, is the console clean | browser interaction and console output |
44
+ | Is it accessible, WCAG, contrast, labels, alt text | accessibility audit |
45
+ | Why does it feel slow, LCP, CLS, INP, TTFB, hydration | Web Vitals and, when needed, a profiler trace |
46
+ | Wrong data, a failing request, a slow API, response headers | network log, HAR, or HTTP response |
47
+ | Does the page expose its own tools to agents | WebMCP page tools, when supported |
48
+ | What is its Lighthouse score | an actual Lighthouse run |
49
+
50
+ Run only the lenses the question needs. Two lenses with clear evidence beat a
51
+ sweep of all seven.
52
+
53
+ ## 4. Report honestly
54
+
55
+ - State the target URL and its kind (hosted preview, dev server, supplied URL),
56
+ the viewport, and when the checks ran.
57
+ - Give the observed values with their units and how many runs produced them.
58
+ One run is one run; say so.
59
+ - Keep what you observed separate from what you inferred, and list the lenses
60
+ you did not run.
61
+ - Never claim a check that did not run. If the environment blocked it (no
62
+ browser, an expired sandbox, a target that would not load), report what
63
+ blocked it.
64
+
65
+ For visitor behavior on the published site (pageviews, top pages, sources),
66
+ use `references/analytics.md`. It reports real traffic rather than one browser
67
+ run.
68
+
69
+ ## See also
70
+
71
+ - `references/preview.md` for preview destinations and sandbox URL expiry.
72
+ - `references/deploy.md` for preview deployment and publishing authorization.
73
+ - `references/analytics.md` for published-site traffic.
@@ -72,6 +72,7 @@ Each reference defines one package contract. Fetch it when the task reaches that
72
72
  - Locale ownership and framework handoff → `references/locales.md`
73
73
  - Upgrading a React Router app that imports `fimo/react-router/routes` → `references/migrations/react-router-route-ownership.md`
74
74
  - Astro connector and output/adapter contract → `references/frameworks/astro.md`
75
+ - Astro/SvelteKit SEO or a new content route → the framework reference, then `references/frameworks/seo-head.md` for value ownership and edit-and-render acceptance
75
76
  - Framework detection, production routing, and hosting adapters → `references/frameworks/hosting.md`
76
77
  - Major visual work → `references/design.md`
77
78
 
@@ -6,7 +6,9 @@ This file covers media fields and the Fimo image components.
6
6
 
7
7
  ## Media field values
8
8
 
9
- A media field stores a reference to an asset, not a copy of the asset metadata. Write the value returned by upload or generation:
9
+ For single-image and gallery schemas, see `references/content/schema.md`.
10
+
11
+ Each media object stores a reference to an asset, not a copy of the asset metadata. Use the value returned by upload or generation:
10
12
 
11
13
  ```json
12
14
  {
@@ -31,7 +33,7 @@ const withAsset = await Post.getBySlug('hello', { populate: ['cover'] });
31
33
 
32
34
  `populate` takes top-level field names. A blocks field populates every media value inside it. One lookup covers all selected media in the response. Media inside a populated reference target stays a reference. Use `fimo assets open <id> --download` to inspect the source file.
33
35
 
34
- Generated reads wrap media in `FimoMedia`. Its `id`, `alt`, `name`, `mime`, `width`, and `height` can be absent. A populated value has the current facts when the asset resolves; missing or external assets stay unchanged. `source` is internal. Pass the whole value to `<Image>` or `<Video>`.
36
+ Generated reads wrap each media object in `FimoMedia`. Its `id`, `alt`, `name`, `mime`, `width`, and `height` can be absent. A populated value has the current facts when the asset resolves; missing or external assets stay unchanged. `source` is internal. Pass one `FimoMedia` value, not the array, to `<Image>` or `<Video>`.
35
37
 
36
38
  ## Rendering in application code
37
39
 
@@ -38,5 +38,3 @@ Use `instant = true` to find blocking code, then verify with `next build` and `n
38
38
  - Avoid duplicate content reads between `generateMetadata` and the page.
39
39
 
40
40
  Verify valid and missing slugs, canonical and initial HTML, shipped JavaScript, duplicate reads, image sizing, instant shell rendering, streaming, freshness, and bounded prefetching.
41
-
42
- Sources: [Instant Navigations](https://nextjs.org/blog/next-16-3-instant-navigations), [`partialPrefetching`](https://github.com/vercel/next.js/blob/canary/docs/01-app/03-api-reference/05-config/01-next-config-js/partialPrefetching.mdx), and [`instant`](https://github.com/vercel/next.js/blob/canary/docs/01-app/03-api-reference/03-file-conventions/02-route-segment-config/instant.mdx).
@@ -14,6 +14,7 @@ Write one schema per `src/schemas/<Uid>.json`. The PascalCase filename must matc
14
14
  "publishedAt": { "type": "date" },
15
15
  "featured": { "type": "boolean" },
16
16
  "cover": { "type": "media" },
17
+ "gallery": { "type": "media", "multiple": true },
17
18
  "metadata": { "type": "json" },
18
19
  "author": { "type": "reference", "target": "Author" },
19
20
  "contributors": { "type": "reference", "target": "Author", "many": true }
@@ -80,11 +81,13 @@ Never declare `id`, `entryId`, `documentId`, `slug`, `locale`, `createdAt`, `upd
80
81
  | `boolean` | boolean | flags |
81
82
  | `date` | ISO date string | calendar days; loose about the form |
82
83
  | `datetime` | ISO instant with offset | exact moments (`2026-08-13T09:30:00Z`) |
83
- | `media` | media object or array | images, video, files |
84
+ | `media` | media object by default | images, video, files |
84
85
  | `json` | JSON | structured metadata |
85
86
  | `reference` | `{ "id": "..." }` or array | links to another schema |
86
87
  | `blocks` | ordered object array | nested/repeatable sections |
87
88
 
89
+ Set `multiple: true` on a media field for an array, even with one image. See `references/assets.md` for the object shape.
90
+
88
91
  A `datetime` value must carry `Z` or `±HH:MM`; a bare day or a naive local time is rejected. Render it with `<DateTime>`, which keeps the whole instant in the `<time datetime>` attribute, and a `date` with `<Date>`. `unique` is not supported on `datetime`.
89
92
 
90
93
  An enum string uses `options`; its optional `default` must be one of them:
@@ -44,10 +44,10 @@ Reference sites to anchor the aesthetic direction. Pull any well-known site, bra
44
44
  | Category | Example Anchors | Quality Bar |
45
45
  | ------------------------ | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
46
46
  | **Creative / Agency** | Awwwards, FWA, CSS Design Awards, Pentagram, Sagmeister & Walsh, Active Theory, Fantasy Interactive, Resn | Would it win Awwwards SOTD? Would Pentagram put this in their portfolio? |
47
- | **SaaS / Product** | Linear, Vercel, Stripe, Notion, Figma, Raycast, Arc Browser, Supabase, Mercury, Clerk, Loom, Pitch | Is it Linear-polished? Would a developer tweet "their site is so clean"? |
47
+ | **SaaS / Product** | Linear, Stripe, Notion, Figma, Raycast, Arc Browser, Supabase, Mercury, Clerk, Loom, Pitch | Is it Linear-polished? Would a developer tweet "their site is so clean"? |
48
48
  | **Editorial / Blog** | Medium, Substack, The Verge, NYT, The Atlantic, Monocle, It's Nice That, Eye on Design, Wired | Would The Verge's design team respect this? Is it magazine-worthy? |
49
49
  | **E-commerce** | Apple Store, Shopify Dawn, Gumroad, Everlane, Glossier, SSENSE, Mr Porter, Mejuri, Allbirds | Does it feel Apple Store premium? Would you trust buying from this? |
50
- | **Documentation** | Stripe Docs, Tailwind Docs, Vercel Docs, Supabase Docs, Prisma Docs, Algolia Docs, Clerk Docs | Is it Stripe Docs clear? Can a developer find what they need in 3 seconds? |
50
+ | **Documentation** | Stripe Docs, Tailwind Docs, Supabase Docs, Prisma Docs, Algolia Docs, Clerk Docs | Is it Stripe Docs clear? Can a developer find what they need in 3 seconds? |
51
51
  | **Personal / Portfolio** | Read.cv, Paco Coursey, Josh Comeau, Rauno Freiberg, Brian Lovin, Lee Robinson, Linus Rogge | Would Read.cv feature this? Is it memorable and distinctly personal? |
52
52
  | **Corporate** | Apple, Stripe, Airbnb, Slack, Square, Intercom, Dropbox, Zendesk | Does it feel Airbnb-trustworthy? Premium but not flashy? |
53
53
  | **Dashboard** | Linear, Figma, Raycast, Retool, Rows, Height, Airtable, Coda | Is it Linear-efficient? Dense but never cluttered? |
@@ -1,6 +1,6 @@
1
1
  # Astro integration
2
2
 
3
- Use this reference for an existing Astro application. The application keeps its route files, output mode, adapter, locale system, links, `<html lang/dir>`, and SEO. Fimo connects content, labels, native rendering, preview, and hosting.
3
+ Use this reference for an existing Astro application. The application keeps its route files, output mode, adapter, locale system, links, `<html lang/dir>`, and per-page SEO. Fimo connects content, labels, native rendering, preview, hosting, and the site-wide SEO defaults from Studio's Settings → SEO.
4
4
 
5
5
  ## Setup
6
6
 
@@ -90,6 +90,42 @@ browser values before submitting. Do not import the server form module into a
90
90
  client island; add a project endpoint if the form is intentionally browser-
91
91
  submitted.
92
92
 
93
+ ## SEO defaults
94
+
95
+ Resolve the current route, apply page values, then convert to native attributes.
96
+ New projects have this in `src/layouts/Base.astro`. Existing apps should extend
97
+ their current head component, preserving unrelated metadata.
98
+
99
+ ```astro
100
+ ---
101
+ import { resolveSeoForPath, toSeoHead } from 'fimo/seo';
102
+ import config from '../../.fimo/config.json';
103
+
104
+ const { seo = resolveSeoForPath(Astro.url.pathname, config) } = Astro.props;
105
+ const canonicalUrl = seo?.url ? new URL(Astro.url.pathname, seo.url).href : undefined;
106
+ const head = toSeoHead(seo, { canonicalUrl });
107
+ ---
108
+ <head>
109
+ <title>{head.title ?? 'My site'}</title>
110
+ {head.meta.map((attributes) => <meta {...attributes} />)}
111
+ {head.links.map((attributes) => <link {...attributes} />)}
112
+ </head>
113
+ ```
114
+
115
+ For a content page, resolve after loading the entry and pass the final values
116
+ to the layout: `const seo = resolveSeoForPath(Astro.url.pathname, config, { article })`,
117
+ then `<Base lang={locale} seo={seo}>`. Route templates can read
118
+ `{{article.title}}`. Apply app-owned overrides before conversion so the title,
119
+ Open Graph and Twitter tags agree.
120
+
121
+ The example canonical policy fits a root-hosted site. Preserve the app's own
122
+ production domain, base path and trailing-slash policy. Omitting the converter's
123
+ `canonicalUrl` omits canonical and `og:url`; `seo.url` alone is only a site base.
124
+ Imported config changes need sync and rebuild/redeploy. Content freshness
125
+ follows the route's rendering and caching policy.
126
+
127
+ Full field and composition contract: read `references/frameworks/seo-head.md` when changing SEO.
128
+
93
129
  ## Static and on-demand rendering
94
130
 
95
131
  Keep the application's per-route rendering choice:
@@ -23,11 +23,11 @@ Vite plugin from `fimo-react-router/vite`, which builds on the installed
23
23
  SvelteKit installs `fimo` and `fimo-sveltekit`. Move a project to a new release
24
24
  with `fimo update <exact-version>`, which keeps the whole set on one version.
25
25
 
26
- React projects pinned before framework companions shipped keep their legacy
27
- runtime imports. The current CLI generates content clients through `fimo/ui`
28
- for those projects and does not require `fimo-react`. Run `fimo update
29
- <exact-version>` only when the developer chooses to move the project to a split
30
- runtime release.
26
+ React and Next.js projects pinned before framework companions shipped keep
27
+ their legacy runtime imports. The current CLI generates content clients through
28
+ `fimo/ui` or `fimo/next` for those projects and does not require `fimo-react`
29
+ or `fimo-next`. Run `fimo update <exact-version>` only when the developer
30
+ chooses to move the project to a split runtime release.
31
31
 
32
32
  `runtime.framework` must match a dependency in `package.json`; a profile the
33
33
  code does not use fails the production build. Shape and rules: `hosting.md`
@@ -64,6 +64,28 @@ local environment alias by hand.
64
64
  projects. Do not add it to new code, env files, setup instructions, or migration
65
65
  plans.
66
66
 
67
+ ## `hosting`: how the deployed site is served
68
+
69
+ Declare hosting rules only in `.fimo/config.json#hosting`, not provider
70
+ deployment files. Run `fimo validate` to catch unsupported keys and malformed rules.
71
+
72
+ | Key | Shape |
73
+ | --------------- | ---------------------------------------------------------------- |
74
+ | `rewrites` | `{ source, destination }`, URL unchanged |
75
+ | `redirects` | `{ source, destination, permanent?, statusCode? }` |
76
+ | `headers` | `{ source, headers: [{ key, value }] }`, response headers |
77
+ | `cleanUrls` | Serve `/about` for `/about.html` and redirect the extension away |
78
+ | `trailingSlash` | `true` requires a trailing slash, `false` forbids one |
79
+
80
+ Rewrites, redirects, and header rules accept `has` / `missing` conditions:
81
+ `header`, `cookie`, and `query` require `key`; `host` requires only `value`.
82
+
83
+ Redirects default to temporary. Use `permanent: true` only for lasting moves;
84
+ browsers cache it. `statusCode`, one of 301, 302, 307, 308, overrides `permanent`.
85
+
86
+ Verify rules on a hosted Preview or published site, not a local dev server.
87
+ Legacy static hosting ignores them; contact support if deployed rules have no effect.
88
+
67
89
  ## React Router framework mode
68
90
 
69
91
  For the supported client-rendered setup, keep `ssr: false` and add Fimo's
@@ -111,5 +133,4 @@ Astro has a dedicated connector — load `references/frameworks/astro.md` before
111
133
  editing an Astro config.
112
134
 
113
135
  `.fimo/config.json#routes` is the Studio page catalog, not deployment routing.
114
- Never generate hosting rewrites from it. If a project already has a
115
- provider-specific deployment file, preserve it; that file remains authoritative.
136
+ Never generate hosting rewrites from it.
@@ -109,24 +109,10 @@ Do not add `'use client'` to a page solely because Fimo is present. Keep promise
109
109
 
110
110
  ## Metadata
111
111
 
112
- Fimo owns the site-wide defaults; the application owns per-page overrides. Keep (or add) the starter wiring in the root layout — it maps `.fimo/config.json#seo` (Studio's Settings → SEO: title, description, favicon, share image, robots, theme color, canonical) onto Next `Metadata`/`Viewport`:
113
-
114
- ```ts
115
- import { buildFimoMetadata, buildFimoViewport } from 'fimo-next';
116
-
117
- export const generateMetadata = () => buildFimoMetadata();
118
- export const generateViewport = () => buildFimoViewport();
119
- ```
120
-
121
- If the root layout lacks this wiring, add it (updating the fimo packages if `fimo-next` does not export the helpers); without it, Settings → SEO never reaches the rendered head.
122
-
123
- Per-page `metadata`/`generateMetadata` exports override the defaults field by field. Resolve labels/content on the server and convert tracked strings only where Next expects primitives:
124
-
125
- ```ts
126
- export async function generateMetadata() {
127
- const labels = await getLabels();
128
- return { title: String(labels.t('seo.home.title')) };
129
- }
130
- ```
131
-
132
- Do not expect `FimoProvider` to inject SEO, routes, language, or direction.
112
+ When creating a site, adding a route, or integrating SEO, load
113
+ `references/frameworks/next/seo.md` (`--ref frameworks/next/seo`). Keep root
114
+ global defaults separate from explicit Home and route SEO. Reuse the app's
115
+ established route integration for new pages; a dynamic route module covers all
116
+ its instances. Next replaces nested metadata objects, not their individual
117
+ fields. Preserve app-owned policies and image routes. `FimoProvider` does not
118
+ inject SEO.