# Contributing to Gitea Mail Templates ## Adding a Theme 1. Run `cd tools && go run . create ` to create a framework-backed theme. 2. Edit `themes//theme.json` and `theme.css`. 3. Run `go run . upstream prepare`, `go test ./...` and `go run . preview all` from `tools/`. 4. Check desktop/mobile previews in English, Simplified Chinese and another official language; submit screenshots with the PR. Theme names use lowercase letters, digits and hyphens, starting with a letter. Themes contain only `theme.json` and `theme.css`. New themes default to `framed` with the `standard` layout; `layout` selects a structural preset from the shared framework. The optional `shared` mode remains CSS-only and does not add framework controls. Shared header, action button, fallback URL, sidebar and footer controls live in `framework/mail/base/`. Structural presets live in `framework/layouts/`; they are framework code, not theme-owned mail templates. `tools/builder/framework.go` is the single alignment layer for official primary-action values and translations. Notification branches, subjects, attachments and contextual links come from downloaded official templates. Do not copy business logic into a theme. ## Design Guidelines - Theme sources define presentation only; the shared framework organizes official mail values and translations into reusable controls. - Use email-compatible CSS in theme sources and presentation markup in the framework. Theme CSS cannot load external resources, generate text or hide official content; the framework's instance-hosted logo is an intentional exception to external-image avoidance. - The fragment validator permits tables, table rows/cells, divs and spans with presentation attributes. Review desktop and 390px mobile layouts. - Test Gmail, Outlook and Apple Mail where available. Browser preview does not simulate every mail client's CSS support. - Preserve the original theme's colors, fonts, borders, header treatment, button/fallback controls and layout. Do not replace established designs with generic cards or invented decorations. - Gallery screenshots must be PNG, at most 50 KiB each; 10–20 KiB is preferred. Capture the current source build with the floating inspector closed. ## Official Snapshot Updates Only the tool-generated `gitea.lock.json` is committed: stable Gitea 28+ tag, immutable commit and file checksums. Official templates, locale JSON files, favicon, license and adapter reference sources are downloaded to ignored `build/upstream/`. Do not maintain copies in the source repository. ### Command Reference Run the following commands from `tools/`. All three subcommands accept `--root ` (default: `..`, relative to the working directory); place this flag after the subcommand. Paths containing spaces must be quoted. ```powershell # From tools/, with an explicit repository root: go run . upstream verify --root "D:\Work\Development\WebSites\GiteaMailTemplates" ``` | Command | Purpose | Network and writes | |---|---|---| | `go run . upstream prepare` | Read the repository lock and prepare its exact inputs | If no cache exists, download files by locked commit, validate SHA-256 and create `build/upstream/`; otherwise verify the existing cache offline. Never changes the root lock. | | `go run . upstream verify` | Audit the existing cache against the root lock | Offline, read-only; does not download files. Reports `[PASS]` and non-English missing-key `[FALLBACK]` lists. | | `go run . upstream sync --tag vX.Y.Z` | Explicitly select an upstream version | Resolve the tag through the GitHub API, download by resolved commit and validate the snapshot; replace the cache and generate `gitea.lock.json`. Requires a stable `vX.Y.Z` tag with major version 28 or later. | There is no implicit `latest`, local Gitea checkout input, token flag or authentication environment-variable support in these commands. Downloads use `api.github.com` (`sync`) and `raw.githubusercontent.com` (`sync`/first `prepare`); network errors and API rate limits are failures, not permission to change versions. Go may separately need network access for its toolchain/modules, even when snapshot verification itself is offline. ### Existing Clone and Offline Use ```bash cd tools go mod download go run . upstream prepare go run . upstream verify go test ./... go run . preview all ``` `build all`, `preview all` and `dev` invoke preparation automatically. They still require the root lock. A complete verified cache and already installed Go dependencies/toolchain allow offline builds. `verify` checks official inputs, adapter reference hashes and official English keys; framework-added keys/action anchors are checked by build and rendering, so `verify` alone is not a compatibility certification. ### Missing Lock and Explicit Version Updates If `gitea.lock.json` is missing, `prepare`, `verify`, build and preview fail when opening it—even if `build/upstream/lock.json` remains. The cache lock is not a substitute. Restore the tracked root lock for a normal clone. For intentional initialization, `sync` does not require a prior root lock: ```bash cd tools # Current source baseline; explicit initialization, not a release operation: go run . upstream sync --tag v28.0.0 go run . upstream verify go test ./... go run . preview all ``` To review another version, replace the tag explicitly (for example, `v28.1.0`, still [PENDING] here). Review the generated lock diff, align the shared framework and fixtures, run all checks and the matching-instance smoke test, then update compatibility documentation. `sync` does not build themes, update Markdown, create Git tags, commit, push or publish a release. It must not be run merely to fix a missing cache. Changed translation or mail-renderer reference hashes block synchronization until the Go adapter is reviewed; downloading a newer version is not enough to approve it. Official English must contain all official template keys; builds additionally validate framework keys. Other languages fall back to English. Validation/network failures before cache replacement leave existing inputs unchanged. Cache replacement and writing the root lock are separate operations: if a filesystem failure leaves them inconsistent, subsequent verification fails; inspect both before retrying. ### Cache Recovery `prepare` refuses corrupt, incomplete or lock-mismatched caches; it does not merge or silently repair them. `sync` also refuses to replace a non-empty invalid snapshot. After inspecting the error, preserve the exact generated cache directory by moving it aside, then run `prepare` using the reviewed root lock. For example, in PowerShell **from the repository root**, choose an unused backup name: ```powershell Move-Item -LiteralPath .\build\upstream -Destination .\build\upstream.backup Set-Location tools go run . upstream prepare go run . upstream verify ``` Do not remove the whole `build/` directory or edit cached official files. To restore a previous version after a deliberate sync, restore its reviewed root lock and rebuild the cache in the same way. Avoid simultaneous `sync`/`prepare`/build processes against one cache; stop `dev` while replacing inputs. Mail types are discovered from the snapshot. `tools/data/templates_config.json` supplies names, descriptions and mock contexts only. A new official mail type requires a fixture before preview can pass. Gitea v28.0.0 has a reviewed Polish `mail.team_invite.text_1` placeholder defect. Preview preserves official behavior and reports `[UPSTREAM-WARN]`; the exception matches the exact official text. Other formatting errors fail rendering. Do not edit locale snapshots to conceal upstream defects. ## Local Development Use **Go 1.24+**. The CLI uses urfave/cli; HTML validation uses Go's x/net HTML parser. Run `go mod download` and `upstream prepare` once; subsequent verified builds work offline. ```bash cd tools go run . list go run . build all go run . preview all go run . dev # http://127.0.0.1:3456 ``` `build` writes installable files to `build/themes//mail/`. `preview` also builds them, then writes a small manifest and one JS bundle per official language. Open `preview/index.html` directly for static preview; its language loader supports `file://`. The loopback development server watches theme CSS/metadata, shared framework, lock/cache and fixtures. It rebuilds in-process and sends SSE reloads. Installable logos reference `{{AppUrl}}assets/img/favicon.png`; only the generated static preview embeds the downloaded official icon for offline display. ## Verification and Release Tests check deterministic framework adaptation and generation, fail-closed action anchors, official keys and preserved notification semantics. Rendering tests cover all themes/languages and push, review, reply, workflow and attachment branches. Shared controls/branding are explicit presentation additions; button labels, fallback targets and logo references are validated separately. Before a release, use an isolated Gitea instance matching the locked tag and trigger a real password-reset or notification email. The administration test-email button bypasses custom templates. Confirm template loading and capture the rendered mail without sending to real users. The optional `tools/integration` test automates this with disposable SQLite, users, Git/SSH paths and loopback SMTP. Set `GITEA_SMOKE_BINARY` to a checksum-verified official binary of the locked version, then run `go test ./integration -v -count=1` from `tools/`. Optional browser QA lives in `tools/qa`: install its dependencies, then run `npm test` after generating preview data; `PREVIEW_DEV_URL` includes HTTP preview checks and `--update-gallery` refreshes screenshots. Release tags must match the snapshot's Gitea version. Add reviewed notes at `.github/release-notes/vX.Y.Z.md`. The workflow verifies the lock and tests, packages generated themes, multilingual preview, documentation and upstream license/provenance, then updates marked release labels. Keep source-only work separate from the published compatibility matrix. Existing historical tags and assets are unchanged. From the repository root, run `python .github/scripts/package_release.py --version vX.Y.Z --output ` after `preview all` for manual packaging. The same script is used by the release workflow. It verifies source/generated hashes and all language bundles, excludes undeclared stale build directories, and refuses to overwrite existing archives. ## Reporting Problems Include the snapshot tag/commit, theme, email type, preview language and error. Run `go run . upstream verify` and `go run . preview all` first; attach screenshots or the relevant render diagnostic. ## Commit Conventions - `style():` — theme presentation - `preview:` — browser preview - `tools:` — CLI/build/snapshot tooling - `docs:` — documentation and translations - `fix:` — bug fixes - `refactor:` — restructuring - `chore:` — maintenance ## Translations and License - English (this document) - [简体中文](docs/CONTRIBUTING.zh-CN.md) Contributions are licensed under MIT. Retain Gitea copyright and the upstream license when distributing derived templates.