Nischal Tiwari

The welcome email that runs itself: wiring Auth0 to OneSignal for cricnepal

How Nepal’s biggest cricket site went from unbranded auth emails and zero email marketing to a fully automated onboarding lifecycle — in one afternoon, with nothing new to host.

It started with a question that sounded trivial: “Do we still run the OneSignal default prompt?”

cricnepal.com — Nepal’s home of cricket coverage — had 174 web-push subscribers and a nagging suspicion. Visitors were seeing two notification prompts: a carefully engagement-gated branded modal the team had built, and, on top of it, OneSignal’s generic dashboard slide prompt firing on every page at the ten-second mark. Nobody remembered turning it on.

Pulling that one thread unravelled something bigger: the site had readers creating accounts every day, and not a single email had ever welcomed them. Worse — the emails they did receive were actively hurting the brand.

The starting point

Here’s what a new cricnepal reader experienced before this project:

  • Verification email from [email protected] — a stranger’s domain, “Powered by Auth0” stamped in the footer, and a verification link pointing at dev-q8ijssilgbpa7t5m.us.auth0.com. Technically functional. Trust-wise, a disaster.
  • No welcome email. Sign up, verify, silence.
  • Duplicate notification prompts stepping on each other.
  • Email addresses captured by the account system (Auth0) sat in one silo; push subscribers sat in another (OneSignal). The two had never met.

The team’s instinct was to reach for the usual fix: stand up a small service, or bolt another workflow onto their n8n automation server, to ferry signups into an email tool. More infrastructure, more credentials to rotate, one more thing to break at 2 a.m. during a live match.

We went a different way.

The idea: let the two platforms talk directly

Both ends of the problem already ran on managed platforms. Auth0 knows the moment a reader signs up. OneSignal knows how to send beautiful lifecycle email. The only missing piece was a handshake — and Auth0 has a native home for exactly that: Actions, small scripts that run inside Auth0’s own infrastructure at defined moments in the login flow.

Twenty-eight lines of JavaScript later, the entire pipeline looked like this:

  1. A reader creates an account (email/password or social login — the Action triggers on first login, which covers both).
  2. The Auth0 Action POSTs the new user to OneSignal’s API: email address, a stable external_id (the Auth0 user ID, so push and email unify into one profile later), and a signup_source: auth0 tag.
  3. A OneSignal segment watches for that tag. The moment a user enters it, the Welcome Journey fires: branded welcome email, sent once, never repeated.

No server. No cron. No middleware. Nothing new to deploy, monitor, patch or pay for. If cricnepal’s own infrastructure went down entirely, new readers would still get welcomed.

The details that make it professional

A dedicated sending domain. Marketing email goes out from edm.cricnepal.com — its own SPF, DKIM and DMARC records, isolated from the root domain. A bad spam-complaint day on the newsletter can never poison deliverability for the transactional mail, and vice versa.

Transactional mail re-homed. Auth0’s default sender was replaced with the site’s own SMTP relay, so verification and password-reset emails now arrive from cricnepal <[email protected]> — with a fully branded template: logo, brand red, a proper “didn’t create this account? ignore this” line, and a plain-text fallback link.

The custom domain, everywhere. One overlooked toggle — use custom domains for email notifications — and every verification link went from dev-xxxx.us.auth0.com to auth.cricnepal.com. Small change, outsized trust gain.

A welcome email that onboards, not just greets. Inspired by the best sports-media onboarding (FOX Sports’ “add favorites” pattern), the welcome email doesn’t say thanks for joining and stop. It shows new readers what the account is for: follow your teams and players, track live matches ball-by-ball, follow whole tournaments, play the daily player quiz — each with its own deep link, all funnelling to one primary call-to-action: build your For You feed. Every link carries UTM tags, so analytics shows exactly which hook converts new readers into engaged ones.

What actually went wrong (because something always does)

Case studies that skip the debugging are lying to you. Three things bit us, and each one is a lesson:

1. The silent 400. The Action’s API call was wrapped in a try/catch — but fetch doesn’t throw on HTTP errors. OneSignal had been rejecting every request with 400: app_id malformed (a bad paste in a config secret), and the catch block never fired. The fix was two lines: capture the response, log status + body. The lesson is older than the web: a failure you can’t see is a failure that doesn’t exist — until it’s three test accounts deep. Auth0’s built-in test runner turned the invisible into a one-line diagnosis.

2. The SMTP relay that refused politely. Every Auth0 email silently died with 525 5.7.1 Unauthorized IP address. The SMTP provider’s security settings were IP-allowlisting SMTP calls — fine for a fixed server, fatal for a cloud platform that sends from a rotating pool of addresses. One toggle, fixed. If your ESP supports authorized-IP restrictions, know what’s going to be calling it.

3. The prompt that wouldn’t die. That original double-prompt problem? Deleting the dashboard prompt looked like it worked — but OneSignal’s “Typical Site” mode requires at least one prompt configured, so the save silently failed validation and the generic popup kept firing. The real fix was switching the integration to Custom Code mode, which matches how the site actually initializes the SDK and removes dashboard-driven prompts permanently.

The result

  • Every new reader gets a branded verification email from cricnepal’s own domain, linking through auth.cricnepal.com
  • Minutes after first login, a branded onboarding email lands — teaching follows, live match centre, tournaments and the quiz
  • Push and email identities unify under one profile per reader, ready for cross-channel journeys
  • The duplicate prompt is gone; the only notification ask is the site’s own engagement-gated modal
  • Zero new infrastructure — the whole pipeline lives inside platforms the site already paid for

And the pattern is reusable. Any product running Auth0 (or any IdP with hooks) plus any modern messaging platform can do this: let the platforms talk to each other, and keep your own servers out of the conversation.

namastec is a digital agency in Kathmandu. We build and run cricnepal.com — Nepal’s largest cricket platform — and take on a small number of client projects where product, content and infrastructure meet. Talk to us: namastec.com

How we built a cricnepal design system that scaled design and development together

cricnepal.com grew from a news blog into a live cricket platform — match centre, scorecards, player archives, ICC rankings. The interface multiplied faster than any one designer could hold in their head. Here is how a single source of truth let design and code move at the same speed.

By early 2026, cricnepal was no longer one product. It was an editorial site, a live scoring engine, a stats archive and a set of social-card templates — each shipping on its own clock. The visual language drifted a little with every new surface. We fixed it by building one system that design and engineering edit from the same place.

What was breaking

  • The same button, card and tab existed in four slightly different versions across editorial and match centre.
  • Colour lived as raw hex scattered through components — a brand tweak meant a find-and-replace across the codebase.
  • Designers worked in a Figma file that no longer matched what the site actually rendered.
  • Every new feature re-litigated decisions we had already made: which card? which tab style? how bold is too bold?

None of these are unusual for a product that grew organically. But each one taxed both sides at once: designers redrew components that already existed, and engineers rebuilt them slightly wrong. The cost wasn’t any single mistake — it was that design and development were drifting apart a few pixels at a time.

The goal we set was narrow and testable: change something once, have it land everywhere — in design and in code.

01 One source of truth, mirrored on both sides

We started by collapsing the brand into a token system rather than a screen library. The Figma file and the code share the exact same structure: tokens.css and input.css on the engineering side, mirrored as variable collections in Figma. The design file’s front page literally states it: “the same source of truth as the code.”

The design-system index in Figma. Foundations, components and guidelines on the left; the three variable collections — primitives, semantic, font weights — that both Figma and the codebase consume.

Tokens are layered in three tiers, and the layering is the whole point:

  • 79 primitives — raw hex scales (neutral, brand, info, success, warning). Reference values only; no component ever reads them directly.
  • 41 semantic tokens — role-based aliases like --surface--text--border--action-primary. This is the layer components consume.
  • 8 font-weight tokens — encoding a rule, not just a number (more on that below).

The brand anchors. Six fixed reference colours sit at the top of the primitive layer — the jersey navy and red lead, the rest map cricket meaning (formats, states).