This is a Next.js + Tailwind CSS based Axure prototype manager. ## Tech Stack - Next.js (App Router, TypeScript) - Tailwind CSS (atomic utility classes) - Node runtime API Routes - Local filesystem persistence (`data/prototypes`) - Package manager: **pnpm** ## Features - Prototype card navigation homepage - Upload Axure prototype ZIP package manually - Auto-parse and register prototype (ZIP must contain `start.html`) - Open prototype in **new tab** - Dark mode toggle (stored in `localStorage`) - Delete uploaded prototype ## Directory Structure ```text app/ api/prototypes/ route.ts # list + upload [id]/route.ts # delete [id]/[...path]/route.ts # serve prototype files layout.tsx page.tsx components/ AddPrototypeModal.tsx PrototypeCard.tsx ThemeToggle.tsx lib/ prototype.ts store.ts data/ prototypes/ index.json # runtime metadata (auto-generated) /... # unzipped Axure files ``` ## Start Development ```bash pnpm install pnpm dev ``` Open `http://localhost:3000`. ## Build & Run Production ```bash pnpm build pnpm start ``` ## Docker (multi-stage, pnpm) Build image: ```bash docker build -t prototype-manager:latest . ``` Run container: ```bash docker run --rm -p 3000:3000 -v prototype-manager-data:/app/data prototype-manager:latest ``` Notes: - Image uses Next.js `output: "standalone"` and `pnpm` in multi-stage build. - Runtime data is written to `/app/data/prototypes`; mount a volume to persist uploads. - A `docker-entrypoint.sh` runs as root at container start, ensures `/app/data/prototypes` exists and is owned by the app user, then drops to the unprivileged `nextjs` user. This avoids `EACCES` errors even when the volume was created by an earlier image as root — no need to delete the existing volume when upgrading. ## Upload Requirements - Only `.zip` is accepted - ZIP must include `start.html` - Keep Axure relative assets (`resources`, `data`, `images`, etc.) in original structure ## Notes on Deployment This project writes files at runtime (upload/unzip), so it must run in a writable Node environment (self-hosted server/VM/container with persistent volume).