Updates to readme
This commit is contained in:
122
README.md
122
README.md
@@ -1,23 +1,129 @@
|
||||
# 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**
|
||||
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`.
|
||||
In Cursor/VS Code: **Command Palette** → **Dev Containers: Reopen in Container** (or **Clone Repository in Container Volume** when opening the repo).
|
||||
First time: builds the container (Node 22 + pnpm), runs `pnpm install`.
|
||||
|
||||
2. **Preview the site**
|
||||
In the container terminal:
|
||||
- **Quick preview** (serves `src/` as-is, no build):
|
||||
`pnpm preview`
|
||||
- **Production-like preview** (build then serve `dist/`):
|
||||
- **Production-like** (build then serve `dist/`):
|
||||
`pnpm preview:prod`
|
||||
|
||||
Port **3000** is forwarded; open **http://localhost:3000** in the host browser (or use the “Preview” port notification).
|
||||
Port **3000** is forwarded; open **http://localhost:3000** (or use the “Preview” port notification).
|
||||
|
||||
3. **Other commands**
|
||||
- `pnpm build` — build `src/` → `dist/` (minify JS/CSS, inline critical CSS)
|
||||
- `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 repo’s `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. Let’s 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) |
|
||||
|
||||
Reference in New Issue
Block a user