Context
Over the past few weeks of building jspod (a thin opinionated wrapper around JSS for first-time users), the same gaps in JSS's first-run experience kept coming up. jspod ended up re-implementing a lot of onboarding surface that would benefit every JSS deployment if it lived upstream. This issue collects those gaps into a phased plan.
Goal: a fresh `jss start` on a clean machine should produce the same "60 seconds to working pod with visible identity, manageable session, and clear next steps" experience that jspod ships today — without needing a wrapper.
Phases
Each phase is independently shippable. Numbered roughly by leverage / dependency order.
Phase 1 — Stop returning blank pages
Problem. Two surfaces return empty / unhelpful HTML today:
Proposed. Both surfaces return real HTML with actionable CTAs. The 401 page links to a sign-in flow; the bare `/idp` page renders the login form (matching what CSS, NSS, ESS all do).
Why first. Everything else assumes the user can sign in without being bounced through an external app. Without this, the rest of the onboarding loop has dead ends.
Phase 2 — Customizable root landing page
Problem. JSS seeds `pod-data/index.html` with a useful HEAD-adaptive template, but there's no clean way for a downstream wrapper to ship its own version. jspod currently overwrites the file every start as a stopgap (issue #459).
Proposed. Either skip-if-exists (cheapest) or a CLI/config hook like `--landing-page ` or `--no-default-landing`. Lets wrappers (jspod and future siblings) own the front door without fighting JSS's init.
Phase 3 — Built-in sign-in app
Problem. Today `/idp` requires OAuth params (i.e. a Solid app initiating the flow). Without those it renders an unhelpful page. A user wanting to authenticate "into their own pod" without picking an external app first has no path.
Proposed. A small server-rendered or bundled sign-in page at e.g. `/signin` that:
- Initiates OIDC against this pod's own IdP via dynamic client registration + PKCE + DPoP
- After auth, hands the user to a configurable post-sign-in URL (default `/account` if exists, otherwise `/`)
- Looks like a sign-in page, not a "find another app" splash
Reference. solid-oidc is already the right primitive — jspod ships a ~150-line static page that uses it. Could be bundled, or rendered server-side using the same templates JSS already has for the OAuth-initiated login form.
Phase 4 — Built-in account dashboard
Problem. JSS exposes account-management endpoints (`PUT /idp/credentials` for password rotation, `GET /idp/account/export` for backup, `POST /idp/account/delete` for multi-user removal, passkey register options/verify) but has no UI to call them. CSS has Pivot. JSS has nothing equivalent.
Proposed. A dashboard at e.g. `/account`:
- WebID, pod URL, sign-out button
- Change password (calls `PUT /idp/credentials`)
- Add a passkey (calls `/idp/passkey/register/*`) — climbs the auth ladder (jspod#6)
- Export pod (links to `/idp/account/export`)
- (Optionally) badges showing the user's current auth rung
- (Optionally) credential tokens list, registered WebIDs, etc. — matching CSS Pivot's scope
Reference. jspod's account.html is a working starting point (~4KB, plain JS, no framework).
Phase 5 — Safer defaults
Problem. A few stock-JSS defaults work against new users:
- Binds to `0.0.0.0` by default — a default password (when seeded) is reachable from the LAN with no warning
- `TOKEN_SECRET` has a documented "set this in production" requirement, but no auto-generation when unset → either operators set it (and forget to rotate) or JSS runs without secure JWT signing
- Hard-errors on `EADDRINUSE` instead of trying `port+1` like Vite / Next.js dev servers
Proposed.
- Default `--host 127.0.0.1`. Loud warning if user passes `--host 0.0.0.0` and a default password is seeded.
- Auto-generate `TOKEN_SECRET` on first start, persist at `/.token-secret` (mode 0600), reuse on subsequent starts. Env var still wins for operator-managed deployments.
- Port-hop up to N times if requested port is busy. Honor a `--strict-port` flag for production.
Reference. jspod implements all three; the code patterns are small and portable.
Phase 6 — Banner + discoverability
Problem. `jss start`'s console output is minimal — URL + a few feature lines. New users have to dig for "how do I sign in" or "what's my password." Compare to Vite / Next.js dev banners which surface the essentials with one glance.
Proposed.
- Highlight the sign-in URL prominently
- If seeded default credentials exist, print them once (and a hint to change)
- Clear "open this URL in your browser" line
- "Powered by JSS vX.Y.Z" / docs link
- README quickstart that matches the banner
Phase 7 — Tiny default data browser
Problem. The full mashlib bundle is hundreds of KB. For "show me what's in my pod" first-touch, this is overkill. JSS could ship a tiny default browser as the baseline (with `--mashlib-cdn` still available as opt-in for power users).
Proposed. Bundle a ~200-byte ES module (or render inline) that renders the JSON-LD data island JSS already embeds, with clickable URIs. Mashlib stays available for the full editing experience.
Reference. jspod's data-browser.js — single file, no deps, AGPL. Could move upstream verbatim or inline into JSS's HTML wrapper.
Cross-references
- jspod#1 — original friction-removal umbrella; this issue is the upstream half
- jspod#3 — single-user positioning (informs which surfaces JSS needs)
- jspod#6 — auth ladder framing (informs Phase 4's climb features)
- JSS#459 — Phase 2 prerequisite
- JSS#461 — Phase 1 prerequisite
Definition of done (overall)
A user running `jss start` on a clean machine — without installing jspod or any wrapper — gets the same end-to-end experience jspod currently provides:
- Auto-discoverable URL with prominent credentials hint
- Working sign-in form on the IdP root
- Account dashboard reachable after sign-in
- Visible auth-rung progression (default password → custom password → passkey)
- Browseable pod resources (private resources don't blank-page)
- Safe defaults (loopback-only, auto-generated JWT secret, port-hopping)
When that's true, downstream wrappers like jspod become positioning layers (branding, opinionated copy, packaging for `npx`) rather than re-implementations of missing surfaces. That's the right division of labor.
Context
Over the past few weeks of building jspod (a thin opinionated wrapper around JSS for first-time users), the same gaps in JSS's first-run experience kept coming up. jspod ended up re-implementing a lot of onboarding surface that would benefit every JSS deployment if it lived upstream. This issue collects those gaps into a phased plan.
Goal: a fresh `jss start` on a clean machine should produce the same "60 seconds to working pod with visible identity, manageable session, and clear next steps" experience that jspod ships today — without needing a wrapper.
Phases
Each phase is independently shippable. Numbered roughly by leverage / dependency order.
Phase 1 — Stop returning blank pages
Problem. Two surfaces return empty / unhelpful HTML today:
Proposed. Both surfaces return real HTML with actionable CTAs. The 401 page links to a sign-in flow; the bare `/idp` page renders the login form (matching what CSS, NSS, ESS all do).
Why first. Everything else assumes the user can sign in without being bounced through an external app. Without this, the rest of the onboarding loop has dead ends.
Phase 2 — Customizable root landing page
Problem. JSS seeds `pod-data/index.html` with a useful HEAD-adaptive template, but there's no clean way for a downstream wrapper to ship its own version. jspod currently overwrites the file every start as a stopgap (issue #459).
Proposed. Either skip-if-exists (cheapest) or a CLI/config hook like `--landing-page ` or `--no-default-landing`. Lets wrappers (jspod and future siblings) own the front door without fighting JSS's init.
Phase 3 — Built-in sign-in app
Problem. Today `/idp` requires OAuth params (i.e. a Solid app initiating the flow). Without those it renders an unhelpful page. A user wanting to authenticate "into their own pod" without picking an external app first has no path.
Proposed. A small server-rendered or bundled sign-in page at e.g. `/signin` that:
Reference. solid-oidc is already the right primitive — jspod ships a ~150-line static page that uses it. Could be bundled, or rendered server-side using the same templates JSS already has for the OAuth-initiated login form.
Phase 4 — Built-in account dashboard
Problem. JSS exposes account-management endpoints (`PUT /idp/credentials` for password rotation, `GET /idp/account/export` for backup, `POST /idp/account/delete` for multi-user removal, passkey register options/verify) but has no UI to call them. CSS has Pivot. JSS has nothing equivalent.
Proposed. A dashboard at e.g. `/account`:
Reference. jspod's account.html is a working starting point (~4KB, plain JS, no framework).
Phase 5 — Safer defaults
Problem. A few stock-JSS defaults work against new users:
Proposed.
Reference. jspod implements all three; the code patterns are small and portable.
Phase 6 — Banner + discoverability
Problem. `jss start`'s console output is minimal — URL + a few feature lines. New users have to dig for "how do I sign in" or "what's my password." Compare to Vite / Next.js dev banners which surface the essentials with one glance.
Proposed.
Phase 7 — Tiny default data browser
Problem. The full mashlib bundle is hundreds of KB. For "show me what's in my pod" first-touch, this is overkill. JSS could ship a tiny default browser as the baseline (with `--mashlib-cdn` still available as opt-in for power users).
Proposed. Bundle a ~200-byte ES module (or render inline) that renders the JSON-LD data island JSS already embeds, with clickable URIs. Mashlib stays available for the full editing experience.
Reference. jspod's data-browser.js — single file, no deps, AGPL. Could move upstream verbatim or inline into JSS's HTML wrapper.
Cross-references
Definition of done (overall)
A user running `jss start` on a clean machine — without installing jspod or any wrapper — gets the same end-to-end experience jspod currently provides:
When that's true, downstream wrappers like jspod become positioning layers (branding, opinionated copy, packaging for `npx`) rather than re-implementations of missing surfaces. That's the right division of labor.