Coding rules for building performant, accessible Astro sites using TypeScript and Tailwind CSS.
Stop wrestling with hydration bugs, performance bottlenecks, and runtime type errors. These production-tested Cursor Rules transform your Astro development workflow into a predictive, error-free pipeline that ships fast sites by default.
You're building modern web apps with Astro, but your workflow is fragmented:
You need development rules that enforce Astro's architecture—zero-JS by default, type-safe everywhere, performance-first—without slowing you down.
These Cursor Rules create a cohesive development experience that aligns perfectly with Astro's zero-JS philosophy. Instead of fighting the framework, you'll work within patterns that automatically optimize for performance and type safety.
What you get:
Before: Writing props handling manually, forgetting TypeScript interfaces, debugging hydration issues.
With these rules: Cursor automatically generates the complete pattern:
// Generates this complete, type-safe component structure
---
interface Props {
title: string;
publishedAt: Date;
excerpt?: string;
readonly featured?: boolean;
}
const { title, publishedAt, excerpt, featured = false } = Astro.props as Props;
if (!title) throw new Error('Title is required');
---
<article class="prose max-w-4xl mx-auto">
<header class="mb-8">
<h1 class="text-4xl font-bold text-gray-900">{title}</h1>
<time class="text-gray-600 text-sm">
{publishedAt.toLocaleDateString()}
</time>
</header>
{excerpt && <p class="lead text-xl text-gray-700">{excerpt}</p>}
<slot />
</article>
Before: Manual image optimization, forgetting responsive formats, performance issues.
With these rules: Every image follows the performance-first pattern:
<!-- Automatically suggests this optimized pattern -->
<Image
src={heroImage}
width={1200}
height={600}
loading="eager"
format={["avif", "webp", "png"]}
alt={imageAlt}
class="w-full h-96 object-cover rounded-lg"
/>
Before: Runtime errors from CMS data, manual validation, inconsistent patterns.
With these rules: Type-safe content from source to render:
// Auto-generates collection schema
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
publishedAt: z.date(),
tags: z.array(z.string()).default([]),
featured: z.boolean().default(false)
})
});
// Type-safe usage throughout components
const { title, publishedAt, tags } = entry.data; // Fully typed
Copy the complete ruleset into your Cursor Rules settings. The configuration automatically handles:
The rules enforce this optimized directory structure:
src/
├── pages/ # Route-generating pages
├── layouts/ # Shared templates
├── components/ # Reusable UI (kebab-case)
├── styles/ # Global CSS
└── types/ # Shared TypeScript definitions
With rules active, your development flow becomes:
Add these npm scripts for team consistency:
{
"scripts": {
"check": "tsc --noEmit && astro check",
"lint": "eslint . --ext .ts,.tsx,.astro",
"format": "prettier --write .",
"test": "vitest"
}
}
These rules don't just improve your Astro development—they transform it into a predictable, high-performance workflow that scales with your team and delivers fast, accessible websites every time.
Ready to experience development without the constant switching between documentation, debugging, and optimization? Add these rules to Cursor and watch your Astro workflow accelerate.
You are an expert in Astro 4.x, TypeScript 5.x, Tailwind CSS 3.x, Vite 5.x, and modern web performance tooling.
---
Key Principles
- Ship **zero-JS by default**; hydrate only interactive islands.
- Embrace **type safety everywhere** (front-matter, props, environment variables).
- Prioritise **performance & accessibility** over visual flair.
- Prefer **functional, declarative components**; avoid stateful classes.
- Keep concerns separated: content (.md / .astro), logic (.ts), presentation (Tailwind utility classes).
- Follow **convention over configuration** to reduce boilerplate.
- CI must fail on TypeScript, ESLint, and formatting errors.
---
TypeScript Rules
- File types:
• `.astro` → component/front-matter.
• `.ts` → utilities, API, config.
• `.tsx` → React/Vue/Svelte islands if required.
- Always declare a `Props` interface:
```ts
---
interface Props {
title: string;
readonly href?: string;
}
const { title, href = '#' } = Astro.props as Props;
---
```
- Non-prop component: `type Props = Record<string, never>`.
- Components expecting slot content:
```ts
type Props = { children: any };
```
- Enable `strict`, `noImplicitAny`, `exactOptionalPropertyTypes` in `tsconfig.json`.
- Use `type` aliases for unions/intersections; reserve `interface` for object shapes.
- Re-export types from `src/types/index.ts`.
- Prefer enums as string unions: `type Theme = 'light' | 'dark';`.
- Inline generics for helpers: `const cls = <T extends string>(...c: T[]) => c.join(' ');`.
---
Error Handling & Validation
- Run `astro check` or `tsc --noEmit` in pre-commit.
- Validate runtime data (env variables, CMS payload) with Zod:
```ts
import { z } from 'zod';
const Post = z.object({ title: z.string(), body: z.string().min(1) });
const data = Post.parse(await fetchCMS());
```
- In components, **fail fast**:
```ts
if (!Astro.props.title) throw new Error('Title is required');
```
- Return early on error paths; keep happy path last.
- Surface user-friendly messages; never leak stack traces to the client.
---
Astro-Specific Rules
- Directory layout:
• `/src/pages/` → route-generating pages.
• `/src/layouts/` → shared templates.
• `/src/components/` → reusable UI, kebab-case names (`callout-box.astro`).
• `/src/styles/` → global CSS (`globals.css`, `fonts.css`).
- Use **Markdown + MDX** for content. Keep front-matter typed via `content/config.ts`.
- Prefer **Astro Image** for optimisation:
```astro
<Image src={img} width={640} loading="lazy" format={["avif","webp","png"]} />
```
- Hydration directives:
- `client:load` → only when static + no SEO hit.
- `client:idle` → defer to idle.
- `client:visible` → lazy-load when in viewport.
- `client:only="react"` for pure islands.
- For global scripts, add in `src/assets/scripts/` and import via `<script is:inline>`.
- Use `tailwind.config.mjs` (ESM) and reference via `@tailwind base|components|utilities`.
- Customise Tailwind layers; avoid arbitrary values unless design token exists.
- Use **`astro-compress`** integration in production builds (`npx astro add compress`).
---
Tailwind CSS Rules
- Enable JIT (`mode: 'jit'`) – default in v3.
- Purge paths: `['./src/**/*.{astro,ts,tsx,mdx}']`.
- Use **semantic class groups**: `prose`, `btn-primary`, etc., via `@apply` in component-scoped CSS.
- Custom colours go to `theme.extend.colors` using CSS custom properties.
- Keep utility class order: `layout > box-model > typography > state > misc` for readability.
- Limit `max-w-*` to responsive breakpoints; prefer `container` class with `mx-auto`.
---
Testing
- Unit + integration: Vitest + `@astrojs/test`.
```ts
import { render } from '@astrojs/test';
import Card from '../src/components/card.astro';
test('renders title', async () => {
const { getByText } = await render(Card, { title: 'Hello' });
expect(getByText('Hello')).toBeDefined();
});
```
- E2E: Playwright (`astro add playwright`).
- Linting: ESLint with `eslint-plugin-astro`, Prettier.
---
Performance
- Inline critical CSS: `<style is:inline>` for < 2 KB snippets.
- Split bundles via Vite `build.rollupOptions.output.manualChunks`.
- Serve images in AVIF/WebP; fallback to PNG/JPEG.
- Enable HTTP/3 & compression on hosting (Vercel/Cloudflare).
- Use `<link rel="preload">` for fonts and hero images.
---
Security
- Add strict CSP meta in `src/layouts/base.astro`:
```astro
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src 'self' https: data:; script-src 'self' 'unsafe-inline';" />
```
- Sanitize user-generated HTML with `DOMPurify` on server side.
- Use `@astrojs/site-map` & `robots.txt` for SEO hygiene, not security.
- Store secrets in `.env`, never in `astro.config.mjs`.
---
Accessibility
- Every interactive element must have an accessible name.
- Use semantic HTML elements first; ARIA only to enhance.
- Test with `npm run astro a11y` or `axe-playwright`.
- Colour contrast ≥ 4.5:1; verify via Tailwind palette.
---
Deployment
- Preferred: Vercel → `vercel.json` with `outputDirectory: "dist"`.
- Ensure `NODE_VERSION` in env ≥ 18.
- Set `edge_middleware = true` in Netlify `netlify.toml` for SSR/prerender.
---
Scripts
```jsonc
// package.json
{
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"check": "tsc --noEmit && astro check",
"lint": "eslint . --ext .ts,.tsx,.astro",
"format": "prettier --write .",
"test": "vitest"
}
}
```
Follow these rules to produce fast, type-safe, maintainable Astro applications with minimal client JavaScript and a first-class developer experience.