history+boards+outline: styles.rokojori.com built, font migration, add-subdomain guide

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Rokojori 2026-07-15 20:39:06 +02:00
parent 5e27849fa3
commit 7c6fca54f9
7 changed files with 182 additions and 28 deletions

View File

@ -49,6 +49,7 @@ var NAV_DATA = {
title: 'History',
path: 'history/index.html',
children: [
{ title: 'Tuesday, 15 July 2026', path: 'history/2026/07-July/15-Tuesday/index.html' },
{ title: 'Monday, 14 July 2026', path: 'history/2026/07-July/14-Monday/index.html' },
{ title: 'Sunday, 13 July 2026', path: 'history/2026/07-July/13-Sunday/index.html' },
{ title: 'Sunday, 12 July 2026', path: 'history/2026/07-July/12-Sunday/index.html' },

View File

@ -22,31 +22,6 @@
<div class="lane">
<div class="lane-header">MVP</div>
<task-item class="blue hide-content">
<task-title>styles.rokojori.com</task-title>
<task-content>
New asset and font hosting service at styles.rokojori.com. Hosts Google Fonts
(downloaded and self-served), CSS presets, components, and images for use
across all rokojori websites.
Auth via shared JWT cookie from rokojori-auth. Access gated by requireAccess
middleware (already designed and documented in rokojori-auth workspace).
PATCH /api/admin/users/:id/products is live in rokojori-auth — assign the
"styles" product to grant access.
Pages:
— / — logged-out or no-permission users see "STYLES" + login button linking
to account.rokojori.com/login?redirect=https://styles.rokojori.com;
logged-in users with access see list of available sections
— /list-fonts — preview-sentence input at top, then all font families rendered
with that sentence
— /add-fonts — preview-sentence input + font-family name input; downloads from
Google Fonts and generates a stylesheet
Access rules: role:admin, role:user + product:styles, role:user + product:premium
</task-content>
</task-item>
<task-item class="blue hide-content">
<task-title>Local Git Repository Integration</task-title>
<task-content>

View File

@ -25,9 +25,11 @@
<task-item class="red hide-content">
<task-title>401 Not Handled in Data-Fetching Components</task-title>
<task-content>
Components that fetch data (groups, projects, etc.) do not handle 401 responses
gracefully — they crash when the API returns an error object instead of an array.
Should show an appropriate message or redirect to login.
Components that fetch data do not handle 401 responses gracefully — they crash
when the API returns an error object instead of an array. Groups and the old
projects page have been removed; the current surfaces to check are project-home
and its theme components (project-list-default). Should show an appropriate
message or redirect to the refresh-session endpoint when a 401 is received.
</task-content>
</task-item>

View File

@ -83,6 +83,23 @@
</task-content>
</task-item>
<task-item class="blue hide-content">
<task-title>Investigate session logout after ~1 hour</task-title>
<task-content>
Users are logged out after a couple of hours. The access token issued by
rokojori-auth expires after 1 hour; the refresh token lasts 30 days.
Roject should silently refresh via GET account.rokojori.com/api/auth/refresh-session
before the token expires.
Investigate:
— Is the 401 response from any API route triggering a redirect to refresh-session?
— Is the refreshToken cookie present and being sent cross-domain?
— Is the refresh-session endpoint actually rotating both cookies correctly?
— Check journalctl on the server for 401 patterns and the browser network tab
for which request first returns 401.
</task-content>
</task-item>
<task-item class="blue hide-content">
<task-title>Switch Gitea webhook to dev branch</task-title>
<task-content>
@ -96,6 +113,18 @@
<div class="lane">
<div class="lane-header">In Progress</div>
<task-item class="yellow hide-content">
<task-title>styles.rokojori.com — complete deployment</task-title>
<task-content>
Service is built and running manually via npm start on the server.
Remaining work:
— Set up systemd service (styles-rokojori.service) so it survives restarts
— Download Barlow from /add-fonts (weights 100, 400, 700, 900)
— Verify CORS is working for roject.rokojori.com font imports
— Add to the add-subdomain deployment guide as a reference example
</task-content>
</task-item>
<task-item class="yellow hide-content">
<task-title>Local Filesystem Access</task-title>
<task-content>

View File

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tuesday, 15 July 2026 — Roject</title>
<link rel="stylesheet" href="../../../../_assets_/styles.css">
<link rel="stylesheet" href="../../../../_assets_/nav.css">
</head>
<body>
<div class="page">
<header>
<p class="date">Tuesday, 15 July 2026</p>
<h1>Session History</h1>
<p class="subtitle">styles.rokojori.com built and deployed; Roject font migration; add-subdomain deployment guide.</p>
</header>
<section>
<h2>What we built</h2>
<div class="card">
<h3>styles.rokojori.com — new service</h3>
<p>
Built a new standalone asset hosting service from scratch at
<code>styles.rokojori.com</code>. Same stack as the other rokojori services:
Node.js + Express + ts-node, no external database, Web Components + raw CSS on
the frontend.
</p>
<p style="margin-top:0.75rem">Key pieces:</p>
<ul style="margin-top:0.5rem;padding-left:1.25rem;line-height:1.9;font-size:0.9rem;color:var(--muted)">
<li><strong style="color:var(--text)">GET /get-font</strong> — public CSS endpoint; three modes: all weights, specific weights (+ auto-italic), or explicit variations. Returns <code>@font-face</code> CSS; font files served statically from <code>storage/fonts/</code>.</li>
<li><strong style="color:var(--text)">POST /api/fonts/download</strong> — auth-gated; hits Google Fonts API with a browser User-Agent to get woff2 URLs, downloads each file, writes <code>meta.json</code>.</li>
<li><strong style="color:var(--text)">GET /api/fonts</strong> — auth-gated; lists all downloaded font families and their available weights/italics.</li>
<li><strong style="color:var(--text)">CORS allowlist middleware</strong> — checks <code>Origin</code> header against <code>*.rokojori.com</code> regex; echoes origin back only if matched. Public <code>*</code> header explicitly avoided.</li>
<li><strong style="color:var(--text)">Auth</strong> — shared JWT cookie from rokojori-auth; <code>requireAccess</code> middleware copied from auth workspace (role: admin, or user + product: styles / premium). HTML pages redirect to login; API routes return 401/403 JSON.</li>
<li><strong style="color:var(--text)">Pages</strong><code>/</code> detects auth state via fetch and shows hero or sections list; <code>/list-fonts</code> renders all families with live preview sentence; <code>/add-fonts</code> takes family name + optional weights, downloads, shows inline preview.</li>
</ul>
</div>
<div class="card">
<h3>Roject — font migration and page cleanup</h3>
<p>
Removed three stale pages: <code>dashboard.html</code>, <code>groups.html</code>,
<code>projects.html</code> — all superseded by the project-home redesign from the
previous session.
</p>
<p style="margin-top:0.75rem">
Migrated Barlow font loading from Google Fonts to styles.rokojori.com:
removed the three Google Fonts <code>&lt;link&gt;</code> tags from
<code>source/pages/index.html</code> and added
<code>@import url('https://styles.rokojori.com/get-font?family=barlow&amp;weights=100,400,700,900')</code>
at the top of <code>project-list-default.css</code>. The theme now self-describes
its font dependency; no Google dependency at runtime.
</p>
</div>
<div class="card">
<h3>rokojori-auth workspace — add-subdomain deployment guide</h3>
<p>
Created <code>workspace/add-subdomain.html</code> — 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.
</p>
<p style="margin-top:0.75rem">
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:
<code>/usr/bin/npx ts-node</code>, <code>Restart=on-failure</code>,
<code>StandardOutput/Error=journal</code>.
Added a step 0 explaining the CORS allowlist pattern with full code example.
</p>
</div>
</section>
<section>
<h2>Key decisions</h2>
<div class="card">
<h3>Font files are woff2-only, named numerically</h3>
<p>
Convention: <code>400.woff2</code>, <code>400-italic.woff2</code>. No "bold"
alias — numeric weights only. woff2 has near-universal browser support; no
fallback formats needed.
</p>
</div>
<div class="card">
<h3>CORS restricted to *.rokojori.com, not wildcard</h3>
<p>
<code>Access-Control-Allow-Origin: *</code> was rejected in favour of an
allowlist that echoes back the matched origin. The regex
<code>/^https?:\/\/([\w-]+\.)?rokojori\.com$/</code> covers all current and
future subdomains. Extra origins can be added as strings or regexes to the
<code>CORS_ALLOWED</code> array.
</p>
</div>
<div class="card">
<h3>styles.rokojori.com scope expanded</h3>
<p>
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.
</p>
</div>
</section>
<footer>
Roject &mdash; session history
</footer>
</div>
<script>var NAV_ROOT = '../../../../';</script>
<script src="../../../../_assets_/nav-data.js"></script>
<script src="../../../../_assets_/nav.js"></script>
</body>
</html>

View File

@ -19,6 +19,11 @@
<section>
<h2>2026 — July</h2>
<div class="card">
<h3><a href="2026/07-July/15-Tuesday/index.html">Tuesday, 15 July 2026</a></h3>
<p>styles.rokojori.com built and deployed (font hosting, /get-font public CSS endpoint, CORS allowlist, auth-gated management pages); Roject Barlow font migrated from Google Fonts; old dashboard/groups/projects pages removed; add-subdomain deployment guide with live variable inputs.</p>
</div>
<div class="card">
<h3><a href="2026/07-July/14-Monday/index.html">Monday, 14 July 2026</a></h3>
<p>Electron desktop app shell, workspace boards system. Full project home redesign: new <code>/</code> entry point, project-home component (hero / theme dispatch), default theme (logo nav, UUID-coloured badges, Barlow skewed names, new-project dialog), user settings backend, groups removed from UI.</p>

View File

@ -76,6 +76,28 @@
persisted server-side in <code>user_settings.json</code> via
<code>GET / PUT /api/user/settings</code>. A second theme (Italic Neon) is
planned. <code>/edit</code> redirects to the existing <code>/editor.html</code>.
Barlow is loaded via <code>@import</code> from <code>styles.rokojori.com</code>
(weights 100, 400, 700, 900 including italics) — no Google Fonts dependency.
</p>
</div>
<div class="card">
<h3>Ecosystem — styles.rokojori.com</h3>
<p>
A shared asset hosting service for all rokojori projects, live at
<code>styles.rokojori.com</code>. Currently serves self-hosted fonts downloaded
from Google Fonts on demand via a <code>GET /get-font</code> public endpoint that
returns a dynamic CSS file with <code>@font-face</code> rules. Font files are
stored as <code>storage/fonts/&lt;family&gt;/&lt;weight&gt;.woff2</code> and
served statically. CORS is restricted to <code>*.rokojori.com</code> origins.
Access to the management UI (<code>/list-fonts</code>, <code>/add-fonts</code>)
is gated by the shared JWT cookie via <code>requireAccess</code> middleware
(role: admin, or role: user + product: styles / premium).
</p>
<p style="margin-top:0.75rem">
Planned: shared HTML components / Web Components, CSS presets, and binary assets
(images, sounds, video) — making styles.rokojori.com the single place to manage
any reusable front-end resource across the rokojori ecosystem.
</p>
</div>