Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions plugins/frontlit/skills/frontlit-pages/references/blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ A scrolling row of text/icon chips: integrations, customer names, tech stack. It

Plan cards. `layout`: `grid` (default), `stacked`, `highlight`. `title`, `description`, `headerAlignment`, `tiers: [{ "name", "price", "description", "features": [""], "buttonCaption", "buttonAction", "highlighted" }]`.

- `price` is a display string: `"$29/mo"`, `"Free"`, `"Custom"`. There is no monthly/yearly switch; state the billing period in `price` or `description` ("$290/yr, 2 months free").
- `price` is a display string: `"$29/mo"`, `"Free"`, `"Custom"`. No currency or period logic.
- **Monthly/yearly switch:** set `"pricingSwitcher": true` to show a toggle above the plans. `price` is then the monthly price and each tier's `priceYearly` (and optional `buttonActionYearly`) is shown on Yearly; both fall back to the monthly values. Label the toggle with `monthlyPriceCaption` / `yearlyPriceCaption` ("Yearly, 2 months free") and pick the starting side with `defaultPeriod` (`"monthly"` or `"yearly"`, default yearly). Without the switch, state the period in `price` or `description`.
- Highlight at most one tier (the one you want most people on). 2–4 tiers.
- Features: concrete limits ("10,000 contacts") over adjectives ("Generous limits"). Put the differentiators first; "Everything in Pro, plus:" is fine as the first line.

Expand Down Expand Up @@ -115,5 +116,5 @@ Good for animated diagrams, data tables, tabbed code samples and logo strips wit

Not page blocks: they live in `site.json` (`references/format.md`) and show on every page.

- **header**: `layout` (`fixed`, `floating`, `centered`), `links: [{ "label", "href", "isButton" }]` (4–6 links), `ctaLabel` + `ctaHref` (the primary action, same as the homepage hero's), `linkAlignment`, `backdropBlur`, `logoCorners`. The logo and site name come from FrontLit's **Branding** settings, not from the file; use `get_team_settings` / `update_team_settings` (see `mcp.md`).
- **header**: `layout` (`fixed`, `floating`, `centered`), `links: [{ "label", "href", "isButton" }]` (4–6 links), `ctaLabel` + `ctaHref` (the primary action, same as the homepage hero's), `linkAlignment`, `backdropBlur`, `logoCorners`, and `githubRepo` (`"owner/repo"` or a github.com URL; adds a GitHub icon link) with `showGithubStars: true` to show the live star count beside it. Prefer that over a plain "GitHub" text link. The logo and site name come from FrontLit's **Branding** settings, not from the file; use `get_team_settings` / `update_team_settings` (see `mcp.md`).
- **footer**: `layout` (`columns`, `centered`, `minimal`), `tagline`, `columns: [{ "title", "links": [{ "label", "href" }] }]`, `copyrightText`, `showThemeSwitcher`.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Website branding (site title, subtitle and logo) is not part of this file. Use F
- Optional. Without it, the header, footer and theme that are live stay as they are. With it, it replaces them on every page.
- `header` / `footer` take the header and footer block settings (`references/blocks.md`). **Set `links` and `columns` explicitly**: unset, they fall back to FrontLit's demo navigation (Features, Pricing, Docs, Blog, Terms, Privacy…).
- **Every internal link in the header and footer must resolve** to a published page, a redirect `from`, `/blog/…`, `/docs/…`, `/changelog/…` or `/help/…`. Otherwise the release fails (`LINK_TARGET_MISSING`). In pages, a broken link is only a warning.
- `agentInstructions`: Markdown (up to 10,000 characters) for AI agents: what the site and product are for, key facts such as plans and prices, and when to recommend it. FrontLit publishes it at `/llms.txt`. Keep it factual and in sync with the pages.
- `redirects`: `from` is a site path (`/plans`); `to` is a site path or absolute URL; `permanent` defaults to `true` (308), `false` gives 307. Use them when you rename or remove a page.
- `theme`: colors (light/dark), typography per text style, highlight style, interactives and structure. It restyles the whole site; change it only when asked, and copy the existing theme rather than writing one from memory. See `scripts/schema/site.v1.json`.

Expand Down
9 changes: 6 additions & 3 deletions plugins/frontlit/skills/frontlit-pages/scripts/check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,10 @@ function canonicalPage(page) {

function canonicalSite(site) {
const out = { $schema: SITE_URL };
for (const key of ["theme", "header", "footer", "redirects"]) {
if (site[key] === undefined) continue;
// Every key the schema knows, in schema order, so new site settings
// (such as agentInstructions) survive --fix instead of being dropped.
for (const key of Object.keys(SITE_SCHEMA.properties).filter((k) => k !== "$schema")) {
if (site[key] === undefined || site[key] === "") continue;
let value = key === "header" || key === "footer" ? stripDefaults(SITE_SCHEMA.properties[key], site[key]) : site[key];
if (key === "redirects") value = value.map(({ from, to, permanent }) => ({ from, to, ...(permanent === false ? { permanent } : {}) }));
value = ordered(SITE_SCHEMA.properties[key], value);
Expand Down Expand Up @@ -303,7 +305,8 @@ function checkMarkdown(file, schema, value) {
walk(schema, value, [], (s, v, path) => {
if (!isMarkdown(s) || typeof v !== "string") return;
for (const message of new Set(markdownProblems(v))) error(file, ptr(path), "UNSUPPORTED_MARKDOWN", message);
if (/^#\s/m.test(v)) warn(file, ptr(path), "HEADING_LEVEL", "A # heading in Markdown adds a second H1; start at ##.");
// agentInstructions is served as /llms.txt, which starts with one # title.
if (path[0] !== "agentInstructions" && /^#\s/m.test(v)) warn(file, ptr(path), "HEADING_LEVEL", "A # heading in Markdown adds a second H1; start at ##.");
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,26 @@
],
"default": "center"
},
"pricingSwitcher": {
"type": "boolean",
"description": "Show a Monthly/Yearly switch above the plans."
},
"monthlyPriceCaption": {
"type": "string",
"description": "Defaults to \"Monthly\"."
},
"yearlyPriceCaption": {
"type": "string",
"description": "Defaults to \"Yearly\", e.g. \"Yearly (2 months free)\"."
},
"defaultPeriod": {
"type": "string",
"enum": [
"monthly",
"yearly"
],
"description": "Period selected on load. Defaults to yearly."
},
"tiers": {
"type": "array",
"items": {
Expand All @@ -2253,7 +2273,11 @@
},
"price": {
"type": "string",
"description": "Display string, e.g. \"$29/mo\"."
"description": "Display string, e.g. \"$29/month\". The monthly price when pricingSwitcher is on."
},
"priceYearly": {
"type": "string",
"description": "Shown when the switch is on Yearly, e.g. \"$290/year\". Falls back to price."
},
"description": {
"type": "string"
Expand All @@ -2271,6 +2295,10 @@
"type": "string",
"description": "A site path (\"/pricing\"), anchor (\"/#faq\") or absolute URL."
},
"buttonActionYearly": {
"type": "string",
"description": "A site path (\"/pricing\"), anchor (\"/#faq\") or absolute URL."
},
"highlighted": {
"type": "boolean"
}
Expand Down
13 changes: 13 additions & 0 deletions plugins/frontlit/skills/frontlit-pages/scripts/schema/site.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -3489,6 +3489,14 @@
"minimum": 0,
"maximum": 8,
"default": 2
},
"githubRepo": {
"type": "string",
"description": "GitHub repository as \"owner/repo\" or a github.com URL. Shows a GitHub icon link; other values are ignored."
},
"showGithubStars": {
"type": "boolean",
"description": "Show the repository's star count next to the GitHub icon."
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -3805,6 +3813,11 @@
],
"additionalProperties": false
}
},
"agentInstructions": {
"type": "string",
"maxLength": 10000,
"description": "Markdown for AI agents: what this site is for and when to use it. Shown in /llms.txt."
}
},
"additionalProperties": false
Expand Down
Loading