Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
RustyAstro is an Astro + Svelte frontend for RustyCMS (a Rust-based CMS). It fetches all content via REST API, generates TypeScript types from the OpenAPI spec, and deploys as a static site to Firebase Hosting.
Requires: RustyCMS running at PUBLIC_CMS_URL (default http://localhost:3000) for development and build.
Commands
# Development (requires RustyCMS running separately)
yarn dev # Generates API types, starts Astro dev server on :4321
# Build
yarn build # Generate types → Astro build → Pagefind indexing
# Preview production build
yarn preview
# Type generation (requires RustyCMS running)
yarn generate:api-types # Regenerate src/lib/cms-api.generated.ts from OpenAPI spec
# Cache management
yarn cache:warm # Pre-populate .cache/cms/ with all common API responses
# Storybook (UI component development)
yarn storybook # Start Storybook on :6006
# Deploy
yarn deploy # Build + firebase deploy
There are no test commands — this project has no test suite.
Architecture
Data Flow
All content comes from RustyCMS via src/lib/cms.ts. At build time, Astro calls CMS functions in getStaticPaths() to generate static pages. A caching layer makes the build resilient to CMS downtime.
RustyCMS API → cms.ts (process cache + disk cache) → Astro pages → Static HTML
CMS Client (src/lib/cms.ts)
The central module for all API access. Key conventions:
slug= URL path (for links, routing)_slug= API/internal ID (for CMSGETrequests)- Slugs are normalized (leading slashes removed)
- Caching: in-process deduplication + disk cache at
.cache/cms/(Node.js only, lazy-imported) - Dev mode: no list-caching so new CMS entries appear immediately
Generated Types
src/lib/cms-api.generated.ts is auto-generated from the OpenAPI spec — never edit manually. Regenerate with yarn generate:api-types after schema changes in RustyCMS.
Page Routing
/→src/pages/index.astro— lists all Pages from CMS/:slug→src/pages/[slug].astro— dynamic page content/post/:slug→src/pages/post/[slug].astro— blog post detail/blog/and/posts/— paginated post lists (both route variants exist)
Content Block System
Pages contain rows of content blocks. Each block type has a corresponding Svelte component in src/components/blocks/. Layout is controlled by src/lib/block-layout.ts using a 12-column Tailwind grid — parent containers need grid grid-cols-12.
i18n / Translations
All UI strings come from a CMS translation bundle, never hardcoded in components.
Flow:
src/middleware.tsloads theappbundle from CMS once per request →Astro.locals.translations- In Astro components:
const translations = Astro.locals.translations ?? {}; uset(translations, T.key) - In Svelte (SSR): wrap with
<TranslationProvider>and useuseTranslate()hook - In
client:loadislands:useTranslate()has no Svelte context during SSR → passtranslationsas a prop from the Astro page and use statict(translations, T.key)instead
Translation keys are defined in src/lib/translations.ts as the TRANSLATION_KEYS array (type-safe). Strings are stored in RustyCMS under content/de/translation_bundle/app.json5. Placeholders use {{name}} syntax.
Image Handling
src/lib/rusty-image.ts proxies image transforms through RustyCMS (/api/transform). Transformed images are cached at public/images/transformed/ and survive builds. The RustyImage component exists in both .astro (SSR) and .svelte (client islands) variants.
Layout
src/layouts/Layout.astro is the master layout. It:
- Wraps content in
<TranslationProvider>for Svelte context - Loads header navigation and footer from CMS
- Optionally renders a
TopBannerfullwidth image - Renders
Breadcrumbs(supports both static labels and translation keys)
Environment Variables
| Variable | Required | Purpose |
|---|---|---|
PUBLIC_CMS_URL |
Yes | RustyCMS base URL (no trailing slash) |
PUBLIC_SITE_URL |
No | Canonical/sitemap URL (production) |
PUBLIC_SITE_NAME |
No | og:site_name and JSON-LD |
PUBLIC_UMAMI_SCRIPT_URL |
No | Analytics |
PUBLIC_UMAMI_WEBSITE_ID |
No | Analytics |
Deployment
Static build deployed to Firebase Hosting. Cache headers: 1-year immutable for assets, 1-hour for HTML. Config in firebase.json and .firebaserc.