From d96cd6756b860257fad1bb690eccd17f6a50a946 Mon Sep 17 00:00:00 2001 From: m Date: Fri, 6 Feb 2026 00:25:27 +0100 Subject: [PATCH] refactor: clean up themes, templates, and add comprehensive README - Themes now only override CSS variables (no selector overrides) - Removed duplicate styles from header.tmpl (just loads Inter font now) - Cleaned up logo SVG (simpler, no overlapping text) - Improved home page with proper hero layout and sign-in/explore buttons - Added detailed README documenting the setup, deployment, and design principles --- README.md | 105 +++++++++- public/assets/css/theme-mgit-dark.css | 279 ++++--------------------- public/assets/css/theme-mgit-light.css | 253 ++++------------------ public/assets/img/favicon.svg | 10 +- public/assets/img/logo.svg | 12 +- templates/custom/body_inner_pre.tmpl | 1 + templates/custom/extra_links.tmpl | 1 + templates/custom/footer.tmpl | 22 +- templates/custom/header.tmpl | 43 +--- templates/home.tmpl | 101 +++++++-- 10 files changed, 294 insertions(+), 533 deletions(-) diff --git a/README.md b/README.md index b803aa4..c5890ff 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,104 @@ -# gitea-custom +# mGit Custom Theme -Shared Gitea theme and customizations \ No newline at end of file +Shared Gitea customizations for all mGit instances. This repo is the single source of truth for branding, themes, and template overrides. + +## Instances + +| Instance | URL | Host | +|----------|-----|------| +| Primary | `mgit.msbls.de` | mvpsm | +| Backup (mirror) | `mgit.x.msbls.de` | mgitx | + +Both run Gitea 1.24.x via Dokploy with this repo cloned to `/home/m/gitea-custom/`. + +## How It Works + +Gitea supports customization by mounting files into its `$GITEA_CUSTOM` directory (`/data/gitea/` in Docker). The Dokploy compose files bind-mount subdirectories from this repo: + +```yaml +volumes: + - /home/m/gitea-custom/public:/data/gitea/public:ro + - /home/m/gitea-custom/templates:/data/gitea/templates:ro + - /home/m/gitea-custom/options:/data/gitea/options:ro +``` + +A cron job on each host runs every 30 minutes to pull changes and restart Gitea if the repo was updated. + +## File Structure + +``` +gitea-custom/ +├── public/ +│ └── assets/ +│ ├── css/ +│ │ ├── theme-mgit-dark.css # Dark theme (CSS variables only) +│ │ └── theme-mgit-light.css # Light theme (CSS variables only) +│ └── img/ +│ ├── logo.svg # Main logo (200x200) +│ └── favicon.svg # Favicon (32x32) +├── templates/ +│ ├── custom/ +│ │ ├── header.tmpl # Injects Inter font from Google Fonts +│ │ ├── footer.tmpl # Custom footer script +│ │ ├── body_inner_pre.tmpl # Empty (available for banners) +│ │ └── extra_links.tmpl # Empty (available for nav links) +│ └── home.tmpl # Custom homepage +└── options/ # Reserved for locale overrides +``` + +## Themes + +Two custom themes are provided — **mGit Dark** and **mGit Light**. They use Gitea's built-in CSS variable system and only override color tokens and font stacks. This approach is forward-compatible with Gitea upgrades because we don't override Gitea's own selectors. + +**Color palette:** Tailwind CSS slate (grays) + blue (primary). +**Fonts:** Inter (proportional), JetBrains Mono (monospace). + +To make these themes available, add them to `app.ini` on each instance: + +```ini +[ui] +THEMES = gitea-auto,gitea-light,gitea-dark,mgit-light,mgit-dark +DEFAULT_THEME = mgit-dark +``` + +In Dokploy, set these as environment variables: + +``` +GITEA__ui__THEMES=gitea-auto,gitea-light,gitea-dark,mgit-light,mgit-dark +GITEA__ui__DEFAULT_THEME=mgit-dark +``` + +## Making Changes + +1. Edit files in this repo and push to `main` +2. Changes auto-deploy within 30 minutes via cron on each host +3. For immediate deployment: `ssh "cd /home/m/gitea-custom && git pull"` then restart the Gitea container + +**To restart Gitea after changes:** +```bash +docker restart $(docker ps -q --filter "ancestor=docker.gitea.com/gitea:1.24.4") +``` + +## Template Hooks + +Gitea provides these injection points in `templates/custom/`: + +| File | Purpose | +|------|---------| +| `header.tmpl` | Injected in `` — use for fonts, analytics, extra CSS | +| `footer.tmpl` | Injected before `` — use for scripts | +| `body_inner_pre.tmpl` | Before top nav — use for announcement banners | +| `extra_links.tmpl` | Extra items in the top nav bar | +| `home.tmpl` | Full homepage override (in `templates/`, not `templates/custom/`) | + +## Adding New Assets + +- **CSS themes:** Add `public/assets/css/theme-.css` and register in `THEMES` +- **Images:** Add to `public/assets/img/` — accessible at `/assets/img/` +- **Locale overrides:** Add to `options/locale/locale_en-US.ini` + +## Design Principles + +- **Work with Gitea, not against it** — only override CSS variables, avoid selector overrides +- **Keep it minimal** — less custom CSS = fewer things that break on upgrades +- **Both themes must stay in sync** — same structure, only color values differ diff --git a/public/assets/css/theme-mgit-dark.css b/public/assets/css/theme-mgit-dark.css index 1bcf180..dd8eda4 100644 --- a/public/assets/css/theme-mgit-dark.css +++ b/public/assets/css/theme-mgit-dark.css @@ -5,254 +5,65 @@ gitea-theme-meta-info { :root { --is-dark-theme: true; - - /* Typography - Same modern font stack */ - --fonts-proportional: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif !important; - --fonts-monospace: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace !important; - --fonts-emoji: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji', sans-serif !important; - - /* Color Palette - Dark theme with good contrast */ + + /* Primary palette */ --color-primary: #3b82f6; --color-primary-dark-1: #2563eb; --color-primary-dark-2: #1e40af; --color-primary-light-1: #60a5fa; --color-primary-light-2: #93c5fd; - + --color-primary-alpha-20: rgba(59, 130, 246, 0.2); + --color-primary-alpha-60: rgba(59, 130, 246, 0.6); + + /* Semantic */ --color-secondary: #94a3b8; --color-success: #10b981; --color-warning: #f59e0b; - --color-danger: #ef4444; - - /* Background colors - Dark */ + --color-error: #ef4444; + + /* Backgrounds */ --color-body: #0f172a; - --color-body-secondary: #1e293b; - --color-body-tertiary: #334155; - - /* Text colors - Light on dark */ + --color-box-body: #1e293b; + --color-box-body-highlight: #334155; + + /* Text */ --color-text: #f1f5f9; - --color-text-secondary: #cbd5e1; - --color-text-muted: #94a3b8; - --color-text-light: #64748b; - - /* Border colors */ - --color-border: #334155; - --color-border-secondary: #475569; - - /* Code block colors */ + --color-text-light: #94a3b8; + --color-text-light-1: #cbd5e1; + --color-text-light-2: #64748b; + + /* Borders */ + --color-secondary-dark-2: #334155; + --color-secondary-dark-1: #475569; + + /* Code */ --color-code-bg: #1e293b; - --color-code-border: #334155; - --color-code-text: #f1f5f9; - - /* Link colors */ - --color-link: #60a5fa; - --color-link-hover: #93c5fd; - - /* Spacing improvements */ - --spacing-xs: 0.25rem; - --spacing-sm: 0.5rem; - --spacing-md: 1rem; - --spacing-lg: 1.5rem; - --spacing-xl: 2rem; - - /* Border radius */ - --radius-sm: 0.375rem; - --radius-md: 0.5rem; - --radius-lg: 0.75rem; + + /* Inputs */ + --color-input-background: #1e293b; + --color-input-border: #334155; + + /* Shadows */ + --color-shadow: rgba(0, 0, 0, 0.4); + + /* Accent bar */ + --color-accent: #3b82f6; + + /* Typography */ + --fonts-regular: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; + --fonts-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, 'Cascadia Code', 'Consolas', monospace; } -/* Base typography improvements */ +/* Accent top border */ +body::before { + content: ''; + display: block; + height: 3px; + background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-primary-dark-2) 100%); +} + +/* Font smoothing for dark backgrounds */ body { - font-family: var(--fonts-proportional); - font-size: 15px; - line-height: 1.6; - letter-spacing: -0.01em; - color: var(--color-text); - background-color: var(--color-body); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } - -/* Headings */ -h1, h2, h3, h4, h5, h6 { - font-weight: 600; - line-height: 1.3; - letter-spacing: -0.02em; - color: var(--color-text); - margin-top: 1.5em; - margin-bottom: 0.75em; -} - -h1 { font-size: 2rem; } -h2 { font-size: 1.75rem; } -h3 { font-size: 1.5rem; } -h4 { font-size: 1.25rem; } -h5 { font-size: 1.125rem; } -h6 { font-size: 1rem; } - -/* Links */ -a { - color: var(--color-link); - text-decoration: none; - transition: color 0.2s ease; -} - -a:hover { - color: var(--color-link-hover); - text-decoration: underline; -} - -/* Code blocks */ -code, pre { - font-family: var(--fonts-monospace); - font-size: 0.9em; -} - -pre { - background-color: var(--color-code-bg); - border: 1px solid var(--color-code-border); - border-radius: var(--radius-md); - padding: var(--spacing-md); - overflow-x: auto; - line-height: 1.5; -} - -code { - background-color: var(--color-code-bg); - padding: 0.2em 0.4em; - border-radius: var(--radius-sm); - color: var(--color-code-text); -} - -pre code { - background-color: transparent; - padding: 0; -} - -/* Buttons */ -.ui.button, .ui.buttons .button { - font-family: var(--fonts-proportional); - font-weight: 500; - letter-spacing: -0.01em; - border-radius: var(--radius-md); - transition: all 0.2s ease; -} - -.ui.primary.button { - background-color: var(--color-primary); - color: white; -} - -.ui.primary.button:hover { - background-color: var(--color-primary-light-1); -} - -/* Forms */ -.ui.input input, .ui.form input[type="text"], -.ui.form input[type="email"], .ui.form input[type="password"], -.ui.form textarea, .ui.form select { - font-family: var(--fonts-proportional); - background-color: var(--color-body-secondary); - color: var(--color-text); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - transition: border-color 0.2s ease, box-shadow 0.2s ease; -} - -.ui.input input:focus, .ui.form input:focus, -.ui.form textarea:focus, .ui.form select:focus { - border-color: var(--color-primary); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2); -} - -/* Logo styling */ -.ui.menu .item img.logo { - height: 32px; - width: auto; -} - -/* Header improvements */ -.ui.menu { - background-color: var(--color-body-secondary); - border-bottom: 1px solid var(--color-border); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); -} - -.ui.menu .item { - color: var(--color-text-secondary); -} - -.ui.menu .item:hover { - background-color: var(--color-body-tertiary); - color: var(--color-text); -} - -/* Cards and containers */ -.ui.card, .ui.segment { - background-color: var(--color-body-secondary); - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); - color: var(--color-text); -} - -/* Repository list items */ -.repository.list .item { - border-bottom: 1px solid var(--color-border); - padding: var(--spacing-md) 0; -} - -.repository.list .item:hover { - background-color: var(--color-body-tertiary); -} - -/* Table improvements */ -.ui.table { - background-color: var(--color-body-secondary); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - overflow: hidden; - color: var(--color-text); -} - -.ui.table thead th { - background-color: var(--color-body-tertiary); - font-weight: 600; - color: var(--color-text); - border-bottom: 1px solid var(--color-border); -} - -.ui.table tbody tr { - border-bottom: 1px solid var(--color-border); -} - -.ui.table tbody tr:hover { - background-color: var(--color-body-tertiary); -} - -/* Badge and label improvements */ -.ui.label { - font-weight: 500; - border-radius: var(--radius-sm); - padding: 0.35em 0.75em; -} - -/* Footer styling */ -footer { - border-top: 1px solid var(--color-border); - background-color: var(--color-body-secondary); - padding: var(--spacing-xl) 0; - margin-top: var(--spacing-xl); - color: var(--color-text-secondary); -} - -/* Responsive improvements */ -@media (max-width: 768px) { - body { - font-size: 14px; - } - - h1 { font-size: 1.75rem; } - h2 { font-size: 1.5rem; } - h3 { font-size: 1.25rem; } -} - diff --git a/public/assets/css/theme-mgit-light.css b/public/assets/css/theme-mgit-light.css index 4fc5b02..44feabd 100644 --- a/public/assets/css/theme-mgit-light.css +++ b/public/assets/css/theme-mgit-light.css @@ -5,228 +5,59 @@ gitea-theme-meta-info { :root { --is-dark-theme: false; - - /* Typography - Modern font stack */ - --fonts-proportional: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif !important; - --fonts-monospace: 'JetBrains Mono', 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace !important; - --fonts-emoji: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji', sans-serif !important; - - /* Color Palette - Professional and cohesive */ + + /* Primary palette */ --color-primary: #2563eb; --color-primary-dark-1: #1e40af; --color-primary-dark-2: #1e3a8a; --color-primary-light-1: #3b82f6; --color-primary-light-2: #60a5fa; - + --color-primary-alpha-20: rgba(37, 99, 235, 0.1); + --color-primary-alpha-60: rgba(37, 99, 235, 0.6); + + /* Semantic */ --color-secondary: #64748b; --color-success: #10b981; --color-warning: #f59e0b; - --color-danger: #ef4444; - - /* Background colors */ + --color-error: #ef4444; + + /* Backgrounds */ --color-body: #ffffff; - --color-body-secondary: #f8fafc; - --color-body-tertiary: #f1f5f9; - - /* Text colors */ + --color-box-body: #f8fafc; + --color-box-body-highlight: #f1f5f9; + + /* Text */ --color-text: #1e293b; - --color-text-secondary: #475569; - --color-text-muted: #64748b; - --color-text-light: #94a3b8; - - /* Border colors */ - --color-border: #e2e8f0; - --color-border-secondary: #cbd5e1; - - /* Code block colors */ + --color-text-light: #64748b; + --color-text-light-1: #475569; + --color-text-light-2: #94a3b8; + + /* Borders */ + --color-secondary-dark-2: #e2e8f0; + --color-secondary-dark-1: #cbd5e1; + + /* Code */ --color-code-bg: #f8fafc; - --color-code-border: #e2e8f0; - --color-code-text: #1e293b; - - /* Link colors */ - --color-link: #2563eb; - --color-link-hover: #1e40af; - - /* Spacing improvements */ - --spacing-xs: 0.25rem; - --spacing-sm: 0.5rem; - --spacing-md: 1rem; - --spacing-lg: 1.5rem; - --spacing-xl: 2rem; - - /* Border radius */ - --radius-sm: 0.375rem; - --radius-md: 0.5rem; - --radius-lg: 0.75rem; + + /* Inputs */ + --color-input-background: #ffffff; + --color-input-border: #e2e8f0; + + /* Shadows */ + --color-shadow: rgba(0, 0, 0, 0.06); + + /* Accent bar */ + --color-accent: #2563eb; + + /* Typography */ + --fonts-regular: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; + --fonts-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, 'Cascadia Code', 'Consolas', monospace; } -/* Base typography improvements */ -body { - font-family: var(--fonts-proportional); - font-size: 15px; - line-height: 1.6; - letter-spacing: -0.01em; - color: var(--color-text); - background-color: var(--color-body); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +/* Accent top border */ +body::before { + content: ''; + display: block; + height: 3px; + background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-primary-dark-2) 100%); } - -/* Headings */ -h1, h2, h3, h4, h5, h6 { - font-weight: 600; - line-height: 1.3; - letter-spacing: -0.02em; - color: var(--color-text); - margin-top: 1.5em; - margin-bottom: 0.75em; -} - -h1 { font-size: 2rem; } -h2 { font-size: 1.75rem; } -h3 { font-size: 1.5rem; } -h4 { font-size: 1.25rem; } -h5 { font-size: 1.125rem; } -h6 { font-size: 1rem; } - -/* Links */ -a { - color: var(--color-link); - text-decoration: none; - transition: color 0.2s ease; -} - -a:hover { - color: var(--color-link-hover); - text-decoration: underline; -} - -/* Code blocks */ -code, pre { - font-family: var(--fonts-monospace); - font-size: 0.9em; -} - -pre { - background-color: var(--color-code-bg); - border: 1px solid var(--color-code-border); - border-radius: var(--radius-md); - padding: var(--spacing-md); - overflow-x: auto; - line-height: 1.5; -} - -code { - background-color: var(--color-code-bg); - padding: 0.2em 0.4em; - border-radius: var(--radius-sm); - color: var(--color-code-text); -} - -pre code { - background-color: transparent; - padding: 0; -} - -/* Buttons */ -.ui.button, .ui.buttons .button { - font-family: var(--fonts-proportional); - font-weight: 500; - letter-spacing: -0.01em; - border-radius: var(--radius-md); - transition: all 0.2s ease; -} - -.ui.primary.button { - background-color: var(--color-primary); - color: white; -} - -.ui.primary.button:hover { - background-color: var(--color-primary-dark-1); -} - -/* Forms */ -.ui.input input, .ui.form input[type="text"], -.ui.form input[type="email"], .ui.form input[type="password"], -.ui.form textarea, .ui.form select { - font-family: var(--fonts-proportional); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - transition: border-color 0.2s ease, box-shadow 0.2s ease; -} - -.ui.input input:focus, .ui.form input:focus, -.ui.form textarea:focus, .ui.form select:focus { - border-color: var(--color-primary); - box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); -} - -/* Logo styling */ -.ui.menu .item img.logo { - height: 32px; - width: auto; -} - -/* Header improvements */ -.ui.menu { - border-bottom: 1px solid var(--color-border); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); -} - -/* Cards and containers */ -.ui.card, .ui.segment { - border: 1px solid var(--color-border); - border-radius: var(--radius-lg); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); -} - -/* Repository list items */ -.repository.list .item { - border-bottom: 1px solid var(--color-border); - padding: var(--spacing-md) 0; -} - -.repository.list .item:hover { - background-color: var(--color-body-secondary); -} - -/* Table improvements */ -.ui.table { - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - overflow: hidden; -} - -.ui.table thead th { - background-color: var(--color-body-secondary); - font-weight: 600; - color: var(--color-text); -} - -/* Badge and label improvements */ -.ui.label { - font-weight: 500; - border-radius: var(--radius-sm); - padding: 0.35em 0.75em; -} - -/* Footer styling */ -footer { - border-top: 1px solid var(--color-border); - background-color: var(--color-body-secondary); - padding: var(--spacing-xl) 0; - margin-top: var(--spacing-xl); -} - -/* Responsive improvements */ -@media (max-width: 768px) { - body { - font-size: 14px; - } - - h1 { font-size: 1.75rem; } - h2 { font-size: 1.5rem; } - h3 { font-size: 1.25rem; } -} - diff --git a/public/assets/img/favicon.svg b/public/assets/img/favicon.svg index efc455c..9a26ee7 100644 --- a/public/assets/img/favicon.svg +++ b/public/assets/img/favicon.svg @@ -1,10 +1,10 @@ - - - + + + - - m + + m diff --git a/public/assets/img/logo.svg b/public/assets/img/logo.svg index a8a8bd6..3f8068b 100644 --- a/public/assets/img/logo.svg +++ b/public/assets/img/logo.svg @@ -1,12 +1,10 @@ - - - + + + - - - m - Git + + m diff --git a/templates/custom/body_inner_pre.tmpl b/templates/custom/body_inner_pre.tmpl index e69de29..8b13789 100644 --- a/templates/custom/body_inner_pre.tmpl +++ b/templates/custom/body_inner_pre.tmpl @@ -0,0 +1 @@ + diff --git a/templates/custom/extra_links.tmpl b/templates/custom/extra_links.tmpl index e69de29..8b13789 100644 --- a/templates/custom/extra_links.tmpl +++ b/templates/custom/extra_links.tmpl @@ -0,0 +1 @@ + diff --git a/templates/custom/footer.tmpl b/templates/custom/footer.tmpl index 41dcb6a..cc4eba9 100644 --- a/templates/custom/footer.tmpl +++ b/templates/custom/footer.tmpl @@ -1,12 +1,10 @@ - + diff --git a/templates/custom/header.tmpl b/templates/custom/header.tmpl index 07bb8c0..a4f7bdf 100644 --- a/templates/custom/header.tmpl +++ b/templates/custom/header.tmpl @@ -1,40 +1,3 @@ - + + + diff --git a/templates/home.tmpl b/templates/home.tmpl index 03755fd..599fa6b 100644 --- a/templates/home.tmpl +++ b/templates/home.tmpl @@ -1,37 +1,94 @@ {{template "base/head" .}} -
-
-
mGit
-
+
+
+
+ + m + +
+

mGit

+

Private Git hosting for projects, code, and collaboration.

+
+ {{if .IsSigned}} + Dashboard + {{else}} + Sign In + {{end}} + Explore +
+
{{template "base/footer" .}}