144 lines
5.1 KiB
Markdown
144 lines
5.1 KiB
Markdown
# 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).
|