Updates to readme
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful

This commit is contained in:
2026-02-13 18:19:29 -03:00
parent 455bc18b3b
commit 6bef0f8254

124
README.md
View File

@@ -1,23 +1,129 @@
# mail-landing # mail-landing
Static landing site for mail.mifi.holdings (HTML/CSS/JS), built to `dist/` and served with nginx in production. Static landing site for **mail.mifi.holdings** (HTML/CSS/JS). Source lives in `src/`, is built to `dist/`, and is served in production by **nginx** inside a Docker container, with **Traefik** as the reverse proxy.
## Dev Container (local development and preview) ---
## Tech stack & frameworks
| Layer | Technology |
| --------------------- | -------------------------------------------------------------------------------------- |
| **Runtime** | Node 22 (dev/build only); production is static files only |
| **Package manager** | pnpm 10.x |
| **Source** | Plain HTML, CSS, JS — no framework (Vite/React/etc.) |
| **Build** | Custom script (`scripts/build.js`): copy, minify, inline critical CSS |
| **Minification** | **Terser** (JS), **clean-css** (CSS) |
| **Critical CSS** | **Beasties** — inlines above-the-fold CSS into HTML (no browser/headless; works in CI) |
| **Lint / format** | ESLint, Stylelint, Prettier, yamllint (for Woodpecker & compose) |
| **Production server** | nginx (Alpine) in Docker |
| **Reverse proxy** | Traefik (via `docker-compose` labels; TLS, gzip, security middlewares) |
| **CI/CD** | Woodpecker CI (Gitea); images pushed to `git.mifi.dev` registry |
---
## Project structure
```
mail-landing/
├── src/ # Source (edited by hand)
│ ├── index.html
│ ├── help/index.html
│ └── assets/
│ ├── css/site.css
│ ├── js/ga-init.js
│ └── images/favicon.svg
├── dist/ # Build output (gitignored in practice; produced by pnpm build)
├── scripts/
│ └── build.js # Build: copy → minify JS/CSS → Beasties inline critical CSS
├── nginx/conf.d/ # nginx config for the container
├── docker-compose.yml # Service definition + Traefik labels for mail.mifi.holdings
├── Dockerfile # nginx:alpine + config + dist/
├── .woodpecker/
│ ├── ci.yml # Lint, format check, build (PR + push to main)
│ ├── build.yml # Build site → Docker image → push to registry
│ └── deploy.yml # Trigger Portainer webhook + Mattermost notifications
├── .devcontainer/ # Dev Container (Node 22 + pnpm) for Cursor/VS Code
└── package.json
```
---
## Architecture (high level)
1. **Develop** in `src/` (HTML/CSS/JS). No bundler; structure mirrors output.
2. **Build** (`pnpm build`): `src/``dist/` (copy, minify JS/CSS, inline critical CSS via Beasties).
3. **Docker image**: `Dockerfile` copies `nginx/conf.d/` and `dist/` into `nginx:alpine`; no Node in the image.
4. **Run**: Container serves `/usr/share/nginx/html` on port 80. Traefik (external) terminates TLS for `mail.mifi.holdings`, applies gzip and security middlewares, and routes to this service on `marina-net`.
5. **Deploy**: Woodpecker runs **ci****build** (site + image + push) → **deploy** (Portainer webhook redeploy + Mattermost).
---
## Local development (Dev Container)
1. **Open in Dev Container** 1. **Open in Dev Container**
In Cursor/VS Code: _Command Palette_**Dev Containers: Reopen in Container** (or **Clone Repository in Container Volume** when opening the repo). In Cursor/VS Code: **Command Palette****Dev Containers: Reopen in Container** (or **Clone Repository in Container Volume** when opening the repo).
The first time will build the container (Node 22 + pnpm) and run `pnpm install`. First time: builds the container (Node 22 + pnpm), runs `pnpm install`.
2. **Preview the site** 2. **Preview the site**
In the container terminal: In the container terminal:
- **Quick preview** (serves `src/` as-is, no build): - **Quick preview** (serves `src/` as-is, no build):
`pnpm preview` `pnpm preview`
- **Production-like preview** (build then serve `dist/`): - **Production-like** (build then serve `dist/`):
`pnpm preview:prod` `pnpm preview:prod`
Port **3000** is forwarded; open **http://localhost:3000** (or use the “Preview” port notification).
Port **3000** is forwarded; open **http://localhost:3000** in the host browser (or use the “Preview” port notification).
3. **Other commands** 3. **Other commands**
- `pnpm build` — build `src/``dist/` (minify JS/CSS, inline critical CSS) - `pnpm build` — build `src/``dist/` (minify JS/CSS, inline critical CSS)
- `pnpm lint` / `pnpm format` — lint and format - `pnpm lint` / `pnpm format` — lint and format
- `pnpm docker:build` — build production image - `pnpm docker:build` — build production image (for local testing; image: `git.mifi.dev/mifi-holdings/mail-landing:latest`)
---
## Build pipeline (what `pnpm build` does)
1. **Clean & copy**`dist/` is removed; `src/` is copied recursively to `dist/`.
2. **Minify JS** — All `.js` files in `dist/` are minified with Terser (no comments).
3. **Minify CSS** — All `.css` files are minified with clean-css (level 2).
4. **Inline critical CSS** — Beasties runs on every `.html` file in `dist/` (default preload behavior; no headless browser).
Output: `dist/` ready to be served or copied into the Docker image.
---
## Deployment (Woodpecker CI/CD)
Pipelines live under `.woodpecker/`. Execution order:
| Pipeline | When | What |
| ------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **ci** (`ci.yml`) | Every PR and every push to `main` | Install → Prettier check → Lint (JS, CSS, YAML) → Build. Mattermost notifications on failure/success. |
| **build** (`build.yml`) | Push/tag/manual on `main`, or deployment event for production | Depends on **ci**. Site build → Docker image build (linux/amd64, tagged with commit SHA + `latest`) → Push to `git.mifi.dev/mifi-holdings/mail-landing`. Mattermost on success/failure. |
| **deploy** (`deploy.yml`) | Same as build (runs after build) | `skip_clone: true`; triggers Portainer webhook to redeploy the stack. Mattermost deploy success/failure. |
**Secrets** (in Woodpecker): `portainer_webhook_url`, `mattermost_*`, `gitea_registry_username`, `gitea_package_token`.
**Production**: Stack is defined in Portainer (using this repos `docker-compose.yml`). Redeploy pulls `git.mifi.dev/mifi-holdings/mail-landing:latest` and restarts the service. Traefik (on `marina-net`) routes `mail.mifi.holdings` to this container with TLS (e.g. Lets Encrypt) and middlewares (gzip, security).
---
## Production runtime (Docker + Traefik)
- **Image**: `git.mifi.dev/mifi-holdings/mail-landing:latest` (nginx:alpine + `nginx/conf.d/` + `dist/`).
- **Compose**: `docker-compose.yml` defines one service, `marina-net`, Traefik labels for `Host(\`mail.mifi.holdings\`)`, TLS, gzip, and security middlewares; healthcheck via `wget`on`/`.
- **nginx**: Serves `/usr/share/nginx/html`; HTML no-cache, JS/CSS long-lived cache; static assets and directory/index handling as in `nginx/conf.d/default.conf`.
---
## Quick reference (pnpm scripts)
| Command | Description |
| ------------------- | ---------------------------------------------- |
| `pnpm build` | Build `src/``dist/` (minify + critical CSS) |
| `pnpm preview` | Serve `src/` on port 3000 (no build) |
| `pnpm preview:prod` | Build then serve `dist/` on 3000 |
| `pnpm lint` | Lint JS, CSS, and Woodpecker/compose YAML |
| `pnpm lint:fix` | Auto-fix lint where supported |
| `pnpm format` | Prettier write |
| `pnpm format:check` | Prettier check only |
| `pnpm docker:build` | Build Docker image (linux/amd64) |
| `pnpm docker:push` | Push image to registry (manual) |