Skip to content

Project Starters

packages/astro-template holds the Astro projects the editor scaffolds new sites from. templates/ is the source of truth and is designed to live in (and be released from) its own repo, cloned into new projects at creation time. Its root holds one directory per starter:

  • plain/ — as plain as it can be: Astro + Tailwind, the data-module behaviour system, and the dormant Sanity starter. Every navigation is a full page load.
  • motion/ — plain plus the animation core in src/lib/: Lenis smooth scroll, Taxi seamless page transitions (wired into the module lifecycle), hey global state, and unified rAF/resize subscriptions. Skipped inside the editor canvas iframe, which stays a plain document.

The starter is chosen at project creation and recorded in the project’s package.json (plyy.starter).

Resolution order (implemented in apps/app/src-tauri/src/bun.rs, template_dir(app, starter)):

  1. PLYY_TEMPLATE_DIR — explicit local checkout; hot re-wiring while working on the starters themselves. Beats everything. May point at the starters root or (legacy) a single template.
  2. This monorepo’s templates/<starter> — live source in dev.
  3. Cloned cache — a shallow clone of the standalone template repo (PLYY_TEMPLATE_REPO, default vallafederico/plyy-template), refreshed on every project create. Built apps use this, so starter releases ship without an app update. Old single-template clones still resolve as a fallback.
  4. Bundled snapshot — build-time copy inside the app resources (templates/<starter>, legacy templates/astro-basic) — offline first-run fallback.
  • LayoutsBaseLayout and PageLayout (header/footer shell)
  • ComponentsSection (container wrapper), Card, Button, Hero, SiteHeader, SiteFooter
  • Pages/, /about, /contact
  • Modules — the data-module behaviour runtime plus starter modules (see Modules). In motion projects, modules should return a teardown — page content is swapped in-place by Taxi; in plain projects a full page load resets everything, so teardowns are optional.
  • Editor bridgesrc/integrations/editor-bridge.ts, synced into projects on open. Identical across starters (enforced by bridge.test.ts).
  • Sanity startersrc/sanity/ (trimmed turbo-solid schema: home + page via createPage, pageSlices, shared blocks, header/footer/SEO singletons) plus sanity.config.ts, sanity.cli.ts, and src/lib/sanity.ts. Dormant until the editor’s Connect CMS flow installs deps and writes .env; bridge sync restores missing files but never overwrites user edits. The embedded Studio is branded to match the site via src/sanity/theme.ts.
  • Brand tokenssrc/styles/global.css (@theme, canonical for Tailwind) mirrored in src/lib/brand.ts for JS consumers (the Studio theme today, component systems later). A rebrand is a two-file edit; the files cross-reference each other.
  • Iconsastro-icon + @iconify-json/lucide ship with both starters: <Icon name="lucide:menu" /> inlines SVG at build time (zero client JS). The config guards the integration so older projects without the dep keep working.
  • Fonts — one convention: woff2 files in public/fonts/ (the editor converts ttf/otf on import), @font-face rules plus a --font-<name> @theme token in src/styles/fonts.css (imported by global.css). The token makes Tailwind expose font-<name>. The editor’s Assets panel (Fonts tab) manages this file: it imports font files from the machine (or the OS font folders), and registered families appear in the Typography font dropdown.
  • astro.config.mjs — single env-guarded config, identical across starters. With PUBLIC_SANITY_PROJECT_ID set it lazily activates @sanity/astro and the embedded Studio at /admin. The editor re-copies this file on bridge sync, so config changes migrate existing projects.
  • Motion animation core (motion/src/lib/) — scroll.ts (Lenis on the unified rAF, window.sscroll), pages.ts (Taxi transitions driving the module lifecycle; teardown scoped to the swapped [data-taxi-view] so persistent chrome survives), hey.ts (global reactive state), raf.ts/resize.ts (onRaf/onResize shared loops), easings.ts.

Pages own content, components are chrome. Per-instance text lives in page source (slots/props at the call site), so the visual editor’s source round-trip edits the page, not the shared component. Component internals are edited via their own file.

Terminal window
bash packages/astro-template/publish.sh git@github.com:vallafederico/plyy-template.git

A git subtree push of templates/ to the standalone repo (its root then holds plain/ and motion/).