Skip to content

Onboarding overhaul: phased plan to make JSS first-run great out of the box #462

@melvincarvalho

Description

@melvincarvalho

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:

  1. Initiates OIDC against this pod's own IdP via dynamic client registration + PKCE + DPoP
  2. After auth, hands the user to a configurable post-sign-in URL (default `/account` if exists, otherwise `/`)
  3. 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:

  1. Auto-discoverable URL with prominent credentials hint
  2. Working sign-in form on the IdP root
  3. Account dashboard reachable after sign-in
  4. Visible auth-rung progression (default password → custom password → passkey)
  5. Browseable pod resources (private resources don't blank-page)
  6. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions