Mockups for emailed, pre-provisioned invites and the server-driven feature tour that runs after a new person signs in — on web, Android, and Apple. The current flow hands someone an 8-character code and drops them on an empty home screen; this replaces both halves.
The existing Invite Codes tab stays exactly as it is for the casual "drop a code in Discord" case. A second tab, Invitations, is for inviting a specific person: the admin scopes their access up front, and the invitee only sets a password.
Email a personal link. Access is set here, so they only choose a password.
| Recipient | Access | Status | Sent | |
|---|---|---|---|---|
|
dana@example.com
Invited by quick
|
Household · All libraries | Accepted | 2 days ago | |
|
marco@example.com
Invited by quick
|
Household · All libraries | Sent · expires in 6d | 18 hours ago | |
|
kid@example.com
Invited by quick
|
Kids · Movies, Cartoons | Sent · expires in 2d | 5 days ago | |
|
old@example.com
Invited by quick
|
Guests · Movies | Expired | 3 weeks ago |
They get an email with a link. Their username is their email address, so all they pick is a password.
Rendered with the existing internal/mail layout, so it matches the
notification and verification emails already going out. No images, no tracking pixel, works
link-free in a plain-text client.
Quick set up an account for you on their Silo server.
"Hey — set yourself up whenever. The 4K stuff is all under Movies."
Set your password
Or paste this into your browser:
https://silo.example.com/invite/9f2c8a4e1b7d63f0
users, so a mistyped address can't create a dead account or squat a username.
One field. Everything else was decided when the invite was sent, so this screen has nothing to
ask. It reuses the existing auth-shell and journey-progress treatment
from Login and Signup.
Choose a password and you're in. You'll sign in with your email address.
Already set this up? Sign in
Right after the password, before the tour: profiles for everyone on the couch. This is step 3
of the journey indicator on the claim screen. Kids get a content ceiling and library limits;
grandparents get big defaults and no clutter; the parent gets a PIN so nobody wanders into
their profile. All of it maps onto the profile model that already exists —
is_child, max_content_rating, PIN, and
per-profile library restrictions.
Everyone gets their own history, watchlist, and recommendations. Add the whole household now or later — this is your account either way.
Profiles share your account — they're not separate logins.
user_id); this screen just surfaces it at the
right moment instead of leaving it buried in settings.
This is the part that actually sells Silo. The steps come from the server, so a server with requests disabled never shows a requests stop — and a stop added later shows up without a client release. Two presentations: a full card for concept stops, a spotlight for "here's where it lives."
You've probably used Plex or Jellyfin. Most of this will feel familiar — but a handful of things work differently here, and they're the reason this server exists. Quick look?
Silo won't burn your data plan guessing. Set a ceiling and it sticks — per device, if you want. You can override it for a single library or a single show later.
Saved as you go. Settings → Playback has the rest.
Favorites teach recommendations what you like. The watchlist is the "get to it eventually" pile — and Silo tells you when something on it lands.
Everything here is in Settings, and you can replay this any time from Settings → Personalize.
Same server manifest, native presentation. The phone apps get a full-screen pager because spotlights don't survive a 390pt viewport; tvOS gets a focus-driven variant with no text entry.
Invited by Quick · silo.example.com
Everyone gets their own history and recommendations.
Start a room, send the link. Play, pause, and seek stay in sync for everyone — no browser extension, no screen share, and it works from the phone or the TV.
Language and appearance follow your profile across every device.
Anything you add on your phone shows up on this screen, and Silo tells you when something on it arrives.
POST /api/v1/admin/invitations — email, group, role, libraries, note.
Server stores only a SHA-256 of the token; the raw token exists in the email and nowhere else.
internal/mail — same SMTP config, layout, and diagnostics as notifications.
If email is off, the endpoint returns the link for the admin to copy instead of failing.
GET /api/v1/invitations/{token} — unauthenticated, returns only what the
claim screen renders: inviter name, email, expiry. Rate-limited alongside the other auth endpoints.
POST /api/v1/invitations/{token}/accept — creates the user with the
pre-bound access, marks the invite accepted in the same transaction, and returns a
normal session token pair. Same shape as signup, so clients reuse their session plumbing.
POST /api/v1/profiles per added profile — the existing endpoint,
which already carries name, avatar, PIN, is_child, rating ceiling, and
per-profile library restrictions. No new backend surface for this step.
GET /api/v1/onboarding/flow?surface=web — ordered steps for this server
and this profile, with features that are off already filtered out.
POST /api/v1/onboarding/progress — per profile, so finishing on the web
means the phone doesn't ask again.
Every step carries a kind the client switches on. A client that
doesn't recognize a kind skips it silently — that's what lets the server add a stop without
waiting for three app store releases.
| Step kind | What it does | Gated on |
|---|---|---|
| welcome | Framing card. Static copy from the server. | Always |
| feature_card | Explains one capability. Title, body, optional illustration key. | Per feature |
| setting_choice | Renders a control and writes a real profile setting. | Setting key exists |
| spotlight | Highlights a named UI anchor. Web and tablet only. | Surface supports it |
| handoff | Ends the tour by routing somewhere — e.g. the taste-seed picker. | Always |