No description
  • HTML 82.8%
  • CSS 13.8%
  • HCL 2.7%
  • Dockerfile 0.7%
Find a file
Tamjid Rahman 15dea131a1
All checks were successful
Deploy brand / deploy (push) Successful in 22s
self-host variable fonts + serve with CORS
Authentik's brand-level Custom CSS field rejects @import (security
restriction), so the Google Fonts <link> approach doesn't work there.
Self-hosting the fonts at brand.basha.cloud lets consumers use plain
@font-face which doesn't require @import.

New files:
- public/assets/fonts/SpaceGrotesk-Variable.woff2  (22 KB, weight 100-900)
- public/assets/fonts/JetBrainsMono-Variable.woff2 (40 KB, weight 100-800)
- public/fonts.css   — drop-in @font-face declarations (link OR paste)
- nginx.conf         — adds CORS (Access-Control-Allow-Origin: *) for
                       fonts so cross-origin apps can use them, plus
                       long-term cache headers for fonts + assets.

Sources from fontsource.org via jsdelivr's CDN
(cdn.jsdelivr.net/fontsource/fonts/{family}:vf@latest/latin-wght-normal.woff2).

Usage for Authentik's Custom CSS — replace the previous @import line with:

  @font-face {
    font-family: 'Space Grotesk';
    font-display: swap;
    font-weight: 100 900;
    src: url('https://brand.basha.cloud/assets/fonts/SpaceGrotesk-Variable.woff2') format('woff2-variations');
  }
  @font-face {
    font-family: 'JetBrains Mono';
    font-display: swap;
    font-weight: 100 800;
    src: url('https://brand.basha.cloud/assets/fonts/JetBrainsMono-Variable.woff2') format('woff2-variations');
  }

Or use the link approach where supported: <link rel="stylesheet" href="https://brand.basha.cloud/fonts.css">.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-08 07:25:08 -04:00
.forgejo/workflows scaffold brand asset site for basha.cloud + tamjid.io 2026-06-07 22:58:31 -04:00
public self-host variable fonts + serve with CORS 2026-06-08 07:25:08 -04:00
.gitignore scaffold brand asset site for basha.cloud + tamjid.io 2026-06-07 22:58:31 -04:00
brand.nomad scaffold brand asset site for basha.cloud + tamjid.io 2026-06-07 22:58:31 -04:00
Dockerfile self-host variable fonts + serve with CORS 2026-06-08 07:25:08 -04:00
nginx.conf self-host variable fonts + serve with CORS 2026-06-08 07:25:08 -04:00
README.md tokens: rewrite with shadcn naming + R G B channels 2026-06-08 06:25:57 -04:00

tamjid · basha cloud — brand

One identity, two domains. The mark, color, and type are identical across tamjid.io (personal) and basha.cloud (homelab) — only the wordmark text changes. The brand is the person, not the address.

Minimal, geometric, terracotta. Built to read from a 16px favicon up to a full-screen login. Every text/UI color clears WCAG AA.

Served at:

  • https://brand.basha.cloud (LAN + via relay)
  • https://brand.tamjid.io (public)

Both URLs serve the same files.


Quick start (consumer apps)

Drop into your <head>:

<link rel="stylesheet" href="https://brand.basha.cloud/tokens.css" />
<link rel="icon" href="https://brand.basha.cloud/assets/favicon.svg" type="image/svg+xml" />

Then use tokens — e.g. color: rgb(var(--foreground)), background: rgb(var(--primary)).

Tokens follow shadcn's naming convention (R G B space-separated channels) so a Tailwind config with rgb(var(--primary) / <alpha-value>) will give you bg-primary/50-style opacity utilities for free.

Dark mode switches automatically with the OS via @media (prefers-color-scheme: dark). Manual override: add data-theme="dark" or data-theme="light" to <html>.

The full drop-in head snippet (favicons at 4 sizes, fonts, theme-color) is in public/head.html.

Open brand-guide.html and dark-mode.html in a browser for the full visual reference.


Files

public/
├─ index.html            landing — links to references + drop-in snippet
├─ tokens.css            CSS variables — light + dark, auto-switching
├─ head.html             drop-in <head> snippet + logo lockup markup
├─ brand-guide.html      visual reference (light)
├─ dark-mode.html        visual reference (dark) + behavior rules
└─ assets/
   ├─ logo-mark.svg          core mark, fill="currentColor" (adapts to any bg)
   ├─ logo-mark-accent.svg   mark pre-filled terracotta
   ├─ favicon.svg            solid-tile mark (browser tabs)
   ├─ favicon-16.png         ┐
   ├─ favicon-32.png         │ raster fallbacks
   ├─ favicon-180.png        │ (180 = apple-touch-icon)
   ├─ favicon-512.png        ┘
   ├─ wordmark-tamjid.svg    lockup: mark + "tamjid"
   ├─ wordmark-basha.svg     lockup: mark + "basha cloud"
   ├─ login-bg.svg           1920×1080 dot-grid background
   └─ palette.json           machine-readable tokens

Color

Shadcn token names. See public/tokens.css for the full table; here's the key mapping for designers used to a more semantic naming:

Token Light Dark What it is
--background #FFFFFF #1A1715 Page bg
--foreground #14161B #F2EEE8 Heading / strong text
--card #FAF7F4 #232019 Card / raised surface
--card-foreground #14161B #F2EEE8 Text on cards
--muted-foreground #5B6273 #ABA49B Body text
--border #E4E6EC #322D28 Hairlines, dividers
--primary #BB5A3C #BB5A3C (same) Brand color — buttons, fills
--primary-foreground #FFFFFF #FFFFFF Text on primary (4.53:1)
--ring #BB5A3C #C56A4A (lifted) Focus ring / link color
--destructive #DC2626 #F87171 Errors / delete

Primary is the brand color: terracotta #BB5A3C. White text on it passes AA (4.53:1). Use it for one primary action per view, links, and focus rings — not as a background wash.

Note: in shadcn naming, --accent is the HOVER/HIGHLIGHT color (a subtle surface), not the brand color. Brand color = --primary.


Dark mode — three rules

  1. The mark adapts for free. logo-mark.svg is a transparent-T knockout. Set color: rgb(var(--foreground)) and the same file becomes a light tile with the dark page showing through the T. No separate dark logo.
  2. The favicon doesn't flip. favicon.svg keeps its solid terracotta tile in both themes so it holds a silhouette on light and dark browser chrome.
  3. The ring/link accent lifts. Terracotta #BB5A3C only hits 3.9:1 on dark — fine as a button fill (white text), too dim as link or focus-ring color. The --ring token lifts to #C56A4A on dark (4.7:1, AA). tokens.css does this for you.

Logo usage

The mark (fill="currentColor") — set color to control it:

<span style="color: rgb(var(--primary))">
  <img src="https://brand.basha.cloud/assets/logo-mark.svg" width="32" alt="tamjid" />
</span>

The wordmark lockup — mark + text as one unit (markup in head.html):

<a class="wordmark" href="/">
  <svg class="wordmark__mark"></svg>
  <span class="wordmark__text">basha cloud</span>
</a>

The wordmark-*.svg files render Space Grotesk via @import — they work wherever that font loads (i.e. your own sites). For contexts that can't load webfonts, prefer the HTML/CSS lockup above.

Do / Don't

  • Do keep the wordmark lowercase, always.
  • Do swap only the text between domains — never the mark.
  • Do honor clear space (≈ the corner radius) around the mark.
  • Don't add gradients, shadows, or a glow to the mark.
  • Don't recolor the T or stretch the lockup.
  • Don't introduce a second accent hue.

Type

Space Grotesk (display + UI) and JetBrains Mono (code, labels, metadata), both from Google Fonts — loaded in head.html.


Tailwind config (consumers)

If you use Tailwind, point its colors at the tokens so bg-primary, text-foreground, etc. just work — and so bg-primary/50-style opacity utilities resolve correctly:

// tailwind.config.js
export default {
  theme: {
    extend: {
      colors: {
        background: 'rgb(var(--background) / <alpha-value>)',
        foreground: 'rgb(var(--foreground) / <alpha-value>)',
        card: {
          DEFAULT: 'rgb(var(--card) / <alpha-value>)',
          foreground: 'rgb(var(--card-foreground) / <alpha-value>)',
        },
        popover: {
          DEFAULT: 'rgb(var(--popover) / <alpha-value>)',
          foreground: 'rgb(var(--popover-foreground) / <alpha-value>)',
        },
        primary: {
          DEFAULT: 'rgb(var(--primary) / <alpha-value>)',
          foreground: 'rgb(var(--primary-foreground) / <alpha-value>)',
        },
        secondary: {
          DEFAULT: 'rgb(var(--secondary) / <alpha-value>)',
          foreground: 'rgb(var(--secondary-foreground) / <alpha-value>)',
        },
        muted: {
          DEFAULT: 'rgb(var(--muted) / <alpha-value>)',
          foreground: 'rgb(var(--muted-foreground) / <alpha-value>)',
        },
        accent: {
          DEFAULT: 'rgb(var(--accent) / <alpha-value>)',
          foreground: 'rgb(var(--accent-foreground) / <alpha-value>)',
        },
        destructive: {
          DEFAULT: 'rgb(var(--destructive) / <alpha-value>)',
          foreground: 'rgb(var(--destructive-foreground) / <alpha-value>)',
        },
        border: 'rgb(var(--border) / <alpha-value>)',
        input: 'rgb(var(--input) / <alpha-value>)',
        ring: 'rgb(var(--ring) / <alpha-value>)',
      },
      fontFamily: {
        sans: ['"Space Grotesk"', 'system-ui', 'sans-serif'],
        mono: ['"JetBrains Mono"', 'ui-monospace', 'monospace'],
      },
      borderRadius: {
        lg: 'var(--radius)',
        md: 'calc(var(--radius) - 2px)',
        sm: 'calc(var(--radius) - 4px)',
      },
    },
  },
};

Deploy

Tiny nginx serving public/ as a static site. Push to main → Forgejo CI builds the nginx image → pushes to git.tamjid.io/tamjid/brand:<sha> → submits brand.nomad. Lands on the apps Nomad pool, auto-registers in Consul, atlas + relay Caddys auto-render the vhosts.


Personal project. No trademark claims. Use freely.