Seiten-Editor: Inhalte pflegen ohne Code-Änderung
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Antwort auf den CMS-Wunsch aus der Community — statt eines Forums, das
neben aktivem Discord erfahrungsgemäß verwaist, ein schlanker Editor für
eigene Seiten: Regeln, Über uns, Mitmachen, FAQ.

- neuer Setup-Tab "Seiten" (Scope content): Titel, Adress-Kürzel wird aus
  dem Titel abgeleitet, Markdown-Editor mit Live-Vorschau daneben
- pro Seite wählbar: veröffentlicht oder Entwurf, im Community-Menü oder
  nur per Direktlink, Reihenfolge
- Anzeige unter /<kürzel>, gerendert mit dem vorhandenen Markdown-Parser
- Entwürfe sind öffentlich nicht abrufbar — sie brauchen den content-Scope
- reservierte Kürzel (devlogs, settings, api, impressum …) werden
  abgelehnt, damit nichts die festen Routen überschreibt

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 15:08:21 +02:00
co-authored by Claude Fable 5
parent 3b80334433
commit e8158ce90b
8 changed files with 337 additions and 2 deletions
+33
View File
@@ -516,6 +516,39 @@ export function deleteUserData(userId) {
return result;
}
// Frei anlegbare Seiten (Regeln, Über uns, Mitmachen …) — Inhalte pflegen
// ohne Code-Änderung. Rechtstexte laufen bewusst separat.
db.exec(`
CREATE TABLE IF NOT EXISTS pages (
slug TEXT PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL DEFAULT '',
published INTEGER NOT NULL DEFAULT 0,
in_menu INTEGER NOT NULL DEFAULT 1,
sort INTEGER NOT NULL DEFAULT 0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
`);
const upsertPage = db.prepare(`
INSERT INTO pages (slug, title, content, published, in_menu, sort, updated_at)
VALUES (@slug, @title, @content, @published, @in_menu, @sort, datetime('now'))
ON CONFLICT(slug) DO UPDATE SET
title = excluded.title, content = excluded.content,
published = excluded.published, in_menu = excluded.in_menu,
sort = excluded.sort, updated_at = datetime('now')
`);
const getPageStmt = db.prepare('SELECT * FROM pages WHERE slug = ?');
const listPagesStmt = db.prepare('SELECT * FROM pages ORDER BY sort, title');
const listPublishedPagesStmt = db.prepare(
'SELECT slug, title, in_menu, sort FROM pages WHERE published = 1 ORDER BY sort, title'
);
const deletePageStmt = db.prepare('DELETE FROM pages WHERE slug = ?');
export const savePage = (p) => upsertPage.run(p);
export const getPage = (slug) => getPageStmt.get(slug) ?? null;
export const listPages = () => listPagesStmt.all();
export const listPublishedPages = () => listPublishedPagesStmt.all();
export const deletePage = (slug) => deletePageStmt.run(slug).changes > 0;
// Portal: eigene Dienste (Gitea, Kanban, Cloud …) für die Kachel-Übersicht
db.exec(`
CREATE TABLE IF NOT EXISTS services (