Changeset 495b019 in Klonkt for src/server.js


Ignore:
Timestamp:
10/25/2026 09:52:01 AM (2 days ago)
Author:
Bart <bart@…>
Children:
b4aaadd
Parents:
5d0d3f35
git-author:
Bart <bart@…> (10/14/2026 02:48:46 PM)
git-committer:
Bart <bart@…> (10/25/2026 09:52:01 AM)
Message:

Lay-outthema's: een pakket, de beheerder kiest, en de zijbalk als eerste

Een lay-out is nu een pakket: een map in src/themes/ met een theme.json (id,
naam, versie, contract, stylesheet) en de stylesheet zelf. De zijbalk is het
eerste ingebouwde thema; een thema van buiten installeren komt later en gaat
door dezelfde lader, zodat er één vorm is.

Dezelfde markup, een ander stelsel: een thema verandert geen template. Het
contract (1) is de afspraak over de ids en klassen waar het op mag bouwen; een
thema op een ander contract valt terug op de gewone kop in plaats van half te
werken. Elke regel staat onder html[data-layout="<id>"], en een toets bewaakt
dat, zodat een thema niets raakt zolang het niet gekozen is.

WIE KIEST: de beheerder, in het sitebeheer (sites.layout). Een bezoeker niet
-- de server zet data-layout zelf, het bezoekersscript met localStorage is
weg, en ?layout= werkt alleen als voorproefje voor wie de site beheert. Het
beheer houdt altijd de gewone kop, ook bij navigeren via htmx (de lay-out reist
mee in pcmsNav): een kapot thema mag je nooit buitensluiten van de instelling
waarmee je het uitzet.

Geserveerd op /themes/<id>/<versie>/<bestand>, met de versie in het pad als
cache-buster; alleen wat het pakket zelf noemt komt eruit. De actor noemt het
gekozen thema als shaer:theme, zodat Shaer het van zijn eigen site kan halen
in plaats van er zelf een te kiezen.

Co-Authored-By: Claude Opus 5.5 <claude@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/server.js

    r5d0d3f35 r495b019  
    1717import http from 'http';
    1818import db, { initializeDatabase } from './config/database.js';
     19import ThemeService from './services/ThemeService.js';
    1920import { startScheduler } from './services/Scheduler.js';
    2021import { SqliteSessionStore } from './services/SqliteSessionStore.js';
    … …  
    238239
    239240app.use('/assets', express.static(path.join(__dirname, 'assets'), { maxAge: isDev ? 0 : '1y' }));
     241// Lay-outthema's (experimental/theme). De versie staat in het pad, dus een
     242// nieuwe versie is een nieuwe URL en deze cache van een jaar klopt altijd --
     243// geen ?v= om bij te houden. Alleen wat het pakket zelf noemt wordt geserveerd
     244// (ThemeService.layoutFile); een pad uit de URL komt nergens in een join.
     245app.get('/themes/:id/:version/:file', (req, res) => {
     246  const file = ThemeService.layoutFile(req.params.id, req.params.version, req.params.file);
     247  if (!file) return res.status(404).end();
     248  res.set('Cache-Control', isDev ? 'no-cache' : 'public, max-age=31536000, immutable');
     249  res.set('X-Content-Type-Options', 'nosniff');
     250  res.sendFile(file);
     251});
    240252
    241253// On-demand cover thumbnails: /media/thumb/<w>/<path> → a small lanczos-downscaled WebP
Note: See TracChangeset for help on using the changeset viewer.