Developers Site building

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 is src/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 under public/

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 matching pages entry (and nav if it should appear in navigation) in the same change set before push.
  • Delete / rename: update or remove the file, pages entry, and any nav item together. Then set a real HTTP redirect with frontpage redirects set --from /old --to /new so 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 seo block of site.ts (favicon, ogImage, siteName, canonicalBase when on a custom domain). Per-page overrides use <BaseLayout> props.
  • Prefer frontpage seo get|set for metadata tweaks without a full file rewrite. See Content.
  • Customize src/pages/404.astro if needed; keep <meta name="frontpage:404" content="true" />. Never add /404 to nav or pages.
  • robots.txt / sitemap.xml are platform-managed. Do not invent a Sitemap line. Use noindex on BaseLayout / seo set to 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 /404 or a redirect from to nav / 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 upload for 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 returned sitePath (/__media/uploads/<slug>/…) in markup. Never raw *.blob.vercel-storage.com URLs. Optional raster sizing: append ?w=320|640|960|1280 on /__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