# Codebase Structure **Analysis Date:** 2026-03-23 ## Directory Layout ``` DiunDashboard/ ├── cmd/ │ └── diunwebhook/ │ └── main.go # Application entry point ├── pkg/ │ └── diunwebhook/ │ ├── diunwebhook.go # Core library: types, DB, handlers │ ├── diunwebhook_test.go # Tests (external test package) │ └── export_test.go # Test-only exports ├── frontend/ │ ├── src/ │ │ ├── main.tsx # React entry point │ │ ├── App.tsx # Root component (layout, state wiring) │ │ ├── index.css # Tailwind CSS base styles │ │ ├── vite-env.d.ts # Vite type declarations │ │ ├── components/ │ │ │ ├── Header.tsx # Top nav bar with refresh button │ │ │ ├── TagSection.tsx # Droppable tag group container │ │ │ ├── ServiceCard.tsx # Individual image/service card (draggable) │ │ │ ├── AcknowledgeButton.tsx # Dismiss/acknowledge button │ │ │ └── ui/ # shadcn/ui primitives │ │ │ ├── badge.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ └── tooltip.tsx │ │ ├── hooks/ │ │ │ ├── useUpdates.ts # Polling, acknowledge, tag assignment │ │ │ └── useTags.ts # Tag CRUD operations │ │ ├── lib/ │ │ │ ├── utils.ts # cn() class merge utility │ │ │ ├── time.ts # timeAgo() relative time formatter │ │ │ ├── serviceIcons.ts # Map Docker image names to simple-icons │ │ │ └── serviceIcons.json # Image name -> icon slug mapping │ │ └── types/ │ │ └── diun.ts # TypeScript interfaces (DiunEvent, UpdateEntry, Tag, UpdatesMap) │ ├── public/ │ │ └── favicon.svg │ ├── index.html # SPA HTML shell │ ├── package.json # Frontend dependencies │ ├── vite.config.ts # Vite build + dev proxy config │ ├── tailwind.config.ts # Tailwind theme configuration │ ├── tsconfig.json # TypeScript project references │ ├── tsconfig.app.json # App TypeScript config │ ├── tsconfig.node.json # Node/Vite TypeScript config │ ├── postcss.config.js # PostCSS/Tailwind pipeline │ └── components.json # shadcn/ui component config ├── docs/ │ ├── index.md # VitePress docs homepage │ ├── guide/ │ │ └── index.md # Getting started guide │ ├── package.json # Docs site dependencies │ ├── Dockerfile # Docs site Nginx container │ ├── nginx.conf # Docs site Nginx config │ └── .gitignore # Ignore docs build artifacts ├── .claude/ │ └── CLAUDE.md # Claude Code project instructions ├── .gitea/ │ └── workflows/ │ ├── ci.yml # CI pipeline (test + build) │ └── release.yml # Release/deploy pipeline ├── .planning/ │ └── codebase/ # GSD codebase analysis documents ├── Dockerfile # Multi-stage build (frontend + Go + runtime) ├── compose.yml # Docker Compose for deployment (pulls image) ├── compose.dev.yml # Docker Compose for local dev (builds locally) ├── go.mod # Go module definition ├── go.sum # Go dependency checksums ├── .gitignore # Git ignore rules ├── README.md # Project readme ├── CONTRIBUTING.md # Developer guide └── LICENSE # License file ``` ## Directory Purposes **`cmd/diunwebhook/`:** - Purpose: Application binary entry point - Contains: Single `main.go` file - Key files: `cmd/diunwebhook/main.go` **`pkg/diunwebhook/`:** - Purpose: Core library containing all backend logic (types, database, HTTP handlers) - Contains: One implementation file, one test file, one test-exports file - Key files: `pkg/diunwebhook/diunwebhook.go`, `pkg/diunwebhook/diunwebhook_test.go`, `pkg/diunwebhook/export_test.go` **`frontend/src/components/`:** - Purpose: React UI components - Contains: Feature components (`Header`, `TagSection`, `ServiceCard`, `AcknowledgeButton`) and `ui/` subdirectory with shadcn/ui primitives **`frontend/src/components/ui/`:** - Purpose: Reusable UI primitives from shadcn/ui - Contains: `badge.tsx`, `button.tsx`, `card.tsx`, `tooltip.tsx` - Note: These are generated/copied from shadcn/ui CLI and customized via `components.json` **`frontend/src/hooks/`:** - Purpose: Custom React hooks encapsulating data fetching and state management - Contains: `useUpdates.ts` (polling, acknowledge, tag assignment), `useTags.ts` (tag CRUD) **`frontend/src/lib/`:** - Purpose: Shared utility functions and data - Contains: `utils.ts` (Tailwind class merge), `time.ts` (relative time), `serviceIcons.ts` + `serviceIcons.json` (Docker image icon lookup) **`frontend/src/types/`:** - Purpose: TypeScript type definitions shared across the frontend - Contains: `diun.ts` with interfaces matching Go backend structs **`docs/`:** - Purpose: VitePress documentation site (separate from main app) - Contains: Markdown content, VitePress config, Dockerfile for static deployment - Build output: `docs/.vitepress/dist/` (gitignored) **`.gitea/workflows/`:** - Purpose: CI/CD pipeline definitions for Gitea Actions - Contains: `ci.yml` (test + build), `release.yml` (release/deploy) ## Key File Locations **Entry Points:** - `cmd/diunwebhook/main.go`: Go server entry point -- init DB, register routes, start server - `frontend/src/main.tsx`: React SPA mount point -- renders `` into DOM, enables dark mode **Configuration:** - `go.mod`: Go module `awesomeProject`, Go 1.26, SQLite dependency - `frontend/vite.config.ts`: Vite build config, `@` path alias to `src/`, dev proxy for `/api` and `/webhook` to `:8080` - `frontend/tailwind.config.ts`: Tailwind CSS theme customization - `frontend/components.json`: shadcn/ui component generation config - `frontend/tsconfig.json`: TypeScript project references (app + node configs) - `Dockerfile`: Multi-stage build (Bun frontend build, Go binary build, Alpine runtime) - `compose.yml`: Production deployment config (pulls from `gitea.jeanlucmakiola.de` registry) - `compose.dev.yml`: Local development config (builds from Dockerfile) **Core Logic:** - `pkg/diunwebhook/diunwebhook.go`: ALL backend logic -- struct definitions, database init/migrations, event storage, all 6 HTTP handlers - `frontend/src/App.tsx`: Root component -- stat cards, tag section rendering, drag-and-drop context, new group creation UI - `frontend/src/hooks/useUpdates.ts`: Primary data hook -- 5s polling, acknowledge, tag assignment with optimistic updates - `frontend/src/hooks/useTags.ts`: Tag management hook -- fetch, create, delete **Testing:** - `pkg/diunwebhook/diunwebhook_test.go`: All backend tests (external test package `diunwebhook_test`) - `pkg/diunwebhook/export_test.go`: Exports internal functions for testing (`GetUpdatesMap`, `UpdatesReset`, `ResetTags`, `ResetWebhookSecret`) ## Naming Conventions **Files:** - Go: lowercase, single word or underscore-separated (`diunwebhook.go`, `export_test.go`) - React components: PascalCase (`ServiceCard.tsx`, `TagSection.tsx`) - Hooks: camelCase prefixed with `use` (`useUpdates.ts`, `useTags.ts`) - Utilities: camelCase (`time.ts`, `utils.ts`) - shadcn/ui primitives: lowercase (`badge.tsx`, `button.tsx`) **Directories:** - Go: lowercase (`cmd/`, `pkg/`) - Frontend: lowercase (`components/`, `hooks/`, `lib/`, `types/`, `ui/`) ## Where to Add New Code **New API Endpoint:** - Add handler function to `pkg/diunwebhook/diunwebhook.go` - Register route in `cmd/diunwebhook/main.go` on the `mux` - Add tests in `pkg/diunwebhook/diunwebhook_test.go` - If new test helpers are needed, add exports in `pkg/diunwebhook/export_test.go` **New Database Table or Migration:** - Add `CREATE TABLE IF NOT EXISTS` or `ALTER TABLE` in `InitDB()` in `pkg/diunwebhook/diunwebhook.go` - Follow existing pattern: `CREATE TABLE IF NOT EXISTS` for new tables, silent `ALTER TABLE` for column additions **New React Component:** - Feature component: `frontend/src/components/YourComponent.tsx` - Reusable UI primitive: `frontend/src/components/ui/yourprimitive.tsx` (use shadcn/ui CLI or follow existing pattern) **New Custom Hook:** - Place in `frontend/src/hooks/useYourHook.ts` - Follow pattern from `useUpdates.ts`: export a function returning state and callbacks **New TypeScript Type:** - Add to `frontend/src/types/diun.ts` if related to the DIUN domain - Create new file in `frontend/src/types/` for unrelated domains **New Utility Function:** - Add to `frontend/src/lib/` in an existing file or new file by domain - Time-related: `frontend/src/lib/time.ts` - CSS/styling: `frontend/src/lib/utils.ts` **New Go Package:** - Create under `pkg/yourpackage/` following Go conventions - Import from `awesomeProject/pkg/yourpackage` (module name is `awesomeProject`) ## Special Directories **`frontend/dist/`:** - Purpose: Production build output served by Go file server at `/` - Generated: Yes, by `bun run build` in `frontend/` - Committed: No (gitignored) **`docs/.vitepress/dist/`:** - Purpose: Documentation site build output - Generated: Yes, by `bun run build` in `docs/` - Committed: No (gitignored) **`.planning/codebase/`:** - Purpose: GSD codebase analysis documents for AI-assisted development - Generated: Yes, by codebase mapping agents - Committed: Yes **`.idea/`:** - Purpose: JetBrains IDE project settings - Generated: Yes, by GoLand/IntelliJ - Committed: Partially (has its own `.gitignore`) ## Build Artifacts and Outputs **Go Binary:** - Built by: `go build -o server ./cmd/diunwebhook/main.go` (in Docker) or `go run ./cmd/diunwebhook/` (local) - Output: `./server` binary (in Docker build stage) **Frontend Bundle:** - Built by: `bun run build` (runs `tsc -b && vite build`) - Output: `frontend/dist/` directory - Consumed by: Go file server at `/` route, copied into Docker image at `/app/frontend/dist/` **Docker Image:** - Built by: `docker build -t diun-webhook-dashboard .` - Multi-stage: frontend build (Bun) -> Go build (golang) -> runtime (Alpine) - Contains: Go binary at `/app/server`, frontend at `/app/frontend/dist/` **SQLite Database:** - Created at runtime by `InitDB()` - Default path: `./diun.db` (overridable via `DB_PATH` env var) - Docker: `/data/diun.db` with volume mount --- *Structure analysis: 2026-03-23*