Imported from programmierbar/website (
AGENTS.md). Install upstream withnpx skills add programmierbar/website. Copyright stays with the author.
AGENTS.md - Project Guide for AI Assistants
This file provides context for AI assistants working with the programmier.bar website codebase.
Behaviour
Do not automatically commit code changes, unless you were tasked with doing so. Do not automatically push code changes, unless you were tasked with doing so.
Project Overview
A podcast/conference/meetup platform for the German developer community. Built with Nuxt 3 (Vue 3) frontend and Directus 11 headless CMS.
Tech Stack
- Frontend: Nuxt 3, Vue 3, TypeScript, Tailwind CSS, Pinia
- CMS: Directus 11 (headless CMS)
- Server: Nitro (Nuxt's server engine)
- Search: Algolia
- AI: Google Gemini (spam filtering)
- Node: 24 for
nuxt-app— seenuxt-app/.nvmrc, which CI reads too. The Directus extension still builds on 22.
Directory Structure
website/
├── nuxt-app/ # Main Nuxt 3 frontend
│ ├── components/ # 77 Vue components
│ ├── composables/ # 24 Vue composables
│ ├── helpers/ # Utility functions
│ ├── types/ # TypeScript definitions
│ ├── pages/ # File-based routing
│ ├── server/ # Nitro API routes
│ └── config.ts # Feature flags & constants
├── directus-cms/ # Directus CMS instance
│ └── extensions/ # Custom Directus extensions
└── shared-code/ # Shared TypeScript code
Common Commands
Nuxt App (run from nuxt-app/)
npm run dev # Development server
npm run build # Production build
npm run eslint # Lint with auto-fix
npm run prettier # Format code
There is deliberately no static-generation script. See
the upgrade plan for why: a static build has to prerender every
<nuxt-img> variant, which is ~6200 downloads and resizes against the CMS, and it does not finish.
Nothing deployed used it — Vercel runs nuxt build and serves images through _vercel/image.
Directus CMS (run from directus-cms/)
npm run start # Start Directus server
npm run build # Build extensions
npm run migrate:db # Database migrations
Testing
# In directus-cms/extensions/directus-extension-programmierbar-bundle/
npm test # Run Jest tests
Code Principles
Consolidation & DRY
- Never duplicate logic across modules. If a pattern (API access, LLM calls, template handling, schema definitions) is used in more than one place, extract it into a shared abstraction with a clear, generic name.
- Tokens, API keys, and credentials should be managed in one place — not scattered across features.
- Types and schemas belong in established, canonical locations. Don't create new files when existing ones cover the same domain.
No Hidden Behavior
- No fallback values for critical configuration. Fail explicitly if config is missing — silent fallbacks cause data loss or broken state in production.
- No hardcoded defaults buried in business logic (prompts, URLs, feature flags). If it affects behavior, it must be visible and configurable.
- Treat missing or empty data as a failure worth surfacing, not a reason to silently exit.
Observability & Failure Handling
- If a failure requires human intervention, notify through the team's established channel (e.g. Slack). Log-only visibility is insufficient for anything that blocks a workflow.
- Prefer loud failures over silent degradation.
Architectural Decision Records
Significant, cross-cutting technical decisions are documented as ADRs in the
_ADRs/ folder (numbered Markdown files, e.g. 0001-...md). Each ADR captures
the context, the decision, its consequences, and any deferred follow-up. Before
changing build/test tooling, module setup, or other foundational concerns,
check _ADRs/ first — the rationale and known trade-offs are likely already
recorded there. Add a new ADR when you make a decision future contributors would
otherwise have to reverse-engineer.
Further Reading
Additional hints can be found in:
- _ADRs/ — architectural decision records (see above)
- .claude/rules/directus-conventions.md
- .claude/rules/nuxt-conventions.md
Code Style
- Prettier: 120 char width, 4 spaces, no semicolons, trailing commas
- ESLint: Nuxt recommended config with TypeScript
- Imports: Auto-sorted, use
typekeyword for type-only imports - Components: PascalCase, single-word names allowed
Formatting is enforced, not requested
CI runs npm run prettier:check in nuxt-app, so unformatted code fails the build. Nobody should be
expected to remember the formatter — turn on format on save and it never comes up:
- WebStorm: Settings → Languages & Frameworks → JavaScript → Prettier → On save
- VS Code: the Prettier extension, plus
"editor.formatOnSave": true
Both read nuxt-app/.prettierrc on their own, and nuxt-app/.editorconfig covers indentation and line
endings before that is set up. Keep those two in step — they overlap, and an editor that indents to a
different width than Prettier produces a diff on every save. If a PR fails the check, npm run prettier
fixes it — never hand-edit to satisfy it.
Note that npm run lint (ESLint) needs nuxt prepare to have run first, since eslint.config.mjs
extends the generated .nuxt/eslint.config.mjs. npm ci does this via postinstall.
Key Patterns
Type System
Directus types follow a preparation pattern:
DirectusPodcastItem- Raw CMS type with ID referencesPodcastItem- Prepared type with hydrated relationships
Composables
Main composables in nuxt-app/composables/:
useDirectus()- CMS data fetching (most important, 884 lines)usePodcastPlayer()- Podcast playback stateuseProfileCreationStore()- User profile state
Configuration
Feature flags and constants in nuxt-app/config.ts:
FLAG_SHOW_LOGIN- Toggle login UIDEVTOOLS- Enable Nuxt DevTools- Event tracking IDs (80+ constants)
Server API
Email endpoint at /api/email (POST):
- Zod schema validation
- Gemini AI spam filtering
- Honeypot protection
Environment Variables
Key variables (see .env.example if exists):
DIRECTUS_CMS_URL- Directus instance URLWEBSITE_URL- Public website URLNUXT_ENV- 'development' or 'production'ALGOLIA_INDEX- Search index name
Content Types
Main Directus collections:
- Podcasts (deep_dive, cto_special, news, other)
- Meetups & Conferences
- Speakers (Hall of Fame)
- Pick of the Day
Important Files
nuxt-app/nuxt.config.ts- Nuxt configurationnuxt-app/config.ts- App constants & feature flagsnuxt-app/composables/useDirectus.ts- CMS integrationnuxt-app/tailwind.config.js- Tailwind customizationsnuxt-app/types/directus.ts- CMS type definitions
Tailwind Theme
Custom colors: black, white, blue, lime, pink, gray Breakpoints: xs(520), sm(640), md(768), lg(1024), xl(1280), 2xl(1536), 3xl(2000)