Skip to content

Feat/lui 144 welcome badge - #98

Merged
luidgi-dev merged 5 commits into
devfrom
feat/lui-144-welcome-badge
Sep 19, 2026
Merged

luidgi-dev merged 5 commits into
devfrom
feat/lui-144-welcome-badge

Conversation

@luidgi-dev

Copy link
Copy Markdown
Owner

What

Adds a one-time welcome moment on first entry into the app, for a real first login and for demo entry. Closes LUI-144 (https://linear.app/luidgi-dev/issue/LUI-144/add-first-login-welcome-badgemoment-real-account-and-demo-account).

Why

Uxia synthetic user testing (LUI-142) found that first-time users landed on an empty Rhythm board with no acknowledgment of the sign-up to app transition, which reads as abrupt rather than as the calm coach voice.

How it works

Two triggers, because the two accounts are fundamentally different.

Real account. A welcomed_at key in the Supabase auth user_metadata, the same JSON the sign-up form already writes username and timezone into. The protected layout reads it off the user object it already fetches, so there is no schema change, no migration, and no extra query. markWelcomed() persists it through auth.updateUser({ data }), which merges into the existing metadata rather than replacing it. The result is exactly once per account, on any device, whatever the entry path (confirm CTA, a login days later, a fresh PWA install).

user_metadata is client-writable by design, so it must never hold anything authorization depends on. tier stays in profiles behind RLS. A cosmetic "already greeted" flag is the correct use: the worst case if forged is that someone replays their own welcome toast.

Demo account. demo@striveapp.cc is a single shared user, so a per-user flag would be consumed by the first visitor in the world. signInAsDemo() redirects to /protected/flow?welcome=demo instead, and the toaster strips the param with history.replaceState once shown, which also keeps an iOS standalone relaunch (it can restore the last URL) silent. Firing on every demo entry is intended: each entry is a different person.

No new UI primitive. The toaster renders no markup of its own, it pushes through the existing useToast().show() and inherits the card, the accent icon circle, the 5s auto-dismiss and the one-at-a-time queue already used by "Ritual defined".

Copy

Trigger Icon EN
First login AudioWaveform Welcome, {username}. Let's define your first ritual.
Demo entry Compass Demo account. Explore freely, everything resets each night.

FR keys added in the same commit. firstLogin reuses the onboarding line from docs/UX_WRITING.md; AudioWaveform is the icon already used by the Rhythm empty state, so the toast reads as part of Rhythm.

Files

  • components/welcome/welcome-toaster.tsx (new) client component, mounted inside ToastProvider
  • app/[locale]/protected/layout.tsx computes showFirstLogin, mounts the toaster
  • app/[locale]/protected/actions.ts adds markWelcomed() next to markNudgesSeen
  • app/[locale]/actions.ts demo redirect carries ?welcome=demo
  • messages/en.json, messages/fr.json new welcome namespace

Required after merge

Every existing account lacks the metadata key, so all current beta users would see a "define your first ritual" toast despite already having rituals. Run this once, after the deploy is live, so only accounts created from then on are greeted:

update auth.users
   set raw_user_meta_data = raw_user_meta_data || jsonb_build_object('welcomed_at', now())
 where raw_user_meta_data->>'welcomed_at' is null;

Running it before the deploy would let any account created in between slip through.

Out of scope

  • Routing a first-time user to Rituals instead of Rhythm. Both empty states are equivalent and funnel to the same CTA, and the condition would have to live in proxy.ts (which intercepts /protected before the forwarder page renders). Worth revisiting only if beta feedback still shows entry confusion.
  • The landing "Try the demo" button has no pending state while the server action signs in, a separate Uxia finding that deserves its own issue.

Testing

  • npm run lint, tsc --noEmit, npm run build and the 76 unit tests pass
  • Verified locally: first login shows the toast once, a reload and a logout/login cycle stay silent, and ?welcome=demo shows the demo toast and cleans the URL back to /protected/flow
  • The demo button itself is to be verified on the preview deploy: the local DEMO_USER_PASSWORD is stale and the Vercel variable is marked sensitive, so it cannot be read back

…tracking

- Modified the sign-in flow for demo users to include a welcome flag in the redirect URL, ensuring a tailored experience.
- Implemented a new function to record when users have seen the first-login welcome, preserving the welcome state for shared demo accounts without affecting future visitors.
…ayout

- Added the WelcomeToaster component to display a welcome message for new users upon their first login.
- Implemented logic to track whether the user has been welcomed, ensuring demo users receive a tailored greeting.
- Wrapped the WelcomeToaster in a Suspense component to handle loading states effectively.
- Introduced the WelcomeToaster component to display tailored welcome messages for new users and demo accounts.
- Implemented logic to ensure the welcome message is shown only once per user session, enhancing the onboarding experience.
- Integrated with the existing ToastProvider for consistent user feedback across the application.
… French translations

- Introduced new "welcome" section in `en.json` and `fr.json` to provide tailored greetings for first-time users and demo accounts.
- Enhanced user onboarding experience by including specific messages for new users and demo exploration.
@vercel

vercel Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
strive Ready Ready Preview Sep 19, 2026 6:50pm UTC

@github-actions

Copy link
Copy Markdown

Strive PR Agent Review

The review could not be generated for this run (model unavailable or rate-limited). Push again to retry.

…eter handling

- Changed the icon displayed in the welcome toast from AudioWaveform to Hand for better visual representation.
- Enhanced URL parameter management by ensuring only the welcome parameter is removed, preserving other query parameters and the hash in the URL.
@luidgi-dev
luidgi-dev merged commit 03d6b02 into dev Sep 19, 2026
7 checks passed
@luidgi-dev
luidgi-dev deleted the feat/lui-144-welcome-badge branch September 19, 2026 18:51
@luidgi-dev luidgi-dev mentioned this pull request Sep 20, 2026
5 tasks done

This branch was successfully deployed

1 active deployment
Preview — 6170b24d Deployed Sep 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant