# 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 `` that automatically adds `Authorization: Bearer ` 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