cms: add openbureau-core CMS (DB-less, auth: local) — vendored at cms/core
kgva can now be edited through openbureau-core instead of Decap: a small Node CMS (git subtree at cms/core) with a schema-driven editor at /admin, file-based login (no Supabase/Postgres), Markdown on disk. cms/kgva.config.js models the content (portfolio/pages/sections); docker-compose builds the core image (Hugo 0.163.3, no VITE_SUPABASE_URL → local-auth admin) and mounts the repo as the site. seed an admin via cms/seed-admin.mjs; deploy/provision-lxc.sh + ADMIN.md updated. Verified DB-less end-to-end on real content (staged): local login → schema-driven editor → 42 entries (de/en) → stats → create/preview/cleanup; unknown frontmatter (image galleries) preserved on save. The LIVE static site (CT130 timer→hugo→nginx) is unaffected — hugo ignores cms/; the CMS is dormant until provisioned. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
# kgva CMS — DB-less (openbureau-core, auth: local). Copy to cms/.env, fill in.
|
||||
# Sign-in token secret — random: openssl rand -hex 32
|
||||
JWT_SECRET=CHANGE_ME
|
||||
# Always-admin emails (comma-separated).
|
||||
ADMIN_EMAILS=karim@gabrielevarano.ch
|
||||
# Commit edits back to git on publish (optional).
|
||||
GIT_PUBLISH=false
|
||||
@@ -0,0 +1,48 @@
|
||||
// kgva site config — consumed by openbureau-core (vendored at cms/core) via
|
||||
// CMS_CONFIG. DB-less: auth 'local' (file users), no plugins. Bilingual content
|
||||
// (.de.md) lists as separate entries (edit each language file on its own).
|
||||
export default {
|
||||
site: 'kgva',
|
||||
auth: 'local',
|
||||
admins: ['karim@gabrielevarano.ch'],
|
||||
plugins: [],
|
||||
|
||||
collections: [
|
||||
{
|
||||
kind: 'project', label: 'Portfolio', order: 0,
|
||||
path: 'portfolio/:slug', statKey: 'portfolio',
|
||||
fields: [
|
||||
{ name: 'title', type: 'string', required: true },
|
||||
{ name: 'slug', type: 'slug' },
|
||||
{ name: 'date', type: 'date' },
|
||||
{ name: 'draft', type: 'bool', default: true },
|
||||
{ name: 'thumbnail', type: 'image' },
|
||||
{ name: 'video', type: 'string', hint: '/media/x.mp4' },
|
||||
{ name: 'studies', type: 'string', hint: '/studies/hslu/ba/semester_05' },
|
||||
{ name: 'schools', type: 'list' },
|
||||
{ name: 'degrees', type: 'list' },
|
||||
{ name: 'semesters', type: 'list' },
|
||||
{ name: 'body', type: 'markdown' },
|
||||
// NB: image galleries (`images:`) and any other frontmatter not modelled
|
||||
// here are PRESERVED on save (the editor keeps unknown keys).
|
||||
],
|
||||
},
|
||||
{
|
||||
kind: 'page', label: 'Seiten', order: 1, fallback: true, statKey: 'pages',
|
||||
fields: [
|
||||
{ name: 'title', type: 'string', required: true },
|
||||
{ name: 'description', type: 'string' },
|
||||
{ name: 'layout', type: 'string' },
|
||||
{ name: 'body', type: 'markdown' },
|
||||
],
|
||||
},
|
||||
{
|
||||
kind: 'section', label: 'Index-Seiten', order: 2, index: true, statKey: 'sections',
|
||||
fields: [
|
||||
{ name: 'title', type: 'string' },
|
||||
{ name: 'description', type: 'string' },
|
||||
{ name: 'body', type: 'markdown' },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
// Seed the first admin into the local users file (DB-less auth). Run once:
|
||||
// docker compose run --rm cms node /site/cms/seed-admin.mjs you@mail yourpass
|
||||
import { createUser, loadUsers } from '/app/src/auth-local.js';
|
||||
const [email, password] = process.argv.slice(2);
|
||||
if (!email || !password) { console.error('usage: seed-admin.mjs <email> <password>'); process.exit(1); }
|
||||
if ((await loadUsers()).some((u) => (u.email || '').toLowerCase() === email.toLowerCase())) {
|
||||
console.log('user already exists:', email); process.exit(0);
|
||||
}
|
||||
console.log('seeded admin', email, await createUser({ email, password, role: 'admin' }));
|
||||
Reference in New Issue
Block a user