Add CLAUDE.md with project guidance for Claude Code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-03-17 22:40:22 +01:00
parent daa4ea17b1
commit 1281ed4a6a
+108
View File
@@ -0,0 +1,108 @@
# 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
```bash
# 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 CMS `GET` requests)
- 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:**
1. `src/middleware.ts` loads the `app` bundle from CMS once per request → `Astro.locals.translations`
2. In Astro components: `const translations = Astro.locals.translations ?? {}`; use `t(translations, T.key)`
3. In Svelte (SSR): wrap with `<TranslationProvider>` and use `useTranslate()` hook
4. **In `client:load` islands:** `useTranslate()` has no Svelte context during SSR → pass `translations` as a prop from the Astro page and use static `t(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 `TopBanner` fullwidth 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`.