This file provides guidelines for AI coding agents working in this repository.
This is an Astro 5 blog/website project with TypeScript, TailwindCSS v4, and DaisyUI. The project uses content collections for blog posts, RSS feeds, and sitemap generation.
Run all commands from the project root:
| Command | Action |
|---|---|
pnpm dev |
Start local dev server at localhost:4321 |
pnpm build |
Build production site to ./dist/ |
pnpm preview |
Preview production build locally |
pnpm astro ... |
Run Astro CLI commands (e.g., astro check) |
pnpm format |
Format code with Prettier |
pnpm format:check |
Check formatting without changing files |
pnpm lint |
Run ESLint |
pnpm lint:fix |
Auto-fix ESLint issues |
- Indentation: Tabs (2 space width)
- Semicolons: None
- Quotes: Double quotes
- Trailing commas: ES5 style
- Print width: 80 characters
- Arrow function parentheses: Always
- Line endings: LF
strictNullChecks: trueis enabled- All .astro, .ts, and .tsx files are type-checked
- Uses TypeScript ESLint parser for .ts/.tsx files
- Uses Astro ESLint parser for .astro files
- Includes jsx-a11y plugin for accessibility rules
astro/no-set-html-directiveis intentionally disabled- Prettier config handles formatting (no conflicts with ESLint)
- Components: PascalCase (
Header,Footer,BlogPost) - Component files: PascalCase (
Header.astro,BaseHead.astro) - Pages: kebab-case routes (
blog/index.astro,[...slug].astro) - Constants: UPPER_SNAKE_CASE (
SITE_TITLE,SITE_DESCRIPTION) - Functions/variables: camelCase
- Types/Interfaces: PascalCase
- Props interface: Always named
Props
- Relative/local imports (components, styles, consts)
- Astro built-in imports (
astro:content,astro:assets,astro/types) - Third-party packages (
@lucide/astro)
Example:
import Header from "../components/Header.astro"
import { getCollection } from "astro:content"
import { Github } from "@lucide/astro"Use the standard Astro fence pattern:
---
// Imports first
import type { HTMLAttributes } from "astro/types"
import Header from "./Header.astro"
// Define Props interface
interface Props {
title: string
date: Date
}
// Destructure props at top
const { title, date } = Astro.props
---
<!-- Template below -->
<Header />
<h1>{title}</h1>Blog posts live in src/content/blog/ as .md or .mdx files. Frontmatter is type-validated through src/content.config.ts using Zod schemas:
export const collections = { blog }Schema fields:
title: string (required)description: string (required)pubDate: Date (coerced from string)updatedDate: Date (optional)heroImage: image (optional)
Use getCollection("blog") to fetch posts in pages.
- Global styles: Defined in
src/styles/global.css - TailwindCSS: Available via
@tailwindcss/viteplugin - DaisyUI: Component classes available
- Custom CSS: Can be scoped in
<style>tags within components - CSS variables: Theme colors defined as CSS variables in
:root
- Use semantic HTML elements (
<header>,<main>,<nav>,<article>) - Provide
aria-labelfor icon-only links and decorative images - Use
aria-hidden="true"for decorative icons - Ensure proper heading hierarchy
- Use
alt=""for decorative images, meaningful alt text otherwise
- Always define
Propsinterface for components receiving props - Use type assertions carefully (
type Props = CollectionEntry<"blog">["data"]) - Leverage Astro's built-in types (
HTMLAttributes<"a">,CollectionEntry)
- Use optional chaining and nullish coalescing for potentially undefined values
- Example:
const { image = FallbackImage } = Astro.props - Render conditional content with logical AND:
{heroImage && <Image src={heroImage} />}
const posts = (await getCollection("blog")).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
)export async function getStaticPaths() {
const posts = await getCollection("blog")
return posts.map((post) => ({
params: { slug: post.id },
props: post,
}))
}<a class:list={[className, 'base-class', isActive ? 'active-class' : '']} />src/
├── components/ # Reusable Astro components
├── content/ # Markdown/MDX content (blog posts)
├── layouts/ # Page layout components
├── pages/ # File-based routing
├── styles/ # Global CSS
├── assets/ # Static assets (images, fonts)
├── consts.ts # Global constants
└── content.config.ts # Content collection schemas
Always run:
pnpm lint(orpnpm lint:fixif auto-fixable)pnpm format:check(orpnpm formatif needed)pnpm buildto ensure production build succeeds