Tuesday, 15 July 2026

Session History

styles.rokojori.com built and deployed; Roject font migration; add-subdomain deployment guide.

What we built

styles.rokojori.com — new service

Built a new standalone asset hosting service from scratch at styles.rokojori.com. Same stack as the other rokojori services: Node.js + Express + ts-node, no external database, Web Components + raw CSS on the frontend.

Key pieces:

  • GET /get-font — public CSS endpoint; three modes: all weights, specific weights (+ auto-italic), or explicit variations. Returns @font-face CSS; font files served statically from storage/fonts/.
  • POST /api/fonts/download — auth-gated; hits Google Fonts API with a browser User-Agent to get woff2 URLs, downloads each file, writes meta.json.
  • GET /api/fonts — auth-gated; lists all downloaded font families and their available weights/italics.
  • CORS allowlist middleware — checks Origin header against *.rokojori.com regex; echoes origin back only if matched. Public * header explicitly avoided.
  • Auth — shared JWT cookie from rokojori-auth; requireAccess middleware copied from auth workspace (role: admin, or user + product: styles / premium). HTML pages redirect to login; API routes return 401/403 JSON.
  • Pages/ detects auth state via fetch and shows hero or sections list; /list-fonts renders all families with live preview sentence; /add-fonts takes family name + optional weights, downloads, shows inline preview.

Roject — font migration and page cleanup

Removed three stale pages: dashboard.html, groups.html, projects.html — all superseded by the project-home redesign from the previous session.

Migrated Barlow font loading from Google Fonts to styles.rokojori.com: removed the three Google Fonts <link> tags from source/pages/index.html and added @import url('https://styles.rokojori.com/get-font?family=barlow&weights=100,400,700,900') at the top of project-list-default.css. The theme now self-describes its font dependency; no Google dependency at runtime.

rokojori-auth workspace — add-subdomain deployment guide

Created workspace/add-subdomain.html — a step-by-step deployment checklist for adding any new rokojori subdomain service to Server A. Covers: Gitea repo creation, .gitignore, DNS on IONOS, server clone, install/build/env, nginx HTTP config, Let's Encrypt via certbot, nginx HTTPS verification, and systemd service setup.

The guide has an interactive variables bar at the top (subdomain, port, service name) — all commands throughout the page update live via JS as you type. systemd unit file format matched to the Roject convention: /usr/bin/npx ts-node, Restart=on-failure, StandardOutput/Error=journal. Added a step 0 explaining the CORS allowlist pattern with full code example.

Key decisions

Font files are woff2-only, named numerically

Convention: 400.woff2, 400-italic.woff2. No "bold" alias — numeric weights only. woff2 has near-universal browser support; no fallback formats needed.

CORS restricted to *.rokojori.com, not wildcard

Access-Control-Allow-Origin: * was rejected in favour of an allowlist that echoes back the matched origin. The regex /^https?:\/\/([\w-]+\.)?rokojori\.com$/ covers all current and future subdomains. Extra origins can be added as strings or regexes to the CORS_ALLOWED array.

styles.rokojori.com scope expanded

Initially conceived as a font host; scope widened to a general shared-asset platform: fonts now, shared HTML components / Web Components, CSS presets, and binary assets (images, sounds, video) planned.