dnsc-io/AGENTS.md

204 lines
4.9 KiB
Markdown

# AGENTS.md - Agentic Coding Guidelines
This file provides guidelines for AI coding agents working in this repository.
## Project Overview
- **Type**: Astro web application (static site generator)
- **Language**: TypeScript
- **Framework**: Astro 5.x
- **Package Manager**: pnpm
- **Module System**: ES Modules (`"type": "module"`)
- **Shell**: Either use `bash` when in `direnv` or `fish` when used on my personal devices. Do not use `zsh`
## Project Structure
```
src/
├── assets/ # Image assets (SVGs, images)
├── components/ # Reusable Astro components (.astro files)
├── layouts/ # Layout components wrapping pages
└── pages/ # File-based routing (each file = a route)
public/ # Static assets served at root (favicons, etc.)
dist/ # Build output (gitignored)
```
## Build/Lint/Test Commands
### Development
```bash
pnpm install # Install dependencies
pnpm dev # Start dev server at localhost:4321
pnpm build # Build production site to ./dist/
pnpm preview # Preview production build locally
```
### Type Checking
```bash
pnpm astro check # Run Astro + TypeScript type checking
```
### Formatting
Use prettier for formatting
### Testing
No testing framework is currently configured. When tests are added:
```bash
# Future: Run all tests
pnpm test
# Future: Run a single test file
pnpm test path/to/file.test.ts
# Future: Run tests matching a pattern
pnpm test -t "pattern"
```
## Code Style Guidelines
### Formatting (Biome)
- **Indentation**: Tabs (not spaces)
- **Quotes**: Double quotes for strings
- **Semicolons**: Required (Biome default)
- **Trailing commas**: Use trailing commas in multiline structures
- **Line width**: 80 characters (Biome default)
### Imports
- Imports are auto-organized by Biome
- Order: External packages first, then internal modules
- Use named imports when possible
- Prefer explicit imports over namespace imports
```typescript
// Good
import { useState, useEffect } from "react";
import { Button } from "../components/Button";
// Avoid
import * as React from "react";
```
### TypeScript
- **Strict mode enabled** via `astro/tsconfigs/strict`
- Always provide explicit types for function parameters
- Use `interface` for object shapes, `type` for unions/intersections
- Avoid `any` - use `unknown` if type is truly unknown
- Use optional chaining (`?.`) and nullish coalescing (`??`)
```typescript
// Good
interface Props {
title: string;
description?: string;
}
function greet(name: string): string {
return `Hello, ${name}`;
}
// Avoid
function greet(name): any {
return "Hello, " + name;
}
```
### Naming Conventions
- **Files**: kebab-case for utilities (`format-date.ts`), PascalCase for components (`Button.astro`)
- **Components**: PascalCase (`WelcomeBanner`, `NavBar`)
- **Functions/Variables**: camelCase (`getUserData`, `isLoading`)
- **Constants**: UPPER_SNAKE_CASE for true constants (`MAX_RETRIES`, `API_BASE_URL`)
- **Types/Interfaces**: PascalCase (`UserProfile`, `ApiResponse`)
- **Boolean variables**: Prefix with `is`, `has`, `should`, `can` (`isVisible`, `hasError`)
### Astro Components
- Use `.astro` extension for Astro components
- Frontmatter goes between `---` fences at the top
- Props interface defined in frontmatter
- Scoped styles with `<style>` tag (scoped by default)
```astro
---
interface Props {
title: string;
class?: string;
}
const { title, class: className } = Astro.props;
---
<h1 class={className}>{title}</h1>
<style>
h1 {
color: var(--text-color);
}
</style>
```
### Error Handling
- Use try/catch for async operations
- Provide meaningful error messages
- Log errors appropriately for debugging
- Handle edge cases explicitly
```typescript
try {
const data = await fetchData();
return data;
} catch (error) {
console.error("Failed to fetch data:", error);
throw new Error(`Data fetch failed: ${error.message}`);
}
```
### Comments
- Use JSDoc for public functions and complex types
- Keep comments concise and meaningful
- Prefer self-documenting code over comments
- Use `// TODO:` for planned improvements
- Use `// FIXME:` for known issues
```typescript
/**
* Formats a date for display in the UI.
* @param date - The date to format
* @param locale - Optional locale string (defaults to 'en-US')
* @returns Formatted date string
*/
function formatDate(date: Date, locale = "en-US"): string {
return date.toLocaleDateString(locale);
}
```
## Development Environment
This project uses Nix Flakes for reproducible development environments:
```bash
# If using direnv (recommended)
direnv allow
# Or manually enter the dev shell
nix develop
```
The Nix shell provides: Node.js, pnpm, PostgreSQL, and language servers.
## Before Committing
1. Run type checking: `pnpm astro check`
2. Run formatting: `pnpm format` (prettier)
3. Build successfully: `pnpm build`
4. Test locally if applicable: `pnpm preview`