docs: add comprehensive AGENTS.md with operational guidance and merged content style rules

- Created AGENTS.md with quick start, architecture, content schema, styling, Prettier, caching, Docker deployment, constraints, common tasks, and gotchas
- Merged content authoring guidelines from AGENT.md (blog post style, tag system with vocabulary and rules)
- Removed redundant AGENT.md file; AGENTS.md is the single source of truth for agent instructions
This commit is contained in:
fiatcode 2026-04-13 10:50:25 +07:00
parent 858f8d927f
commit 064a1fcfb6
No known key found for this signature in database
2 changed files with 204 additions and 78 deletions

204
AGENTS.md Normal file
View file

@ -0,0 +1,204 @@
# Agent Instructions
Compact guidance for OpenCode sessions working on this repository.
---
## Quick Start
```sh
npm install
npm run dev # dev server at http://localhost:4321
npm run build # production build to ./dist/
npm run preview # serve production build locally
npm run format # Prettier across entire codebase
```
**Never skip `npm install` after checkout.** Dependencies are not vendored.
---
## Architecture
- **Framework**: Astro 5 with Tailwind CSS v4 (Vite plugin)
- **Content**: Astro Content Collections — markdown files in `src/content/blog/`
- **Schema**: `src/content.config.ts` — posts require `title`, `description`, `date`; optional `draft`, `tags`
- **Build output**: `dist/` (gitignored). Never commit built files.
- **Deployment**: Docker multi-stage build → `static-web-server` behind Traefik. `compose.yml` defines production service.
---
## Content
Blog posts live in `src/content/blog/`. Frontmatter must match the schema in `src/content.config.ts`.
### Blog Post Style
- **Voice:** First-person, direct, opinionated. No preamble, no "Hope this helps" closings.
- **Opening:** Hook into a specific frustration or observation. Skip the generic intro.
- **Headings:**
- `##` — lede/subtitle (one per post, immediately after the title, punchy)
- `###` — main sections
- `---` — horizontal rule between sections
- No `#` (H1) anywhere in the post body
- **Closing:** End decisively. A statement, not a sendoff.
- **Grammar:** Correct. No "Do you ever wondering", no "Let's get started!"
- **Tone reference:** See the three most recent posts by date.
### Tag System
#### Current Vocabulary
| Tag | Description |
| --------------------- | ------------------------------------------------------------------------- |
| `linux` | Linux-specific content — distros, tools, fixes |
| `flutter` | Flutter framework, mobile development |
| `android` | Android-specific content, ADB, AVD |
| `windows` | Windows-specific content, PowerShell, Win tooling |
| `git` | Git commands, workflows, hosting |
| `hardware` | Physical hardware, drivers, firmware quirks |
| `ai` | AI-assisted development, LLM tools, agents |
| `dev-setup` | Developer environment, tooling, workflow, DX |
| `dart` | Dart language, Dart-specific libraries |
| `go` | Go language |
| `craftsmanship` | Software design, architecture, TDD, DDD, Clean Architecture, code quality |
| `self-hosting` | Self-hosted services, VPS, infrastructure |
| `distributed-systems` | Distributed data, sync, CRDTs, consensus |
| `misc` | Catch-all for posts that don't fit elsewhere |
#### Per-Post Tags (current state)
| Post | Tags |
| -------------------------------------------- | ------------------------------ |
| stop-stashing-use-git-worktree | `git`, `dev-setup` |
| vibe-coding-still-needs-a-craftsman | `ai`, `craftsmanship` |
| building-my-own-self-hosted-music-library | `linux`, `self-hosting` |
| building-load-testing-script-with-claude | `go`, `ai` |
| crdt-conflict-free-replicated-data-types | `dart`, `distributed-systems` |
| fix-adb-unsufficient-permission-linux | `linux`, `android` |
| fix-infinix-air-pro-plus-quad-speakers-linux | `linux`, `hardware` |
| fix-infinix-air-pro-plus-screen-color | `windows`, `linux`, `hardware` |
| flutter-android-emulator-not-showing | `flutter`, `android` |
| flutter-clean-architecture | `flutter`, `craftsmanship` |
| immutable-workstation-fedora-kinoite | `linux`, `dev-setup` |
| kuwot (draft) | `flutter`, `dart` |
| remap-copilot-key-infinix-air-pro-plus | `linux`, `hardware` |
| sign-github-commit-on-windows | `git`, `windows` |
| using-direnv-in-powershell-on-windows | `windows`, `dev-setup` |
| welcome | `misc` |
#### Rules for Tags
**When tagging a post:**
- Use 24 tags per post. More than 4 is a sign you're being too specific.
- Prefer tags from the existing vocabulary above.
- A tag should describe what the post _is about_, not every concept it _mentions_.
**When adding a new tag:**
- Ask: will this tag apply to at least one other existing post, or is it clearly a category this blog will write about again?
- If yes: add it to the vocabulary table above and apply it.
- If no: fold into an existing tag or leave it out.
- Do not add tags for topics covered once and unlikely to recur (e.g. `music`, `testing`, `open-source`).
- Document new tags in this file.
---
## Styling
- Tailwind v4 via `@tailwindcss/vite`. Global styles in `src/styles/global.css`.
- Custom theme: Fira Code font, neutral-900 background, neutral-300 text.
- Expressive Code (`ec.config.mjs`) — code blocks use `dark-plus` theme, no border radius, transparent shadows.
- Pagefind integration provides search index built at `npm run build`.
---
## Prettier
**Format before committing.** The config (`.prettierrc`) uses:
- `prettier-plugin-astro` — parses `.astro` files
- `prettier-plugin-organize-imports` — sorts imports automatically
`npm run format` writes changes in place. No separate lint step exists.
---
## Production Caching
`sws.config.toml` (mounted into Docker container) defines cache headers:
- HTML: `no-cache, must-revalidate` — always revalidate
- Astro assets (`/_astro/*`): `max-age=31536000, immutable` — fingerprinted, cache forever
- Images/fonts: `max-age=604800` — 1 week
Do not change without understanding fingerprinting behavior.
---
## Docker & Deployment
- **Build**: `docker build -t site .` (multi-stage: node:24-alpine → static-web-server)
- **Run**: `docker compose up -d` (uses external `traefik-proxy` network)
- **Port**: Container serves on port 80; Traefik routes `fiatcode.dev` and `www.fiatcode.dev`
- **Config**: `sws.config.toml` mounted at `/config.toml`; `SERVER_CONFIG_FILE` env var points to it.
- **No build args or secrets** — site is fully static.
---
## Important Constraints
- **No test suite** — no `vitest`, `jest`, or similar configured.
- **No CI/CD** — no GitHub Actions workflows in repo.
- **No ESLint** — only Prettier for formatting.
- **Single package** — not a monorepo; all code lives under `src/`.
- **Node version** — Docker uses Node 24; local dev should match (nvm recommended).
- **Generated files**`.astro/` directory is generated; never edit files there.
- **Content assets** — images in `public/images/`; reference with absolute paths like `/images/piko-1.webp`.
---
## Common Tasks
### Add a blog post
1. Create `src/content/blog/<slug>.md` with required frontmatter (title, description, date, draft: false, tags)
2. Run `npm run dev` to verify rendering
3. Run `npm run format`
4. Commit with conventional commit: `feat: add post <title>`
### Update tag vocabulary
Edit the "Current Vocabulary" table and "Per-Post Tags" matrix in this file. Keep both in sync.
### Change site metadata
- Site URL: `astro.config.mjs``site` field
- Title/description per-page: in the page/layout component frontmatter
- Favicon/manifest: replace files in `public/`
### Modify Tailwind theme
Edit `src/styles/global.css``@theme` block and `@layer base` utilities.
---
## Gotchas
- **Port conflict**: Astro dev defaults to port 4321. Change via `npm run dev -- --port <n>` if needed.
- **Content cache**: Astro caches content collections in `.astro/data-store.json` (large, gitignored). Delete if content changes aren't reflected.
- **Image paths**: In markdown, use absolute paths starting with `/` (e.g., `![alt](/images/file.webp)`). Relative paths break in production.
- **Date format**: Use ISO 8601 with timezone offset (e.g., `2024-03-18T14:16:19+07:00`). Astro's date parser is strict.
- **Draft posts**: Set `draft: true` to exclude from builds. `draft` field is optional in schema but recommended for clarity.
- **Prettier on Astro files**: Must have the plugin installed; otherwise formatting corrupts `.astro` syntax. Verified in `devDependencies`.
---
## References
- `astro.config.mjs` — integrations (sitemap, pagefind, expressive-code)
- `src/content.config.ts` — content collection schema and loader
- `sws.config.toml` — production server and cache headers
- `compose.yml` — Docker Compose production service
- `README.md` — basic commands and tech stack