Files
Gitea/docs/guidelines-frontend.md
T
silverwind 61be9fcdfa chore: update eslint and stylelint configs and re-sync modern-normalize (#38982)
- update the vendored `modern-normalize` to v3.0.1
- require descriptions for lint disables in TS and CSS, same as we
already have in Go.
- disable core rules covered by `regexp/*` and `unicorn/*`, and ones
that cannot fire
- stop applying vitest rules to the playwright files in `tests/e2e`
- enable 7 stylelint rules, mostly `no-unknown` and `no-invalid` checks
- drop 2 unnecessary vendor prefixes (safari v17+, chrome v120+)
- look up ids via `querySelector` with `CSS.escape` instead of
`getElementById`
- remove stale doc about `@ts-expect-error`, it's forbidden
- misc dev doc fixes

Every declaration that `modern-normalize` v3 removes was checked against
chromium, webkit and firefox defaults first. The `hr` color and the
`:-moz-focusring` outline are kept as documented deviations, dropping
those does change rendering.

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-08-20 09:57:56 -04:00

4.3 KiB

Frontend development guidelines

This document covers frontend-specific architecture and contribution expectations. For the general workflow see CONTRIBUTING.md, and for building and testing see development.md and testing.md.

Background

The frontend uses Vue 3, hard-forked Fomantic-UI (built on jQuery) and Tailwind CSS. Pages are rendered with Go HTML templates. Source files live in:

  • web_src/css/: CSS styles
  • web_src/js/: JavaScript and TypeScript
  • web_src/js/components/: Vue components
  • web_src/js/features/: feature modules wired up at page load
  • templates/: Go HTML templates

Dependencies

Frontend dependencies are managed with pnpm. The same rules as for backend dependencies apply, except the relevant files are package.json and pnpm-lock.yaml, and new versions must always reference an existing published version.

Framework usage

Mixing frameworks arbitrarily makes code hard to maintain. Recommended combinations:

  • Vue3
  • Vanilla JavaScript
  • Fomantic-UI (jQuery), deprecated, we vendored a specific version with a lot of changes.

Avoid combinations such as Vue with Fomantic-UI. Vue components may reuse Fomantic-UI CSS classes for visual consistency. Use Go templates for simple or SEO-relevant pages and Vue for complex, interactive pages. Gitea uses Vue 3 without JSX to keep HTML and JavaScript separate.

Note

Fomantic-UI is not an accessibility-friendly framework. Gitea patches some ARIA behavior, but accessibility work is ongoing — prefer semantic HTML and test keyboard/screen-reader behavior where you can.

Gitea-specific conventions

  • Keep features in their own files or directories.
  • Use kebab-case for HTML ids and classes with 2-3 feature keywords.
  • Prefix classes to avoid short-name conflicts between different frameworks.
  • Our framework can automatically link "input" and "label" if they are the children of a .field element, no need to write id/for attributes for them unless there are reasons to do so.
  • Create a new class name when overriding framework styles instead of editing the framework's own classes, or fix the framework's source to fix all cases.
  • Prefer semantic elements such as <button> over generic <div>s.
  • Avoid !important; when it is unavoidable, document why.
  • Prefix custom DOM events with ce-.

CSS

Prefer Tailwind utility classes with the tw- prefix, and the flex-* layout helpers over per-child margins. Gitea also ships a small set of custom helpers: gt- for general helpers and g- for framework-level helpers (see web_src/css/helpers.css); use these only when a Tailwind utility does not exist.

Write class attributes as a single readable unit in templates:

<div class="flex-text-inline {{if .IsFoo}}tw-hidden{{end}}"></div>

TypeScript

  • Use import type for type-only imports.
  • Use the ! non-null assertion (rather than ?./??) when a value is known to always exist.
  • Only mark a function async when it actually uses await or returns a Promise. Avoid async event listeners; if unavoidable, call e.preventDefault() before the first await.

Data fetching

Use the GET, POST, PUT, PATCH, and DELETE wrappers from web_src/js/modules/fetch.ts.

Prefer to use our fetch-action.ts framework for form submissions, button clicks and network requests, which provides a consistent UX and error handling.

DOM attributes

Avoid node.dataset because of its camel-casing behavior; use node.getAttribute in new code. Never bind user-provided data directly onto DOM nodes.

Showing and hiding elements

  • In Vue, use v-if and v-show. If an element contains unmanaged DOM, use v-show to avoid losing the DOM state.
  • In Go templates and plain JavaScript, use the .tw-hidden class together with the showElem(), hideElem(), and toggleElem() helpers from web_src/js/utils/dom.ts.

When running Gitea in development mode, standardized UI components are available at /devtest (for example http://localhost:3000/devtest). These pages are also used by the e2e tests.