{"name":"build-astro-site","description":"Builds a content site with Astro and TypeScript - pages and layouts, Markdown or MDX content collections with a typed schema, interactive islands only where needed, Tailwind styling, images and SEO basics, then a static or server build. Use when the user wants a blog, docs, marketing or portfolio site with Astro, or asks about islands or content collections.","category":"frontend","tags":["astro","typescript","website"],"models":["any"],"proven":false,"passing_families":0,"model_testing":"Not yet model-tested; testing Jan 2027","url":"https://theskillvault.ai/skills/build-astro-site","api_url":"https://theskillvault.ai/api/skills/build-astro-site","raw_url":"https://theskillvault.ai/api/skills/build-astro-site/raw","body":"# Build an Astro site\n\nAstro ships plain HTML by default and adds JavaScript only to the parts that need it. That makes content sites fast with little effort.\n\n## When to use\n- You are building a blog, docs, portfolio or marketing site.\n- Page speed and SEO matter more than app-like interactivity.\n- You want to write content in Markdown or MDX.\n\n## When not to use\n- You are building a logged-in app with lots of interactive screens. A full app framework such as Next.js or SvelteKit fits better.\n\n## Steps\n1. Create the site: `npm create astro@latest`, choose TypeScript (strict), then `npm run dev`.\n2. Add pages as `.astro` files in `src/pages`; `src/pages/about.astro` becomes `/about`.\n3. Make a shared layout in `src/layouts` with the `<head>`, title and meta description as props.\n4. Put posts in a content collection (`src/content/blog`) and define a typed schema with `defineCollection` and Zod in the content config.\n5. List and render posts with `getCollection` and dynamic routes such as `src/pages/blog/[slug].astro`.\n6. Add interactive parts as islands: a React, Svelte or Vue component with `client:visible` or `client:load`. Leave everything else static.\n7. Add Tailwind with `npx astro add tailwind`, and use Astro's `<Image />` for optimised images.\n8. Add the sitemap integration and an RSS feed, and set the `site` URL in the Astro config.\n9. Build with `npm run build`. Static output deploys anywhere; add an adapter only if you need server rendering.\n\n```astro\n---\nimport { getCollection } from \"astro:content\";\nimport Layout from \"../layouts/Layout.astro\";\nconst posts = (await getCollection(\"blog\")).sort((a, b) => +b.data.date - +a.data.date);\n---\n<Layout title=\"Blog\" description=\"Notes and guides\">\n  {posts.map((p) => <a href={`/blog/${p.id}/`}>{p.data.title}</a>)}\n</Layout>\n```\n\n## Gotchas\n- Code in the `---` frontmatter runs at build or on the server; it never reaches the browser. Still, keep secrets in non-public env vars, as `PUBLIC_` values are exposed.\n- Forgetting a `client:` directive makes a component render as static HTML with no interactivity.\n- `client:load` everywhere throws away Astro's speed advantage. Prefer `client:visible` or `client:idle`.\n- Set the `site` config, or canonical URLs and the sitemap will be wrong.\n\n## Portability\nStatic builds deploy to Vercel, Netlify, Cloudflare Pages or GitHub Pages. If you use React, Svelte or Vue components, Astro supports all of them as islands.\n\n## Example prompt\n\"Build an Astro blog with TypeScript, a typed content collection for posts, Tailwind, a sitemap and an RSS feed.\"\n\n## Done when\n- Pages build as static HTML and only island components ship JavaScript.\n- Posts come from a typed content collection.\n- The sitemap and RSS feed list every post, and `npm run build` passes.\n\n---\nBased on the Astro TypeScript rules file in PatrickJS/awesome-cursorrules (CC0 1.0, public domain). See LICENSE.txt.","files":["LICENSE.txt"],"license":"CC0-1.0","license_name":"CC0 1.0","license_url":"https://creativecommons.org/publicdomain/zero/1.0/","attribution":"Based on work by awesome-cursorrules contributors (astro-typescript rules) (Public domain (CC0 1.0) - rules contributed to PatrickJS/awesome-cursorrules, CC0 1.0), https://github.com/PatrickJS/awesome-cursorrules/blob/b044f956f021b6e8877f16781bcfc466a6a120e9/rules/astro-typescript-cursorrules-prompt-file.mdc; adapted by TheSkillVault, https://theskillvault.ai","install":{"claude_code":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-astro-site/raw' -o ~/'.claude/skills/build-astro-site/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-astro-site/files/LICENSE.txt' -o ~/'.claude/skills/build-astro-site/LICENSE.txt'","cursor":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-astro-site/raw' -o '.cursor/skills/build-astro-site/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-astro-site/files/LICENSE.txt' -o '.cursor/skills/build-astro-site/LICENSE.txt'","agents":"curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-astro-site/raw' -o '.agents/skills/build-astro-site/SKILL.md' && curl -fsSL --create-dirs 'https://theskillvault.ai/api/skills/build-astro-site/files/LICENSE.txt' -o '.agents/skills/build-astro-site/LICENSE.txt'","mcp_url":"https://theskillvault.ai/mcp","cursor_mcp_deeplink":"cursor://anysphere.cursor-deeplink/mcp/install?name=theskillvault&config=eyJ1cmwiOiJodHRwczovL3RoZXNraWxsdmF1bHQuYWkvbWNwIn0%3D","mcp_config":{"mcpServers":{"theskillvault":{"url":"https://theskillvault.ai/mcp"}}}},"bundles":[],"tested_on":[{"family":"chatgpt","name":"ChatGPT","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"claude","name":"Claude","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"gemini","name":"Gemini","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"grok","name":"Grok","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"llama","name":"Llama","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"deepseek","name":"DeepSeek","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"mistral","name":"Mistral","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"qwen","name":"Qwen","outcome":null,"date":null,"source":null,"counts":false,"stale":false},{"family":"kimi","name":"Kimi K","outcome":null,"date":null,"source":null,"counts":false,"stale":false}],"proven_rule":{"threshold":5,"window_days":365,"computed_at":"2026-11-02T03:20:33.817Z"}}