Basking: sign in with Authentik only, pages that nest and link

Sign-in is now OpenID Connect against Authentik (authorization code flow
with PKCE, state and nonce). The password, API tokens and the add command
are gone; each person who signs in gets a private notebook in a folder
named from a hash of who they are. An optional allowed list is checked on
every request.

Notes become pages with titles, a tree of subpages, [[links]] with
backlinks that follow renames, a Ctrl+K finder, slash commands, list
continuation, and Write and Read modes. Autosave keeps the text through a
dropped connection or an expired session. Export opens as an Obsidian vault.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
VeillaxandClaude Sonnet 5.5 committed 2026-10-31 22:51:26 -06:00
1 parent b548faa258
commit 98f7730913
19 files changed
+3291 -1578

No files matched your search

+91 -3
View File
@@ -14,7 +14,7 @@
--font:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
--font-mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
--text-xs:12px; --text-sm:13px; --text-base:15px; --text-lg:18px; --text-xl:22px; --text-2xl:28px; --leading:1.5;
--sidebar-w:232px; --content-max:1120px; --touch:44px; --control-h:38px;
--sidebar-w:272px; --content-max:1120px; --touch:44px; --control-h:38px;
--z-sticky:20; --z-overlay:100; --z-toast:200; --ease:140ms ease;
color-scheme:light;
}
@@ -219,8 +219,6 @@
.toast-act { background:transparent; border:0; color:inherit; font:inherit; font-weight:600; text-decoration:underline; cursor:pointer; padding:0; }
.toolbar .push { margin-left:auto; }
.toolbar input[type=search] { max-width:360px; }
.snippet { margin:0 0 var(--s4); padding:var(--s3); background:var(--bg); border:var(--border-w) solid var(--border); border-radius:var(--radius); overflow-x:auto; }
.snippet code { white-space:pre; }
/* rendered markdown */
.md > *:first-child { margin-top:0; } .md > *:last-child { margin-bottom:0; }
@@ -237,3 +235,93 @@
.md pre { margin:0 0 var(--s3); padding:var(--s3); background:var(--bg); border:var(--border-w) solid var(--border); border-radius:var(--radius); overflow-x:auto; }
.md code { background:var(--surface-2); padding:1px 4px; border-radius:4px; } .md pre code { background:none; padding:0; }
.md hr { border:0; border-top:var(--border-w) solid var(--border); margin:var(--s4) 0; }
/* sign in */
.btn-link { display:inline-flex; align-items:center; justify-content:center; gap:var(--s2); min-height:var(--control-h); padding:0 var(--s4); border-radius:var(--radius); font:inherit; font-weight:500; text-decoration:none; white-space:nowrap; background:var(--surface); border:var(--border-w) solid var(--border-strong); color:var(--text); }
.btn-link:hover { background:var(--surface-2); text-decoration:none; }
.btn-link.primary { background:var(--accent); border-color:var(--accent); color:var(--accent-contrast); }
.btn-link.primary:hover { background:var(--accent-hover); border-color:var(--accent-hover); }
.btn-link.wide { display:flex; width:100%; min-height:var(--touch); margin-top:var(--s4); }
.login-h { font-size:var(--text-xl); text-align:center; margin-bottom:var(--s2); }
.center-text { text-align:center; }
kbd { font:inherit; font-family:var(--font-mono); font-size:var(--text-xs); padding:1px 6px; border:var(--border-w) solid var(--border-strong); border-radius:4px; background:var(--surface-2); color:var(--text-muted); white-space:nowrap; }
/* sidebar: search, pages tree */
.navitem.find { border:var(--border-w) solid var(--border); margin-bottom:var(--s2); }
.navitem.find kbd { margin-left:auto; }
.navsec-row { display:flex; align-items:center; justify-content:space-between; padding-right:var(--s1); }
button.tiny { width:26px; min-height:26px; height:26px; }
.treerow { display:flex; align-items:center; gap:2px; }
.treerow.d1 { padding-left:var(--s4); } .treerow.d2 { padding-left:var(--s5); } .treerow.d3 { padding-left:calc(var(--s5) + var(--s3)); }
.treerow.d4 { padding-left:var(--s6); } .treerow.d5 { padding-left:calc(var(--s6) + var(--s3)); } .treerow.d6 { padding-left:calc(var(--s6) + var(--s4)); }
.tree-link { flex:1 1 auto; min-width:0; min-height:32px; padding:var(--s1) var(--s2); }
.twist, .twist-gap { width:24px; height:24px; flex:none; }
.twist { display:inline-flex; align-items:center; justify-content:center; border:0; background:none; color:var(--text-faint); cursor:pointer; border-radius:var(--radius); padding:0; }
.twist:hover { background:var(--surface-2); color:var(--text); }
.twist .icon { transition:transform var(--ease); }
.twist.open .icon { transform:rotate(90deg); }
.sub-add { display:inline-flex; align-items:center; justify-content:center; width:24px; height:24px; flex:none; border:0; background:none; border-radius:var(--radius); color:var(--text-faint); cursor:pointer; opacity:0; padding:0; }
.treerow:hover .sub-add, .sub-add:focus-visible { opacity:1; }
.sub-add:hover { background:var(--surface-2); color:var(--text); }
.navhint { margin:0; padding:var(--s1) var(--s3); font-size:var(--text-sm); color:var(--text-muted); }
@media (pointer: coarse) { .sub-add { opacity:1; } .navitem.find kbd { display:none; } }
/* a page */
.page { max-width:780px; margin:0 auto; }
.page-top { display:flex; align-items:center; justify-content:space-between; gap:var(--s3); flex-wrap:wrap; margin-bottom:var(--s5); }
.crumbs { display:flex; align-items:center; gap:var(--s2); font-size:var(--text-sm); flex-wrap:wrap; min-width:0; }
.crumbs a { color:var(--text-muted); }
.crumbs .sep { color:var(--text-faint); }
.page-actions { display:flex; align-items:center; gap:var(--s2); flex-wrap:wrap; flex:1 1 auto; justify-content:flex-end; }
.page-actions .sub { min-width:4.5em; }
.daynav { margin-bottom:var(--s4); }
.seg { display:inline-flex; border:var(--border-w) solid var(--border-strong); border-radius:var(--radius); overflow:hidden; }
.seg-b { min-height:30px; padding:0 var(--s3); font:inherit; font-size:var(--text-sm); font-weight:500; background:var(--surface); color:var(--text-muted); border:0; cursor:pointer; }
.seg-b + .seg-b { border-left:var(--border-w) solid var(--border-strong); }
.seg-b.on { background:var(--accent-soft); color:var(--accent-text); }
.title-wrap { margin-bottom:var(--s2); }
.title-input { font-size:var(--text-2xl); font-weight:700; letter-spacing:-.02em; line-height:1.25; border:0; padding:0; background:transparent; min-height:0; width:100%; }
.title-input:focus { outline:none; border:0; }
.title-input::placeholder { color:var(--text-faint); }
.day-title { font-size:var(--text-2xl); letter-spacing:-.02em; margin-bottom:var(--s2); }
.editor-wrap { position:relative; margin-top:var(--s3); }
.page textarea.write.big { min-height:45vh; line-height:1.7; font-family:var(--font); font-size:var(--text-base); resize:none; overflow:hidden; }
.view { min-height:45vh; cursor:text; overflow-wrap:anywhere; }
.md-big { font-size:var(--text-base); line-height:1.7; }
.md-big h3.md-h { font-size:var(--text-xl); margin-top:var(--s5); } .md-big h4.md-h { font-size:var(--text-lg); margin-top:var(--s4); }
.tagrow { display:flex; flex-wrap:wrap; gap:var(--s2); margin-top:var(--s4); }
.tagrow:empty { display:none; }
.aside { margin-top:var(--s6); display:flex; flex-direction:column; gap:var(--s5); }
.aside:empty { display:none; }
.aside-sec h2 { font-size:var(--text-xs); font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--text-muted); margin-bottom:var(--s2); }
.linklist { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px; }
.linklist a { display:inline-flex; align-items:center; gap:var(--s2); padding:var(--s1) 0; }
.page-meta { margin-top:var(--s6); }
.wikilink { text-decoration:none; border-bottom:var(--border-w) solid var(--accent-text); }
.wikilink:hover { background:var(--accent-soft); }
.wikilink.missing { color:var(--text-muted); border-bottom-style:dashed; border-bottom-color:var(--text-faint); }
.popup { position:absolute; z-index:var(--z-sticky); min-width:240px; max-width:320px; max-height:260px; overflow-y:auto; padding:var(--s1); background:var(--surface); border:var(--border-w) solid var(--border-strong); border-radius:var(--radius-lg); box-shadow:var(--shadow); }
.popup-row { display:flex; align-items:center; justify-content:space-between; gap:var(--s3); padding:var(--s2) var(--s3); border-radius:var(--radius); cursor:pointer; }
.popup-row.on, .popup-row:hover { background:var(--accent-soft); }
.popup-name { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.popup-hint { color:var(--text-faint); font-size:var(--text-xs); font-family:var(--font-mono); white-space:nowrap; }
.mirror { position:absolute; left:-9999px; top:0; visibility:hidden; white-space:pre-wrap; overflow-wrap:break-word; box-sizing:content-box; }
.notice .btn-link { min-height:30px; }
/* quick find and the move picker */
.shade-top { align-items:start; padding-top:12vh; }
.finder-input { font-size:var(--text-lg); min-height:44px; margin-bottom:var(--s2); }
.finder-list { display:flex; flex-direction:column; gap:2px; max-height:50vh; overflow-y:auto; }
.finder-row { display:flex; align-items:center; gap:var(--s3); width:100%; padding:var(--s2) var(--s3); border:0; border-radius:var(--radius); background:none; color:var(--text); font:inherit; text-align:left; cursor:pointer; }
.finder-row.on, .finder-row:hover { background:var(--accent-soft); }
.finder-name { flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.finder-sub { flex:1 1 0; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:right; }
.pad { padding:var(--s3); margin:0; }
/* note cards and settings */
.note.openable { cursor:pointer; }
.note-title { font-size:var(--text-lg); margin-bottom:var(--s2); }
.note-title a { color:inherit; text-decoration:none; }
.note-title a:hover { text-decoration:underline; }
.keys { list-style:none; margin:0; padding:0; display:grid; gap:var(--s2); }
@media (max-width:640px) { .page-actions { justify-content:flex-start; } .shade-top { padding-top:var(--s4); } }