# AGENTS.md — Simple App Template

## Project Structure

```
src/
├── index.ts          # Bun server entry (routes, HMR)
├── index.html        # HTML entry point
├── frontend.tsx      # React root mount
├── index.css         # Tailwind + global styles
├── App.tsx           # Main React component
└── components/       # UI components
build.ts              # Build script (bun run build → dist/)
.officerdev/
└── meta.json         # Project metadata
```

## Tech Stack

- **Runtime**: Bun
- **Language**: TypeScript (strict)
- **Framework**: React 19
- **Styling**: Tailwind CSS v4
- **UI**: shadcn/ui components (Radix UI primitives)
- **Icons**: lucide-react

## Build System

- `bun dev` — starts dev server with HMR
- `bun run build` — produces `dist/` via `build.ts`
- Build uses `bun-plugin-tailwind` for CSS processing
- Output: minified JS/CSS bundles + HTML in `dist/`

## Publishing

This project can be published as a standalone app in officer.dev.

**Version**: Set in `package.json` → `version` field. Bump before republishing.

**Icon**: When publishing, choose from these available lucide icon names:
Activity, Airplay, Archive, BarChart3, Bell, Blocks, BookOpen, Box, BrainCircuit,
Calendar, Camera, ChartPie, CircleDot, Cloud, Code, Compass, CreditCard, Database,
FileText, Folder, Gamepad2, Globe, Heart, Home, Image, Inbox, Layers, Layout,
LineChart, Link, List, Mail, Map, MessageCircle, Monitor, Music, Palette, PenTool,
Play, Puzzle, Radio, Rocket, Search, Settings, ShoppingCart, Star, Sun, Table,
Terminal, Timer, Users, Wand2, Zap

## Iframe Constraints

Published apps run inside an iframe in officer.dev workspace panels:

- **Auth token injection**: The iframe URL includes a `?token=` param. A script is injected into the HTML `<head>` that automatically adds `Authorization: Bearer <token>` to all fetch/XHR requests.
- **Path rewriting**: All absolute paths (`/api/...`, `/assets/...`) are rewritten to go through the serve proxy at `/api/app-serve/{slug}/`. Relative paths work as-is.
- **No direct DOM access**: The app cannot access the parent frame.
- **API access**: Use `fetch('/api/...')` — the injected script rewrites paths and adds auth headers automatically.

## Coding Conventions

- Functional components, arrow functions
- No default exports — use named exports
- Strict TypeScript, no `any`
- Semicolons, single quotes (JS), double quotes (JSX)
- 2-space indentation
- Prefer composition over inheritance
- Keep components small and focused
