Agent instructions for the Idol or Bust project - an Astro.js template for research project websites.
Idol or Bust is simple website software for research projects that want to understand their user needs. Built with Astro.js, Tailwind CSS, and TypeScript strict mode.
bun dev # Start dev server at localhost:4321
bun run build # Build for production to ./dist
bun preview # Preview production build locally
bun storybook # Start Storybookbun run lint # Run ESLint on source files
bun run typecheck # Run TypeScript type checking
bun run format # Format code with Prettierbun add <package> # Add a dependency
bun add -d <package> # Add a dev dependency
bun remove <package> # Remove a dependencysrc/
├── components/ # Reusable UI components
│ ├── atoms/ # Atomic components (Button)
│ ├── molecules/ # Compound components (Card)
│ ├── organisms/ # Sections (Team, SocialLinks)
│ └── templates/ # Page-level composition (optional)
├── layouts/ # Page layouts (BaseLayout, BlogLayout)
├── pages/ # File-based routing and colocated content (_articles)
├── styles/ # Global styles and Tailwind config
└── utils/ # Helper functions and utilities
public/ # Static assets served directly
- Maintainability over everything else - Prioritize readable, understandable code
- Clean code standards - Follow SOLID principles, meaningful names, small functions
- No backward compatibility constraints - This is a new project, make good decisions
- Documentation - Keep this file and README.md updated with architectural decisions
- Keep documentation concise and maintainable
- Prefer linking to the source-of-truth file over duplicating large config examples
- When documenting configuration, show a short quick-start and point to the canonical file (for branding:
src/pages/_brandConfig.ts) - Update docs in the same PR when behavior, APIs, or customization paths change
- Document content architecture decisions (for example, colocating collection content under
src/pages/**/_articles)
- Strict mode is enabled - no implicit any, strict null checks
- Prefer explicit types over
any- useunknownwhen type is truly unknown - Use Zod for runtime validation of external data
- Prefer
interfacefor object shapes,typefor unions/primitives - Define Props interfaces at the top of
.astrofiles
// Good
export interface Props {
title: string;
items: readonly string[];
}
// Avoid
const data: any = fetchData();- Use
@/alias for all src imports - Group imports: external packages → internal modules → types
- Named imports preferred over default imports
- Barrel exports via
index.tsfiles
// Good
import { Button, Card } from "@/components";
import type { CollectionEntry } from "astro:content";
// Avoid
import { Button } from "@/components/atoms/Button";.astrofiles for static/presentational components- One component per file
- PascalCase for component names
- kebab-case for file names
- Props interface named
Propsat file top
---
export interface Props {
title: string;
variant?: 'primary' | 'secondary';
}
const { title, variant = 'primary' } = Astro.props;
---- Tailwind CSS utility classes in templates
- Custom utilities in
src/styles/global.cssunder@layer components - Mobile-first responsive design (sm:, md:, lg: breakpoints)
- Use semantic color names from theme (primary, secondary)
<!-- Good -->
<button
class="rounded-lg bg-primary-600 px-4 py-2 text-white hover:bg-primary-700"
>
<!-- Avoid -->
<button class="rounded-lg bg-blue-500 px-4 py-2"></button>
</button>| Type | Convention | Example |
|---|---|---|
| Files | kebab-case | blog-post.astro |
| Components | PascalCase | BlogPost |
| Functions | camelCase | formatDate() |
| Variables | camelCase | pageTitle |
| Constants | SCREAMING_SNAKE_CASE | MAX_ITEMS |
| CSS classes | kebab-case | .container-prose |
- Validate external data with Zod schemas
- Throw descriptive Error messages with context
- Use Astro's error pages for 404/500 handling
- Never catch and silently ignore errors
// Good
const result = schema.safeParse(data);
if (!result.success) {
throw new Error(`Validation failed: ${result.error.message}`);
}
// Avoid
try {
something();
} catch (e) {
/* ignore */
}- Do not add comments for obvious code
- Document design decisions that are not obvious
- Document side effects and non-local impacts
- Use JSDoc for exported utility functions
// Good: Explains non-obvious decision
// Using UTC to avoid timezone issues in blog post dates
const pubDate = new Date(post.data.pubDate).toUTCString();
// Avoid: States the obvious
// Get the title
const title = post.data.title;Blog posts are managed via Astro Content Collections:
- Posts located in
src/pages/blog/_articles/ - Resources located in
src/pages/resources/_articles/ - Schema defined in
src/content.config.ts - Use
.mdxfor posts with components - Required frontmatter: title, description, pubDate
---
title: Post Title
description: Brief description for SEO (max 160 chars)
pubDate: 2026-02-20
author: Research Team
tags: [research, updates]
draft: false
---Define site-specific page copy directly in the frontmatter script blocks of .astro page files.
- Keep
.astropages focused on layout, rendering, and wiring content collections. - Keep reusable global identity, SEO defaults, and link metadata in
src/pages/_brandConfig.ts.
Use conventional commits format:
type(scope): brief description
[optional body]
Types: feat, fix, docs, style, refactor, test, chore
Important: Never add yourself as a co-author. The user takes ownership when code is committed.
- Platform: GitHub Pages
- Base path:
/idolbust/ - Site URL:
https://yourusername.github.io - Update
astro.config.mjswith your actual GitHub username
The project includes sitemap and RSS feed generation. On push to main, GitHub Pages will build and deploy automatically if configured.
When making changes, update these files as needed:
- AGENTS.md - This file (coding standards, commands)
- README.md - Project documentation
- package.json - When adding/removing dependencies
- src/content.config.ts - When adding new content types