Music marketing / Dashboard rebuild and migration
ArtistHub dashboard rebuild and migration
2026Part-time contract, ArtistHub LLCFull-stack engineerNot public yet: built and tested, not rolled out
The core of ArtistHub's new Next.js and Supabase dashboard, and the opt-in move of Classic users onto it with the same account, pages, stats and billing.
Problem
ArtistHub is replacing its Vue artist dashboard with a new one in Next.js on Supabase. The old dashboard, now called Classic, still serves 5,316 users who own an artist or pay for one. Both apps read the same database.
Those users had to be able to try the new dashboard without losing a page, a stat or a billing setting, and to go back to Classic whenever they wanted.
Constraints
- The switch changes which dashboard someone uses, never their data. Anything that changes a public page is a separate step with a preview and an Undo.
- Logins in the new dashboard must keep each user's Classic id. 5,191 users already had one; 125 didn't.
- 449 accounts pay or are comped, almost all through Braintree in Classic. The new dashboard bills through Stripe, so no account can end up paying twice.
- Invites are marketing email: they carry an unsubscribe link, and the 111 paying owners who opted out of marketing email only see the in-app banner.
- About 200 users were active in the last 90 days, too few for a random holdout to measure anything. Rollout uses waves and pause thresholds instead.
What I owned
- The core of the new Next.js and Supabase artist dashboard.
- The whole migration from Classic, starting with its design: read-only production counts, research into how other products ran opt-in moves, six invite waves, and the thresholds that pause a wave.
- One click from Classic into the new dashboard, already signed in, with a login created under the same id and the Classic password hash.
- The first-run screens: a welcome card, "formerly Smart Links" labels on renamed pages, an "Open in Classic" list for features not rebuilt yet, and a roster for managers of three or more artists.
- Switching back: one click, then an optional question about why, asked at most once every 14 days.
- Billing: Braintree plans stay managed in Classic, and the new sign-up and checkout refuse accounts that already pay.
- Undo for every optional upgrade, written as PostgreSQL functions with their own SQL tests.
- Invite and reminder emails, switched off until the client approves sending, and the Classic side of the flow in Vue.
Result
Built and tested end to end on a test account. Rollout starts when the client applies the database migrations and approves the first invite emails.
Hardest problem
Signing a Classic user into the new dashboard
Classic's "Try the new dashboard" button posts the user's Classic session token to the new dashboard in a form, never in the address. The new dashboard checks it with Classic's public key (RS512 only, at most 90 days old, from Classic's own origins), creates the same-id login if it's missing, and signs the user in on the server. Neither app holds the other's private key.
Showing that nothing was lost
The first screen has to show the numbers users already know. For 8 October to 8 November the new dashboard showed 12,419 views and Classic 12.1k. The difference came from Classic counting from the current hour on the first day rather than from midnight, so the welcome card uses Classic's date range and says that in one line.
Invite links that mail scanners can't use up
Email security scanners open links before people do. The invite link carries a signed token that expires after 45 days and lands on a page that signs nobody in. Only the Continue button moves on to sign-in, with the email already filled in.
Stack
- New dashboard
- Next.js · React · TypeScript · TanStack Query
- Data and sign-in
- Supabase · PostgreSQL · Supabase Auth
- Classic
- Vue · GraphQL · Braintree
- Postmark
