Refinement of #433 (Phase 3 of #427). After landing the landing-page seed, two things felt off in practice:
- The page is mode-frozen — once seeded by a
--single-user run, every subsequent run (any mode) serves the same HTML because of skip-if-exists. A multi-user restart still showed "Mode: single-user" and a non-functional Sign-in button.
- The buttons don't reflect what the server actually exposes. "Sign in" links to
/idp which 404s when IDP isn't enabled; "Create a pod" only makes sense in multi-user + IDP. We worked it out at write time, but mode changes invalidate it.
Also: the page should be professional enough for an operator running an IDP / multi-user deployment to leave as their public landing — not a first-run celebration screen.
Proposal
Keep the current seed model (write /index.html, /.acl, /index.html.acl skip-if-exists — operators can't write ACLs by hand, the .acl seeds are operator quality-of-life infrastructure). Refine the page itself so it adapts to the server's current state at load time, not at seed time.
Page content
Welcome
Your JSS Solid pod is running at http://localhost:4443
This is a Solid pod server. Solid is an open standard for personal data —
your data lives in pods you own, and apps connect to it.
[ Get started → ] ← always, → jss.live/docs/getting-started/
[ Sign up ] [ Sign in ] ← HEAD-adaptive (see below)
──────────────────────
v0.0.187 · single-user · idp
features: nostr · webrtc · …
Powered by JSS · GitHub · Customise: edit /index.html in your data dir
- Mode-agnostic copy — works for single-user (server hosting your one pod) and multi-user (server hosting pods for others). The status pill carries the mode difference; the buttons carry the IDP difference.
- Calm and professional — no emoji headline, no confetti, sentence case. Polished enough to leave as a public landing.
- Visible live URL with a status dot — the installer's confirmation that "this worked" without explicit celebration.
- Get started → docs. Sends first-time installers straight to the friendly onboarding page rather than the docs root.
HEAD-adaptive Sign up / Sign in
A small inline script (no external deps) does HEAD /idp/register on page load and reveals the right buttons based on the response code:
| Status |
Reveal |
| 200 |
Sign up and Sign in (multi-user + IDP, registration open) |
| 403 |
Sign in only (single-user — registration intentionally disabled) |
| 404 |
Neither (IDP not enabled) |
| (network error) |
Neither (fail closed; Get started + Docs still present) |
Both buttons start with display: none and are revealed after the HEAD completes — no flash of incorrect content. Same seeded HTML works in all modes; mode changes adapt without regenerating the file.
Docs page
docs/getting-started/ already exists in JavaScriptSolidServer/docs (Docusaurus). The current Quick Start is curl-focused; we'd add a friendly "Getting started" landing for first-time installers — the page someone lands on after clicking the button on the local landing.
Sketch of the doc page contents (handled in the docs repo via this issue's checklist):
- Brief congratulation: server is running
- Try it in a Solid app — Mashlib data browser, Pilot, etc.
- Sign up / sign in walkthrough (multi-user vs single-user)
- Connect from your own app (OIDC client_id, callback URL pattern)
- Enable features — link to flag reference
- Customise the landing page — edit
/index.html in your data dir
- Where to ask questions
Implementation
src/ui/server-root.html — refresh the template per the spec above; add the inline HEAD-adaptive script for Sign up / Sign in (button containers data-cond="register" / data-cond="login", both display:none until the script reveals them).
src/ui/server-root.js — minor: keep the renderer + seeder largely as-is. Drop the "Personal pod" subtitle in favour of mode-agnostic copy. Pass the request URL into the template so the live URL renders into the page (or render window.location.origin client-side — preferable since it adapts to whatever host the visitor used).
src/server.js — unchanged.
Tests
- All existing 14 tests in
test/server-root.test.js keep passing or get updated for new copy.
- New: assert the inline HEAD-detection script is present in the rendered HTML.
- New: assert the rendered HTML contains the docs link (
jss.live/docs/getting-started/).
Acceptance
Out of scope
- A standalone
/idp/login page (sc.net / NSS-style direct credential form). Useful but its own feature — would unblock a true Login button without OIDC client.
- Dynamic render at request time (instead of seed). Considered, but operators would have to write ACLs by hand to override the page — too high a bar.
- An optional "skip the landing seed entirely" CLI flag. Discussed; deferred until someone actually needs it.
Refs #427 (Phase 3 refinement).
Refinement of #433 (Phase 3 of #427). After landing the landing-page seed, two things felt off in practice:
--single-userrun, every subsequent run (any mode) serves the same HTML because of skip-if-exists. A multi-user restart still showed "Mode: single-user" and a non-functional Sign-in button./idpwhich 404s when IDP isn't enabled; "Create a pod" only makes sense in multi-user + IDP. We worked it out at write time, but mode changes invalidate it.Also: the page should be professional enough for an operator running an IDP / multi-user deployment to leave as their public landing — not a first-run celebration screen.
Proposal
Keep the current seed model (write
/index.html,/.acl,/index.html.aclskip-if-exists — operators can't write ACLs by hand, the.aclseeds are operator quality-of-life infrastructure). Refine the page itself so it adapts to the server's current state at load time, not at seed time.Page content
HEAD-adaptive Sign up / Sign in
A small inline script (no external deps) does
HEAD /idp/registeron page load and reveals the right buttons based on the response code:Both buttons start with
display: noneand are revealed after the HEAD completes — no flash of incorrect content. Same seeded HTML works in all modes; mode changes adapt without regenerating the file.Docs page
docs/getting-started/already exists inJavaScriptSolidServer/docs(Docusaurus). The current Quick Start is curl-focused; we'd add a friendly "Getting started" landing for first-time installers — the page someone lands on after clicking the button on the local landing.Sketch of the doc page contents (handled in the docs repo via this issue's checklist):
/index.htmlin your data dirImplementation
src/ui/server-root.html— refresh the template per the spec above; add the inline HEAD-adaptive script for Sign up / Sign in (button containersdata-cond="register"/data-cond="login", bothdisplay:noneuntil the script reveals them).src/ui/server-root.js— minor: keep the renderer + seeder largely as-is. Drop the "Personal pod" subtitle in favour of mode-agnostic copy. Pass the request URL into the template so the live URL renders into the page (or renderwindow.location.originclient-side — preferable since it adapts to whatever host the visitor used).src/server.js— unchanged.Tests
test/server-root.test.jskeep passing or get updated for new copy.jss.live/docs/getting-started/).Acceptance
https://jss.live/docs/getting-started/.seedServerRootbehaviour unchanged (skip-if-exists; .acl seeds intact).Out of scope
/idp/loginpage (sc.net / NSS-style direct credential form). Useful but its own feature — would unblock a true Login button without OIDC client.Refs #427 (Phase 3 refinement).