Contributing
Contributions are welcome! The full guide is CONTRIBUTING.md in the repository root; this page is a summary.
License
This project is licensed under AGPL-3.0-or-later. By submitting a pull request, you agree to license your contribution under the same license.
Branches and Commits
- Create a feature branch from
main:feat/xxx,fix/xxx,docs/xxx. - We recommend Conventional Commits for commit messages:
feat: add bulk question export APIfix: fix LaTeX rendering of fill-in-the-blank answersdocs: update deployment docs
Code Style
Backend (Python)
- Type hints are mandatory; database access uses
AsyncSession+ SQLAlchemy 2.0 syntax. - New CRUD classes inherit from
app/crud/base.py:CRUDBase. - Add dependencies with
uv add <package>; include an Alembic migration with any database change.
Frontend (Vue/TS)
<script setup lang="ts">; preferref.- Use
zod+vee-validatefor form validation. - Tailwind v4 utility classes, no scoped CSS; use
lucide-vue-nextfor icons. - Make API calls through
useAPI.
See Backend Conventions and Frontend Conventions for details.
Submitting a Pull Request
- Fork the repository and create a feature branch.
- Before submitting, make sure both frontend and backend start correctly locally.
- Include Alembic migration files for any database change.
- Include screenshots for any UI change.
- Describe the motivation, approach and verification steps in the PR description.
Reporting Issues
When opening an issue, please try to include: steps to reproduce, expected vs. actual behavior, environment details (OS, Python/Node version, browser), and relevant logs or screenshots.
Security Issues
WARNING
Please do not report security vulnerabilities in public issues. Contact the maintainers privately by email instead.
Contributing to the Docs
This docs site is built with VitePress; its source is in docs/. To preview locally:
cd docs
pnpm install
pnpm docs:devAfter a push to docs/** on the main branch, GitHub Actions automatically builds and deploys the site to GitHub Pages.
Docs Translations
Chinese is the single source; English translations live in docs/en/, mirroring the Chinese paths one-to-one (guide/, desktop/, server/, admin/, features/, development/ and the home page). The repository README.md has an English counterpart, README.en.md, which is only checked for staleness, not structure, so the two may differ in content (e.g. the English one omits the WeChat section); mark it with the path ../README.md.
- After changing a Chinese page, run
pnpm i18n:statusto list translations that are missing, stale, orphaned, or structurally inconsistent (structure). - Update the matching page under
docs/en/: the number of headings, code blocks,:::containers and images must match the source; prefix internal links with/en; use the app's actual English UI text for UI labels (seefrontend/i18n/locales/en-US.json), and followfrontend/i18n/glossary.jsonfor terminology. - When a translation is done, run
pnpm i18n:mark <path>(e.g.pnpm i18n:mark guide/introduction.md) to record the source hash, and commitdocs/.translation-lock.json. pnpm i18n:checkexits non-zero if there are any problems; the deploy workflow only prints the status and does not block a release because of stale translations.- The sidebar and navigation are maintained in
.vitepress/locales/zh.mtsanden.mtsrespectively; when adding a page, add it to both. - Browser language detection: on the first visit to a bilingual page, if the browser's preferred language is not Chinese, the visitor is redirected to the matching English page; after that, the last language the user viewed is remembered (switching via the language menu takes effect). The logic is in
.vitepress/lang-redirect.mts, and its bilingual scope must stay in sync withSCOPEinscripts/i18n-docs.mjs.