Commit b8e47be6 by PLN (Algolia)

admin: Sveltia CMS over content/blog, gitlab PKCE backend

/admin serves Sveltia CMS from a pinned jsdelivr bundle (0.229.0) with a
cms-config-url link to ./config.yml; HTML comment documents the Decap
fallback (same config, swap the script). Backend points at git.nech.pl
with base_url + api_root for the self-hosted instance, PKCE app_id
filled in, implicit grant noted as fallback. Blog collection fields
match the existing frontmatter; media folder public/images/blog with
public_path /images/blog. scripts/new-share-token.mjs prints a random
6-char token for the unlisted draft links.
parent fe6b6c16
# yaml-language-server: $schema=https://unpkg.com/@sveltia/cms/schema/sveltia-cms.json
site_url: https://me.nech.pl
backend:
name: gitlab
repo: pln/www
# Self-hosted GitLab — both base_url and api_root must point at git.nech.pl
# (Sveltia does not infer them from the repo URL).
base_url: https://git.nech.pl
api_root: https://git.nech.pl/api/v4
# PKCE: no client secret anywhere. If this GitLab version rejects PKCE,
# fall back to implicit grant — add `auth_type: implicit` and keep the same
# app_id (the OAuth app must then allow the implicit grant flow).
auth_type: pkce
# Paste the OAuth application ID from git.nech.pl (Admin area -> Applications;
# redirect URI https://me.nech.pl/admin/, "Confidential" unchecked, api scope).
app_id: d8696dc65c5f2308ce16f3a0ddbcfb913915562917ad4647cfaa3ea843dee287
media_folder: public/images/blog
public_folder: /images/blog
collections:
- name: blog
label: Blog
label_singular: Post
folder: content/blog
create: true
editor:
preview: false
fields:
- { label: Title, name: title, widget: string }
- { label: Date, name: date, widget: datetime, format: 'YYYY-MM-DD', date_format: 'YYYY-MM-DD', time_format: false }
- { label: Slug, name: slug, widget: string, required: false, hint: 'Kebab-case; must match the filename (content/blog/<slug>.md)' }
- { label: Description, name: description, widget: string, required: false }
- { label: Tags, name: tags, widget: list, required: false, default: [] }
- { label: Draft, name: draft, widget: boolean, default: false }
- { label: Share token, name: share, widget: string, required: false, pattern: ['^[a-z0-9]{2,16}$', 'Lowercase letters and digits only'], hint: '6-char token for the unlisted /blog/d/<slug>-<token> link — node scripts/new-share-token.mjs' }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
<title>Content Manager</title>
<!-- config.yml sits next to this file; the link makes the location explicit. -->
<link href="./config.yml" type="application/yaml" rel="cms-config-url" />
<!--
Decap fallback: config.yml is Decap-compatible as-is. If the Sveltia
bundle breaks, swap only the script below for:
<script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
(Drop the <link> tag above — Decap reads ./config.yml by convention.)
-->
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/@sveltia/cms@0.229.0/dist/sveltia-cms.js"></script>
</body>
</html>
#!/usr/bin/env node
// Print a random 6-char share token for an unlisted draft link —
// paste it as `share:` in the post's frontmatter (node scripts/new-share-token.mjs).
const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
function pick(count) {
const max = 256 - (256 % alphabet.length); // rejection sampling: no modulo bias
const bytes = new Uint8Array(count);
let n = 0;
while (n < count) {
crypto.getRandomValues(bytes);
for (const byte of bytes) {
if (byte < max) {
process.stdout.write(alphabet[byte % alphabet.length]);
if (++n === count) return;
}
}
}
}
pick(6);
console.log();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment