# Armandine Pre-rendered Svelte gallery site served by Nginx. Build outputs to `build/`; image is built and pushed via Woodpecker CI/CD from this repo. ## Stack - **Site:** Svelte 5 + SvelteKit (TypeScript), `@sveltejs/adapter-static`. Gallery is rendered at build time from `src/lib/media.ts`; lightbox and theme toggle run from a preloaded client script (`static/assets/js/script.js`). - **CSS:** PostCSS (nesting + level 2), component-scoped styles; critical CSS inlined at build time with Beasties. - **Runtime:** `nginx:alpine` (see `Dockerfile`) serves the contents of `build/`. - **Registry:** Gitea at `git.mifi.dev` → image `git.mifi.dev/mifi-holdings/armandine`. - **Deploy:** Portainer on Linode; stack uses this image (no volume for site content). ## Local development ```bash # Install dependencies pnpm install # Dev server with hot reload (http://localhost:5173) pnpm dev # Type-check (Svelte + TypeScript) pnpm check # Lint JS/TS and CSS pnpm lint # Check formatting (CI uses this) pnpm format:check # Fix formatting pnpm format # Build for production (Vite + critical CSS step) pnpm build # Preview the built site (http://localhost:4173) pnpm preview ``` ## Dev container Open the repo in a dev container (VS Code/Cursor: **Dev Containers: Reopen in Container**) for a consistent environment: - **Node 22** (matches CI), with `pnpm install` run after create - **Docker (outside of Docker)** – uses the host Docker socket so you can run `pnpm build` and test the image inside the dev container - **ESLint, Prettier, Stylelint, Svelte** extensions plus format-on-save and fix-on-save Ports: - **5173** – SvelteKit dev server (`pnpm dev`) - **4173** – Preview built site (`pnpm preview`) - **80** – Nginx when running the Docker container locally ## Manual build and push 1. Log in to the Gitea container registry: ```bash docker login git.mifi.dev ``` Use your Gitea username and a token with package permissions. 2. Build the site and Docker image: ```bash pnpm build pnpm docker:build ``` `pnpm build` runs Vite build then Beasties to inline critical CSS into `build/`. The Dockerfile copies `build/` into the image. 3. Push to the registry: ```bash pnpm docker:push ``` Then on the server, redeploy the stack (e.g. Portainer “Pull and redeploy” or your webhook). ## Woodpecker CI/CD Three pipelines (see `.woodpecker/`): | Pipeline | When | What | |----------|------|------| | **ci** | Every push to `main`, every PR | Lint (ESLint + Stylelint), Prettier check, Svelte/TypeScript check | | **build**| Push/tag/manual on `main` only (after ci) | Build site to `build/`, build Docker image, push to `git.mifi.dev/mifi-holdings/armandine` | | **deploy** | After build | Trigger Portainer stack redeploy via webhook | Order: **ci** → **build** → **deploy**. ### Secrets (Woodpecker) Configure in the repo’s Woodpecker secrets: - `gitea_registry_username` – Gitea user for registry login - `gitea_package_token` – Gitea token with package read/write - `portainer_webhook_url` – Portainer stack webhook URL for redeploy - Mattermost/Discord webhook secrets (see `.woodpecker/*.yaml` for notifications) ## Server / Portainer - Stack is defined by `docker-compose.yml` in this repo. - Compose uses the image from the registry (`git.mifi.dev/mifi-holdings/armandine:latest`); no volume for site content (it’s inside the image). - Ensure the server can pull from `git.mifi.dev`. After a push, either let the deploy pipeline trigger the Portainer webhook or manually “Pull and redeploy” the stack. ## Project layout ``` ├── src/ │ ├── app.html # SvelteKit HTML template │ ├── app.css # Global CSS (variables, body, lightbox) │ ├── app.d.ts # App types │ ├── routes/ │ │ ├── +layout.svelte │ │ ├── +layout.ts # prerender = true │ │ ├── +page.svelte # Main page (header, gallery, lightbox markup) │ │ └── +page.ts # Loads media data for build-time gallery │ └── lib/ │ ├── media.ts # Typed gallery media list (used at build time) │ └── components/ │ ├── GalleryFigure.svelte │ └── SiteHeader.svelte ├── static/ # Copied as-is to build root │ ├── robots.txt │ └── assets/ │ ├── js/ # script.js (lightbox, theme), ga-init.js │ ├── media/ # desktop/, tablet/, mobile/, thumbnail/, videos/ │ └── favicon*.png, favicon.ico ├── scripts/ │ └── critical-css.js # Beasties post-step on build/ ├── build/ # Output of pnpm build (Vite + Beasties) ├── Dockerfile # nginx:alpine + COPY build/ ├── docker-compose.yml ├── package.json # Scripts: dev, build, preview, check, lint, format ├── .devcontainer/ ├── .woodpecker/ │ ├── ci.yaml │ ├── build.yaml │ └── deploy.yaml ├── README.md └── AGENTS.md # Guidance for LLM agents ``` ## Version `package.json` version: **1.0.0** (bump when you want to track releases).