13 KiB
Contributing to Gitea Mail Templates
Contributions to themes, tooling, tests, documentation and translations are welcome. This guide covers the current source architecture; installation and release selection are described in the README.
Local Development
Use Go 1.24 or later. From the repository root, prepare the dependencies and locked official inputs, then run the checks and generate the preview:
cd tools
go mod download
go run . upstream prepare
go test ./...
go run . preview all
Open preview/index.html in a browser, or run go run . dev from tools/ and visit http://127.0.0.1:3456 for live reload. The development server watches themes, the framework, the lock/cache and preview fixtures.
The CLI uses urfave/cli and the x/net HTML parser. Python 3.11 or later is used by the documentation and packaging checks.
Common Commands
Run these commands from tools/. Place flags before positional arguments.
| Command | Result |
|---|---|
go run . list |
List available themes |
go run . create my-theme |
Create theme metadata and CSS |
go run . build my-theme |
Generate one theme's installable templates |
go run . build all |
Generate every theme |
go run . preview all |
Build every theme and render all official languages |
go run . dev |
Start the development server on port 3456 |
go run . dev --port 3457 |
Use a different local port |
go run . delete my-theme |
Remove the named theme's source directory |
build writes to build/themes/<name>/mail/ and records file and source hashes in build.json. preview also builds the templates, then writes preview/rendered.js and preview/rendered/<locale>.js. These generated files and the downloaded inputs are ignored by Git. Keep them out of contributions.
Adding a Theme
- Run
go run . create my-themefromtools/. - Edit
themes/my-theme/theme.jsonandtheme.css. - Run
go test ./...andgo run . preview allfromtools/. - Check desktop and mobile layouts in English, Simplified Chinese and at least one other official language. Include screenshots with the pull request.
Theme names start with a lowercase letter and may contain lowercase letters, digits and hyphens. A theme directory contains only theme.json and theme.css.
{
"name": "my-theme",
"description": "A short description of the theme",
"mode": "framed",
"layout": "standard"
}
| Mode | Generated presentation |
|---|---|
framed |
Shared controls and a framework layout, styled with the theme's CSS. New themes use this mode with the standard layout. |
shared |
CSS in the official head partial and the official footer partial; no additional framework controls or per-mail overrides. |
Shared Framework
Headers, action buttons, fallback links, sidebars and footers live in framework/mail/base/. Layout presets live in framework/layouts/; the optional layout field selects a preset for framed themes. Colors, fonts and spacing belong in theme CSS.
tools/builder/framework.go adapts official action values and translation keys for the shared controls. Official templates retain responsibility for notification conditions, subjects, attachments and contextual links. Changes to controls or layout structure belong in the framework so all themes use the same adaptation logic.
Layout fragments must form balanced presentation markup. __HEADER__ inserts the shared header, __MAIL_TYPE__ expands to the discovered mail ID, and __SIDEBAR__ inserts the shared sidebar in footer fragments. Deployment logos use {{AppUrl}}assets/img/favicon.png; generated preview data embeds the downloaded icon for offline display.
Design Guidelines
- Use email-compatible CSS. Theme CSS must not load external resources, generate text or hide official content.
- Use presentation markup for layout fragments. The validator accepts
table,tbody,tr,td,divandspanwith supported presentation attributes. - When editing an existing theme, preserve its visual identity: palette, typography, borders, header, buttons and layout.
- Check desktop and 390px mobile previews, including long text and URLs. Test Gmail, Outlook and Apple Mail where available; the browser preview does not emulate mail clients.
- Keep gallery images in PNG format, at most 50 KiB each; 10–20 KiB is preferred. Follow the capture guide for consistent images.
Official Snapshot Updates
gitea.lock.json records a stable Gitea 28+ tag, its commit and per-file SHA-256 hashes. Official mail templates, locale catalogs, the favicon, license and reviewed adapter references are downloaded into build/upstream/. Only the generated root lock is committed; official files are not maintained in the source tree.
Command Reference
Run from tools/. Each upstream subcommand accepts --root <repository-root>, defaulting to .. relative to the working directory. Place the flag after the subcommand and quote paths containing spaces:
go run . upstream verify --root "C:\Projects\GiteaMailTemplates"
| Command | Behavior |
|---|---|
go run . upstream prepare |
Read the root lock. Download and validate its exact inputs if the cache is absent; otherwise verify the existing cache offline. Leaves the root lock unchanged. |
go run . upstream verify |
Check the existing cache against the root lock, offline and read-only. Reports [PASS] and lists non-English missing keys as [FALLBACK]. |
go run . upstream sync --tag vX.Y.Z |
Resolve an explicit stable Gitea 28+ tag through the GitHub API, download and validate its files, then replace the cache and generate the root lock. |
sync uses api.github.com; file downloads use raw.githubusercontent.com. These commands do not accept a local Gitea checkout, authentication tokens or an implicit latest version. Network errors and API rate limits stop the operation. Go may separately need network access to download its toolchain or modules.
Existing Clone and Offline Use
build, preview and dev prepare inputs automatically. They require the committed root lock and validate cached files before use. Once the cache, Go toolchain and dependencies are available, builds can run offline.
Use upstream verify to check the cache independently. It validates official file hashes, reviewed adapter references and official template keys in the English catalog. Build and rendering checks also cover framework translation keys and primary-action anchors, so cache verification is only one part of compatibility testing.
Missing Lock and Explicit Version Updates
For an existing clone, restore the tracked gitea.lock.json if it is missing. The copy at build/upstream/lock.json cannot replace it. When intentionally initializing the lock, run:
cd tools
go run . upstream sync --tag v28.0.0
go run . upstream verify
go test ./...
go run . preview all
To review a different version, specify its tag explicitly. Review the lock diff, update the framework adapter and fixtures as needed, and complete the checks before updating compatibility records. sync changes the cache and lock only; documentation and release publication are separate steps. Use prepare for a missing cache.
Changes to the reviewed translation or mail-renderer sources require an adapter review before their reference hashes can be updated. Official English must contain all referenced keys; other languages use English fallback. New mail types require framework alignment and fixtures in tools/data/templates_config.json, which supplies preview metadata and example contexts. Keep integer values as integers in JSON fixtures for Go formatting.
Network or validation failures before cache replacement leave existing inputs unchanged. Cache replacement and root-lock writing are separate operations; if a filesystem error interrupts them, inspect both before retrying.
Cache Recovery
prepare reports corrupt, incomplete or lock-mismatched caches without repairing them. sync also refuses to replace a non-empty invalid snapshot. Inspect the error and move the generated cache aside before preparing it again from the reviewed root lock.
For example, in PowerShell from the repository root, with an unused backup name:
Move-Item -LiteralPath .\build\upstream -Destination .\build\upstream.backup
Set-Location tools
go run . upstream prepare
go run . upstream verify
Preserve the rest of build/ and leave official cached files unedited. To return to a previous snapshot, restore its reviewed root lock and rebuild the cache in the same way. Stop dev before replacing inputs, and avoid concurrent processes writing to the same cache.
Known Upstream Formatting Issue
Gitea v28.0.0 contains a Polish mail.team_invite.text_1 placeholder defect. Preview preserves the official output and reports [UPSTREAM-WARN]. The exception matches the exact reviewed source text; other formatting errors fail rendering. Report upstream defects without modifying the cached locale files.
Verification and Release
Checks for a Pull Request
From tools/, run go test ./... and go run . preview all. Tests cover deterministic generation, changes to action anchors, translation keys, and notification subjects, text and links across all themes and languages. Fixtures include push, review, reply, workflow and attachment branches. Shared controls and branding are accounted for separately from official notification content.
For documentation or packaging changes, run from the repository root:
python -B -m unittest discover -s .github/scripts -p 'test_*.py'
Keep English and Simplified Chinese guides aligned when changing shared instructions. Include a description of the change, relevant checks and screenshots for visual changes in the pull request.
Preparing a Release
Release tags must match the locked Gitea version. The current source refactor is unreleased; retain existing v28.0.0 and historical assets.
- Complete the Go tests, documentation checks and preview generation.
- Update documentation and compatibility records with the verification results. Release notes are optional and are not used as the Release body.
- Generate all themes and language bundles with
go run . preview allfromtools/. - Package the release and verify its contents before publication.
For manual packaging, run from the repository root:
python .github/scripts/package_release.py --version vX.Y.Z --output <new-output-directory>
Replace the version and output placeholder with the reviewed tag and a new directory. The script checks source and generated hashes, includes all language bundles, excludes stale theme builds, and refuses to overwrite existing archives.
The release workflow uses the same script to package templates, previews, documentation, the upstream license and provenance. It publishes only the archives, with the tag as the Release title and an empty body. Version labels, badges and compatibility records are maintained manually; review archive documentation before tagging. Confirm Actions support and write permissions on the configured Gitea host before relying on automated publication. See version maintenance.
Gitea Workflow Configuration
The release workflow uses the linux-amd64-docker-small runner label. The job image must support the Node.js actions used for checkout and toolchain setup, as well as Git and a POSIX shell. Go and Python are installed by the setup steps.
Publication uses gitea-release-action@v1.3.7 directly, with the instance URL, repository, built-in GITEA_TOKEN, tag, title and the two archive paths. The Release body is empty when created; no notes file or Issue reminder is required. The repository must allow release writes. Action URLs explicitly use https://gitea.com rather than depending on DEFAULT_ACTIONS_URL.
Before publication, actions/setup-node@v4 prepares Node.js 22. The current Gitea runner executes JavaScript actions with node from PATH; this provides the runtime interfaces used by the release action without --experimental-fetch. On repeated publication of an existing tag, the action preserves an existing body and replaces same-name attachments. It does not provide the previous script's draft-until-all-uploads-complete behavior. Review the release and attachments before retrying a failed publication.
Reporting Problems
Include the Gitea version, template release or source commit, theme, mail type, language and steps to reproduce. For source-build problems, include the snapshot tag/commit and output from go run . upstream verify or go run . preview all. For display problems, include the mail client and a screenshot with personal data removed.
Commit Conventions
| Prefix | Scope |
|---|---|
style(<name>): |
Theme presentation |
preview: |
Browser preview |
tools: |
CLI, build and snapshot tools |
docs: |
Documentation and translations |
fix: |
Bug fixes |
project: |
Repository configuration and project structure |
refactor: |
Code restructuring |
chore: |
Maintenance |
Translations and License
The Simplified Chinese guide covers the same workflow. Contributions are licensed under MIT. Retain Gitea copyright and the upstream license when distributing derived templates; see third-party notices.