fimo 2.4.0-staging.2 → 2.4.0-staging.4
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.
- package/assets/skills/fimo-cli/SKILL.md +1 -1
- package/assets/skills/fimo-cli/references/branches.md +4 -4
- package/assets/skills/fimo-cli/references/deploy.md +2 -5
- package/assets/skills/fimo-cli/references/domains.md +5 -5
- package/assets/skills/fimo-cli/references/hosting.md +5 -4
- package/assets/skills/fimo-cli/references/preview.md +1 -1
- package/assets/skills/fimo-cli/references/projects.md +5 -5
- package/assets/skills/fimo-code/SKILL.md +1 -0
- package/assets/skills/fimo-code/references/assets.md +4 -2
- package/assets/skills/fimo-code/references/best-practices/next.md +0 -2
- package/assets/skills/fimo-code/references/content/schema.md +4 -1
- package/assets/skills/fimo-code/references/design.md +2 -2
- package/assets/skills/fimo-code/references/frameworks/astro.md +37 -1
- package/assets/skills/fimo-code/references/frameworks/compatibility.md +5 -5
- package/assets/skills/fimo-code/references/frameworks/hosting.md +23 -2
- package/assets/skills/fimo-code/references/frameworks/seo-head.md +78 -0
- package/assets/skills/fimo-code/references/frameworks/sveltekit.md +57 -4
- package/assets/skills/fimo-migration/SKILL.md +4 -0
- package/assets/skills/fimo-migration/references/qa.md +6 -0
- package/assets/skills/fimo-studio/references/billing-and-credits.md +7 -4
- package/assets/skills/fimo-studio/references/seo-settings.md +2 -0
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +11 -10
- package/dist/runtime/seo/head.d.ts +31 -0
- package/dist/runtime/seo/head.js +47 -0
- package/dist/runtime/seo/index.d.ts +1 -0
- package/dist/runtime/seo/index.js +1 -0
- package/dist/runtime/seo/resolver.d.ts +16 -2
- package/dist/scripts/sync-schemas.js +12 -5
- package/package.json +8 -8
- package/templates/astro/.fimo/config.json +1 -0
- package/templates/astro/AGENTS.md +1 -1
- package/templates/astro/astro.config.mjs +1 -0
- package/templates/astro/package.json +2 -2
- package/templates/astro/src/layouts/Base.astro +20 -4
- package/templates/astro/src/pages/[locale]/index.astro +1 -1
- package/templates/astro/src/pages/[locale]/projects/[slug].astro +4 -1
- package/templates/astro/src/pages/index.astro +1 -1
- package/templates/astro/src/pages/projects/[slug].astro +4 -1
- package/templates/nextjs/package.json +3 -3
- package/templates/react-router/package.json +4 -4
- package/templates/sveltekit/AGENTS.md +1 -1
- package/templates/sveltekit/package.json +2 -2
- package/templates/sveltekit/src/routes/+layout.server.ts +4 -0
- package/templates/sveltekit/src/routes/+layout.svelte +12 -0
- package/templates/sveltekit/src/routes/[[locale=locale]]/+page.svelte +0 -5
- package/templates/vite/package.json +4 -4
|
@@ -145,7 +145,7 @@ These fire at specific moments in the project lifecycle. **Surface them proactiv
|
|
|
145
145
|
- **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
146
|
- **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
147
|
- **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
|
|
148
|
+
- **Adding another deploy tool**. Fimo handles deploys; don't bolt another platform on.
|
|
149
149
|
- **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
150
|
- **Hardcoding tokens in flags** — use the credentials written by `fimo login` (one file per backend at `~/.config/fimo/credentials/<host>-<hash>.json`).
|
|
151
151
|
- **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.
|
|
@@ -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
|
|
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
|
|
102
|
-
- **`fimo deploy --publish`** —
|
|
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
|
-
|
|
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
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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`.
|
|
55
|
-
- **"I want to buy a domain"** → `search` → `pricing` → `buy`.
|
|
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
|
|
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. **
|
|
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
|
|
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.
|
|
@@ -57,9 +57,9 @@ them are present.
|
|
|
57
57
|
{
|
|
58
58
|
"redirects": [
|
|
59
59
|
{
|
|
60
|
-
"source": "/
|
|
61
|
-
"has": [{ "type": "header", "key": "x-
|
|
62
|
-
"destination": "/
|
|
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
|
|
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
|
|
@@ -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
|
|
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.
|
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
27
|
-
runtime imports. The current CLI generates content clients through
|
|
28
|
-
for those projects and does not require `fimo-react
|
|
29
|
-
<exact-version>` only when the developer
|
|
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.
|
|
115
|
-
provider-specific deployment file, preserve it; that file remains authoritative.
|
|
136
|
+
Never generate hosting rewrites from it.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Astro and SvelteKit SEO
|
|
2
|
+
|
|
3
|
+
Resolve route data, apply the app's policy, then convert. Both imports are pure
|
|
4
|
+
and bundle-safe. Neither reads files, fetches content, discovers a route, nor
|
|
5
|
+
sets framework caching. Use the installed package's exports.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { resolveSeoForPath, toSeoHead, type FimoSEO } from 'fimo/seo';
|
|
9
|
+
import config from '../../.fimo/config.json'; // adjust to the actual file
|
|
10
|
+
|
|
11
|
+
const resolved = resolveSeoForPath(pathname, config, { article });
|
|
12
|
+
const seo: FimoSEO = { ...resolved, title: String(article.title) };
|
|
13
|
+
const head = toSeoHead(seo, { canonicalUrl });
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`resolveSeoForPath` combines global defaults and the matching catalog route's
|
|
17
|
+
`seo`. Supply the actual pathname, including the app's locale/base path, and
|
|
18
|
+
the already-loaded data named by templates such as `{{article.title}}`.
|
|
19
|
+
Unresolved tokens fall back for the entire field. The route catalog is not a
|
|
20
|
+
router. For domain/custom locale routing, the app selects locale-specific
|
|
21
|
+
values explicitly. No global defaults are required to use route SEO.
|
|
22
|
+
|
|
23
|
+
All `FimoSEO` fields are optional strings:
|
|
24
|
+
|
|
25
|
+
| Fields | Output |
|
|
26
|
+
| ---------------------- | --------------------------------------------------------------------------------- |
|
|
27
|
+
| `title`, `description` | Native title/description and matching Open Graph/Twitter values |
|
|
28
|
+
| `image` | Open Graph and Twitter share image |
|
|
29
|
+
| `favicon` | Icon and apple-touch-icon links |
|
|
30
|
+
| `siteName`, `locale` | Open Graph site name and locale |
|
|
31
|
+
| `twitterSite` | Twitter site account |
|
|
32
|
+
| `robots`, `themeColor` | Native meta tags |
|
|
33
|
+
| `url` | Site base only. The app computes `canonicalUrl`; it emits canonical and `og:url`. |
|
|
34
|
+
|
|
35
|
+
`toSeoHead` returns `{ title?, meta, links }`. No configured values produces
|
|
36
|
+
empty arrays. Absent/empty fields emit no corresponding tags. The default
|
|
37
|
+
social type/card are `website`/`summary_large_image`; use the existing head
|
|
38
|
+
component for article tags, alternate languages, JSON-LD, and other app-owned
|
|
39
|
+
metadata. Filter a converter attribute before replacing that same tag.
|
|
40
|
+
|
|
41
|
+
Preserve editor-owned settings through resolution; do not copy their initial
|
|
42
|
+
values into app constants that overwrite config. Derive content-owned title
|
|
43
|
+
and description from the same loaded entry or singleton as the visible page,
|
|
44
|
+
including Home/About. Pass that data to resolution or compose its current
|
|
45
|
+
values before conversion. A correct first render does not prove editability.
|
|
46
|
+
|
|
47
|
+
App values win only where intentionally required. Keep overrides together and
|
|
48
|
+
record their reason in the existing code or handoff, not a new ownership
|
|
49
|
+
registry. Set `image: undefined` to remove a
|
|
50
|
+
global image, or `robots: 'noindex'` for an editorial page before conversion. An
|
|
51
|
+
explicit `undefined` in a spread removes a field; use conditional spreads to
|
|
52
|
+
retain defaults for missing optional overrides. Resolve once, then compose;
|
|
53
|
+
do not resolve again after applying policy.
|
|
54
|
+
|
|
55
|
+
Pass a final absolute canonical URL from the app's production URL policy.
|
|
56
|
+
`new URL(pathname, seo.url).href` fits a root-hosted starter; preserve existing
|
|
57
|
+
base paths, domains, trailing slashes and query policy in other apps. Never use
|
|
58
|
+
the preview/request origin as a production canonical. Omit `canonicalUrl` to
|
|
59
|
+
emit neither canonical nor `og:url`.
|
|
60
|
+
|
|
61
|
+
For existing apps, inventory the current head owner and extend it in place.
|
|
62
|
+
Do not add duplicate tags or overwrite unrelated metadata. Framework-escape
|
|
63
|
+
attributes; never render a raw HTML string. Each new route must use the app's
|
|
64
|
+
SEO path, with route data where needed. Verify title, description, canonical,
|
|
65
|
+
robots and social values in built HTML, not only the browser tab title.
|
|
66
|
+
|
|
67
|
+
Imported JSON is a build snapshot. Studio config changes need sync and
|
|
68
|
+
rebuild/redeploy. Content freshness follows the app's SSR/prerender/cache
|
|
69
|
+
policy; changing a helper does not change that policy.
|
|
70
|
+
|
|
71
|
+
For SEO integration acceptance, use an authorized isolated project to change
|
|
72
|
+
one inherited setting and one content-owned value after the initial render.
|
|
73
|
+
Follow the app's sync/build/cache policy, then compare built HTML and the
|
|
74
|
+
hydrated head; verify intentional overrides remain unchanged. Restore the
|
|
75
|
+
test values. Include client navigation and Back where supported. Never mutate
|
|
76
|
+
customer production data for this check. If edits or rendering are unavailable,
|
|
77
|
+
report freshness unproven. `fimo validate` checks declared contracts, not rendered
|
|
78
|
+
head propagation; a green result or helper import is not this acceptance proof.
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Use this reference when `fimo describe --json` reports
|
|
4
4
|
`framework.slug: "sveltekit"`. SvelteKit keeps owning routes, load functions,
|
|
5
|
-
locale resolution, links, document metadata, and SEO
|
|
5
|
+
locale resolution, links, document metadata, and per-page SEO; Fimo supplies the
|
|
6
|
+
site-wide SEO defaults from Studio's Settings → SEO.
|
|
6
7
|
|
|
7
8
|
## Compatibility
|
|
8
9
|
|
|
@@ -12,7 +13,7 @@ SvelteKit 1 or Svelte 4 projects are compatible.
|
|
|
12
13
|
|
|
13
14
|
## Install both packages
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
SvelteKit-specific APIs live in `fimo-sveltekit`, installed at the same version
|
|
16
17
|
as `fimo`:
|
|
17
18
|
|
|
18
19
|
```bash
|
|
@@ -95,9 +96,10 @@ export async function load(event) {
|
|
|
95
96
|
<script lang="ts">
|
|
96
97
|
import { afterNavigate } from '$app/navigation';
|
|
97
98
|
import { FimoProvider } from 'fimo-sveltekit/components';
|
|
98
|
-
import type { LayoutData } from './$types';
|
|
99
99
|
import type { Snippet } from 'svelte';
|
|
100
100
|
|
|
101
|
+
import type { LayoutData } from './$types';
|
|
102
|
+
|
|
101
103
|
let { data, children }: { data: LayoutData; children: Snippet } = $props();
|
|
102
104
|
|
|
103
105
|
afterNavigate(() => {
|
|
@@ -110,6 +112,57 @@ export async function load(event) {
|
|
|
110
112
|
</FimoProvider>
|
|
111
113
|
```
|
|
112
114
|
|
|
115
|
+
## SEO defaults
|
|
116
|
+
|
|
117
|
+
Resolve SEO in the existing server load and return `seoHead`. Preserve the
|
|
118
|
+
load's other data, including labels. A content page resolves after its read:
|
|
119
|
+
`resolveSeoForPath(event.url.pathname, config, { article })`, applies app
|
|
120
|
+
overrides, and returns its complete `seoHead` using `toSeoHead`.
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// src/routes/+layout.server.ts, or a content page's +page.server.ts
|
|
124
|
+
import { resolveSeoForPath, toSeoHead } from 'fimo/seo';
|
|
125
|
+
import config from '../../.fimo/config.json';
|
|
126
|
+
|
|
127
|
+
export function load({ url }) {
|
|
128
|
+
const seo = resolveSeoForPath(url.pathname, config);
|
|
129
|
+
return {
|
|
130
|
+
seoHead: toSeoHead(seo, {
|
|
131
|
+
canonicalUrl: seo?.url ? new URL(url.pathname, seo.url).href : undefined,
|
|
132
|
+
}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Render the final merged route data from one head owner. A leaf load's
|
|
138
|
+
`seoHead` replaces the default head as a whole.
|
|
139
|
+
|
|
140
|
+
```svelte
|
|
141
|
+
<!-- Inside the existing root layout, alongside its provider and children -->
|
|
142
|
+
<script lang="ts">
|
|
143
|
+
import { page } from '$app/state';
|
|
144
|
+
const head = $derived(page.data.seoHead ?? { meta: [], links: [] });
|
|
145
|
+
</script>
|
|
146
|
+
|
|
147
|
+
<svelte:head>
|
|
148
|
+
<title>{head.title ?? 'My site'}</title>
|
|
149
|
+
{#each head.meta as attributes}<meta {...attributes} />{/each}
|
|
150
|
+
{#each head.links as attributes}<link {...attributes} />{/each}
|
|
151
|
+
</svelte:head>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Do not add a second page title beside root social tags. Use the same final
|
|
155
|
+
values for all tags and check client navigation, including returning to a page
|
|
156
|
+
without overrides. Existing apps can keep their current head component and
|
|
157
|
+
extend it in place.
|
|
158
|
+
|
|
159
|
+
The example canonical policy fits a root-hosted site; preserve existing
|
|
160
|
+
production domains, base paths and trailing slashes. Imported config needs
|
|
161
|
+
sync and rebuild/redeploy. Content freshness follows the app's load,
|
|
162
|
+
prerender and cache policy.
|
|
163
|
+
|
|
164
|
+
Read `references/frameworks/seo-head.md` for the field and composition contract.
|
|
165
|
+
|
|
113
166
|
Generated values are serialized at a `load` boundary and hydrated in the
|
|
114
167
|
component that renders them. Use `Text`, `RichText`, `Image`, `Video`, `Date`,
|
|
115
168
|
`DateTime`, `Boolean`, `Json`, and `Number` from
|
|
@@ -142,7 +195,7 @@ component, read Fimo preview environment variables, or inject Fimo scripts.
|
|
|
142
195
|
|
|
143
196
|
## Boundaries
|
|
144
197
|
|
|
145
|
-
- SvelteKit owns routing, history, 404s, locale URLs, and SEO.
|
|
198
|
+
- SvelteKit owns routing, history, 404s, locale URLs, and per-page SEO; the root layout renders Fimo's site-wide SEO defaults.
|
|
146
199
|
- `fimo-sveltekit/vite` owns dev source tagging only.
|
|
147
200
|
- `FimoProvider` owns labels and the optional Studio preview bridge.
|
|
148
201
|
- Do not add React, React Query, or a Vite SPA fallback to a SvelteKit project.
|
|
@@ -224,6 +224,10 @@ report the exact failed command and setup requirement.
|
|
|
224
224
|
- Content data/code workers -> `references/workers/content-execution.md`.
|
|
225
225
|
- Independent validator -> `references/workers/validator.md`.
|
|
226
226
|
- Next.js source -> `references/frameworks/nextjs.md`.
|
|
227
|
+
- Astro/SvelteKit SEO -> the target's `fimo-code` framework reference and
|
|
228
|
+
`frameworks/seo-head`. Preserve the existing head owner and URL policy;
|
|
229
|
+
follow its value-ownership and edit-and-render contract, preserving
|
|
230
|
+
intentional source overrides rather than freezing editor-owned values.
|
|
227
231
|
- React Router/Vite source -> load the target project's `fimo-code`
|
|
228
232
|
`frameworks/react-router`, `frameworks/vite-react`, and
|
|
229
233
|
`frameworks/hosting` references as applicable.
|
|
@@ -67,6 +67,12 @@ items.
|
|
|
67
67
|
categories, tags, redirects, and locales are preserved when present.
|
|
68
68
|
- Existing SEO, OG, and social behavior - including dynamic OG image routes -
|
|
69
69
|
is preserved or explicitly reported as a gap.
|
|
70
|
+
- Editor-owned SEO remains connected to its setting, entry, or singleton.
|
|
71
|
+
Inspect the implementation lane's before/after edit-and-render receipt from
|
|
72
|
+
an authorized isolated target, including preserved intentional overrides and
|
|
73
|
+
required rebuild/cache steps. If absent, report freshness unproven and hand
|
|
74
|
+
back a bounded test; this read-only validator does not mutate content.
|
|
75
|
+
`fimo validate` and matching initial tags do not prove later edits propagate.
|
|
70
76
|
- When the source has no low-risk SEO or social value, safe defaults derived
|
|
71
77
|
from verified page/site data are present or the missing behavior is reported;
|
|
72
78
|
the migration must not invent marketing claims.
|
|
@@ -19,13 +19,13 @@ From a linked project directory, `fimo credits` shows the same organization bala
|
|
|
19
19
|
|
|
20
20
|
## Buying More Credits
|
|
21
21
|
|
|
22
|
-
Buying credits is available
|
|
22
|
+
Buying credits is available while a paid plan is effective, including after scheduling its cancellation. Cancellation stops automatic spending immediately but keeps the current plan until renewal. A deliberate credit purchase still charges the payment method on file.
|
|
23
23
|
|
|
24
24
|
1. Click the credit display near the chat input.
|
|
25
25
|
2. Click **Buy credits**.
|
|
26
26
|
3. Enter a dollar amount (up to $10,000) or pick one of the presets: **$25**, **$50**, **$100**, or **$200**.
|
|
27
|
-
4.
|
|
28
|
-
5. Confirm the purchase. Your card on file is charged and the credits are added
|
|
27
|
+
4. Check the rate shown in the dialog. It comes from your current plan, so the same dollar amount can buy a different number of credits on Pay as you go than on Pro.
|
|
28
|
+
5. Confirm the purchase. Your card on file is charged and the credits are added after confirmation; there is no separate checkout page to complete. If confirmation stays pending, retry the same purchase or contact support. Do not start another purchase to replace an unresolved one.
|
|
29
29
|
|
|
30
30
|
## Refilling Credits Automatically
|
|
31
31
|
|
|
@@ -33,7 +33,7 @@ Organization billing admins on a paid plan can configure auto-refill from **Sett
|
|
|
33
33
|
|
|
34
34
|
1. Choose the balance threshold that should trigger a refill.
|
|
35
35
|
2. Choose the dollar amount to purchase when the balance crosses that threshold.
|
|
36
|
-
3.
|
|
36
|
+
3. Check the plan rate shown in the dialog, then save. Fimo charges the payment method on file and buys credits at that rate when the balance crosses the threshold.
|
|
37
37
|
|
|
38
38
|
Turn auto-refill off from the same control. Fimo does not keep a separate copy of this configuration; the Billing page always shows the provider's current setting. Leaving a paid plan clears auto-refill, and billing admins retain the off-switch if provider cleanup is delayed.
|
|
39
39
|
|
|
@@ -54,6 +54,9 @@ From there:
|
|
|
54
54
|
## Changing or leaving a paid plan
|
|
55
55
|
|
|
56
56
|
- Free to Pay as you go or Pro, and Pay as you go to Pro, use checkout and take effect after payment succeeds.
|
|
57
|
+
- Cancelling Pay as you go or Pro stops auto-refill and paid bandwidth immediately. The current plan, remaining allowances, credits, and reset date stay unchanged until Free takes over at renewal. Manual credit purchases remain available while the paid plan is active.
|
|
58
|
+
- Automatic spending cannot be enabled while cancellation is scheduled. Keep your plan first; then you can immediately enable auto-refill and paid bandwidth independently. Keeping the plan itself leaves both off.
|
|
59
|
+
- Usage before cancellation remains payable. Enabling paid bandwidth again does not make usage from the off-period billable.
|
|
57
60
|
- Pro to Pay as you go or Free takes effect at the end of the current billing period. Billing shows the destination and effective date until then.
|
|
58
61
|
- Choosing the current plan again before that date cancels the scheduled change.
|
|
59
62
|
- Pay as you go requires an active payment method. Removing its only valid card returns the organization to Free immediately.
|
|
@@ -24,6 +24,8 @@ This is the image that shows up when someone shares your link on social media (F
|
|
|
24
24
|
|
|
25
25
|
All SEO changes auto-save as you make them. However, a small amber reminder appears in the top-right corner: "Publish your website to apply your changes." Click Publish to push the changes to your live site.
|
|
26
26
|
|
|
27
|
+
Current templates include SEO wiring. For older Next.js, Astro or SvelteKit sites, ask the coding agent to update Fimo and connect these values to the app's existing SEO flow. Route-specific content must reach that flow too. Load the matching recipe: `fimo skills get fimo-code --ref frameworks/next`, `fimo skills get fimo-code --ref frameworks/astro`, or `fimo skills get fimo-code --ref frameworks/sveltekit`.
|
|
28
|
+
|
|
27
29
|
## Why SEO Matters
|
|
28
30
|
|
|
29
31
|
- **Favicon** -- Makes your site look professional and easy to find among open tabs.
|