site/AGENTS.md
fiatcode 064a1fcfb6
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
2026-04-13 10:50:25 +07:00

9.1 KiB
Raw Permalink Blame History

Agent Instructions

Compact guidance for OpenCode sessions working on this repository.


Quick Start

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.mjssite 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