Developers
Site building
How to build Frontpage Astro sites correctly via the CLI: pages registry, tokens, SEO, modules, and craft defaults.
Frontpage sites are Astro projects. Coding agents editing via
pull/push should follow the same product contract as the in-editor agent. Without
inventing backends or editing platform-owned files. Deep command examples live under
Content & settings and File sync.
In the CLI package: frontpage help site-building and AGENTS.md.
Stack
- Astro 6 + TypeScript + Tailwind CSS v4
- Pages under
src/pages/(home issrc/pages/index.astro) - Every page wraps content in
<BaseLayout title="…" description="…"> - Design tokens:
src/config/tokens.ts - Site registry (title, nav, pages map, optional seo):
src/config/site.ts - Components under
src/components/; static assets underpublic/
Page registry (site.ts)
The pages map is the path registry (which URL paths exist), not the authority for the browser tab
title. Real title/description come from each page’s <BaseLayout> props.
- Add a page: create
src/pages/…and add a matchingpagesentry (andnavif it should appear in navigation) in the same change set before push. - Delete / rename: update or remove the file,
pagesentry, and anynavitem together. Then set a real HTTP redirect withfrontpage redirects set --from /old --to /newso bookmarks and search keep working. -
Path mapping:
index.astro→/,about.astro→/about,blog/index.astro→/blog.
One file per URL
For sets of similar pages (services, locations, guides, case studies), prefer one discrete
.astro file per URL plus a shared layout component. Do not default to
getStaticPaths() over a local src/data/*.ts array. Those pages are hard to edit
individually in the product. Exception: Store product pages — one src/pages/products/item.astro (or shop) with data-fp-store-product, not one file per item. Blog/news/essay content belongs in the
Articles module (frontpage articles), not a hand-rolled data-driven template.
Hard product fences
- No backends. No API routes, serverless functions, or databases.
- No fake forms or checkout. Use real modules (
data-fp-*markup +frontpage modules) or Frontpage Store (Store) — never a fake cart or card form. Per-key CLI usage: Modules (frontpage modules <key>). - Astro only. Do not migrate the site to another framework.
- Quoted attributes vs frontmatter. In frontmatter JavaScript, a backslash-quote is an
escape. In an Astro attribute it is not. The quote after
href=closes the string and the next token fails the compile. Put HTML in a frontmatter const and pass it as an expression (auditBody={auditBody}), or use an expression attribute. Never put an HTML tag or a backslash-quote inside a quoted JSX attribute.
Platform-owned vs customer files
Sync only src/, public/, content/. Platform overlay / scaffold paths are
rejected (examples: BaseLayout.astro, module/extension shells, package.json,
astro.config.mjs). Customer layouts such as DocsLayout.astro or
GuideLayout.astro are fine when they are site-owned.
Shared chrome
Prefer src/components/Header.astro and src/components/Footer.astro imported on every
page (including article landings). Alternatively set chrome: { managed: true } in
site.ts for config-driven chrome from nav. Opt out per page with
<BaseLayout chrome={false}>.
Design tokens
tokens.ts is a typed contract. Keep required groups/keys:
colors (primary, secondary, background, text, muted, border),
fonts (sans, serif, mono; optional display),
spacing (xs–xl), radii (base, full). Optional article group for
article-only overrides. Prefer surgical edits over rewriting the whole file; do not rename keys or redefine the
type. Style pages with CSS variables / token-backed Tailwind (e.g.
text-[color:var(--color-muted)]), not hardcoded brand colors.
Fonts: browse the installed catalog with
frontpage fonts [--slot serif] [--query elegant] and copy the exact value string.
Preferred path: set a brand role with
frontpage tokens set --group fonts --key sans --value "…" (same CAS / active-run rules as push),
then apply font-sans / font-serif / font-mono / font-display
(or var(--font-*)) on elements. The build bundles catalog faces when the family string appears in
tokens.ts and/or in a real CSS font-family / fontFamily /
font-['…'] context under site source. Not from prose alone. Inline catalog accents can load after
rebuild; off-catalog families silently fall back to system fonts.
SEO, favicon, 404
-
Site-wide defaults live in the
seoblock ofsite.ts(favicon, ogImage, siteName, canonicalBase when on a custom domain). Per-page overrides use<BaseLayout>props. -
Prefer
frontpage seo get|setfor metadata tweaks without a full file rewrite. See Content. -
Customize
src/pages/404.astroif needed; keep<meta name="frontpage:404" content="true" />. Never add/404tonavorpages. -
robots.txt/sitemap.xmlare platform-managed. Do not invent a Sitemap line. Usenoindexon BaseLayout /seo setto keep pages out of search.
Redirects (301 / 308)
A permanent URL move is a row in the site redirect table, not a page and not a file. The hop is an HTTP
301 or 308 on the live host. Instant, no push or compile.
frontpage revert does not undo redirects; frontpage redirects rm does.
frontpage redirects list
frontpage redirects set --from /old --to /new
frontpage redirects set --from /agents --to /agent --status 308
frontpage redirects rm --from /old - Same-origin pathnames only (
/old→/new). No host,//, query, or hash. - Do not ship
Astro.redirect,location.replace, or a meta refresh for a permanent move. Those are 200s. - Never add
/404or a redirectfromtonav/pages. - If a page file still exists at
from, delete it in the same change so visitors hit the hop.
Deep command examples: Content & settings.
People CRM
People CRM is a platform capability, not a data-fp-* module. Use
frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide.
Inbox stays the raw submission ledger. Hide is not a legal delete. Full logic,
identity rules, status machine, and v1 map:
People CRM.
Store
Frontpage Store holds the catalog. The page is yours. Use
frontpage store items|variants|categories|settings|orders|payments|connect|status|disconnect
for products, stock, store-wide checkout, Service fee, fulfillment, and Stripe.
Integer cents only ($49.99 is 4999).
Stock --add / --remove are signed delta.
Write a data-fp-store-grid + data-fp-product-card and a
data-fp-cart + data-fp-cart-line on the page (every store control carries
data-fp-requires="store"). Frontpage fills from the Store catalog.
A product page is one src/pages/products/item.astro (or shop) with
data-fp-store-product, filled from the live Store item.
Product description is a small markdown subset. First paragraph is the card;
the product-page bind is <div data-fp-store-bind="description">.
Do not use a leading underscore. Do not write one typed file per product. Do not invent
getShopItems on the site. Grid href/url default to
/products/{itemId}. Checkout is store-wide
(frontpage store settings set-checkout). Pay now extras open the cart drawer —
do not write a pay modal or /__shop/choose.
Stripe connect is frontpage store connect. Full guide:
Store.
Modules & articles (summary)
Real lead forms use <form data-fp-form="slug"> with named inputs. No custom submit JS,
honeypot, or action. Do not put a CRM webhook or token in markup; HubSpot / Pipedrive / Privyr
copies are a site-level destination, then a per-form attach. See
Forms destinations.
Do not fake card fields or checkout. Manage lifecycle with
frontpage modules / frontpage articles. To migrate a folder of pages into Articles, prefer
frontpage prompt "migrate … into the articles module" rather than a fragile mass delete/write.
Google reviews use data-fp-google-reviews / data-fp-google-ask with
data-fp-requires="google_reviews". Never fake quote cards or a guessed Maps href; see
Content & settings.
Craft defaults
-
Common sections (hero, features grid, pricing, testimonials, FAQ with
<details>, CTA band, footer) are good defaults. Always styled from the site’s tokens, not a stock template look. - When asked for real copy, do not leave lorem/TODO placeholders. For large pages: push a complete skeleton first, then grow section by section across edits/pushes.
-
Media:
frontpage media uploadfor a file you already have (images/PDFs ≤25 MB, video MP4/WebM/MOV ≤50 MB, SVG/text ≤4 MB proxy).frontpage images generate --prompt "…"[--count N]invents 1–4 AI variations of one picture (counts against AI $ and storage). Reference the returnedsitePath(/__media/uploads/<slug>/…) in markup. Never raw*.blob.vercel-storage.comURLs. Optional raster sizing: append?w=320|640|960|1280on/__media/…image paths only (not video).
Workflow reminder
frontpage pull # or when tipDrift
# edit allowlisted files following this contract
frontpage diff --json
frontpage push --message "…"
# review https://<subdomain>.frontpage.host. Do not publish unless asked