Copy-paste Claude Code prompts for Astro 4 — content collections, framework islands, server endpoints, MDX. Hybrid rendering with React/Svelte islands.
Astro punishes over-shipping JS. The default Claude pattern is to reach for React islands eagerly — that's the wrong default for an Astro site. The prompts below force Claude to justify every island and keep zero-JS where possible.
Add a 'guides' content collection.
Schema (zod):
- title: string, max 80
- description: string, max 160
- pubDate: date
- updatedDate: date.optional()
- author: enum ['team', 'community']
- tags: array(string), max 5
- draft: boolean.default(false)
Constraints:
- Add the collection to src/content/config.ts — keep alongside the existing
'blog' collection.
- Create src/pages/guides/[...slug].astro that renders one entry. Read
src/pages/blog/[...slug].astro first as the template.
- Create src/pages/guides/index.astro listing entries sorted by pubDate desc,
filtering out draft: true.
- Add MDX support if not already enabled in astro.config.mjs (check first).
- DO NOT add a React island for the list — it's static.
The /pricing page needs an interactive monthly/yearly toggle that swaps prices.
Implement it.
Constraints:
- This is the ONE place a framework island is justified. Use the Svelte
toggle component we already have at src/components/PriceToggle.svelte.
- Hydrate with client:visible — NOT client:load (don't block initial render).
- The toggle persists choice in localStorage so a refresh restores it.
- All prices and feature copy still render in .astro at build time. Only the
toggle behaviour is client-side.
In the .astro file, add a top-of-component comment explaining why this island
exists. One sentence.
Add src/pages/api/contact.ts that accepts POST with { name, email, message }
and forwards to Postmark.
Constraints:
- export const prerender = false (it's a runtime endpoint)
- Validate body with zod — schema in src/lib/schemas/contact.ts
- 400 on invalid, 500 on Postmark failure, 200 on success
- Postmark API key from import.meta.env.POSTMARK_KEY — never inline
- Rate limit: simple in-memory bucket keyed by IP from request headers,
10/min. Acceptable for low-traffic; note this in a comment.
- Add the corresponding form on src/pages/contact.astro — no JS, use the
standard form submit with the action attribute
## Stack
Astro 4, Svelte 5 islands (sparingly), Tailwind v4, MDX for long-form content.
## Conventions
- Default to .astro (zero JS). Islands need a one-line justification comment.
- Content in src/content// with zod schemas in config.ts.
- Endpoints in src/pages/api/ with `export const prerender = false`.
- No client:load unless on the critical path — prefer client:visible / client:idle.
Related: testing prompts.