A rewards program inside the customer portal, inside a fixed hosting fee

RaftLabs built a customer rewards platform for a full-fibre broadband provider. Customers reach offers, coupons, and competitions from their account portal with single sign-on, and the backend runs on Vercel and Neon to fit a fixed monthly hosting fee.

from a new codebase to a live staging environment
13 days
lifetime of each signed, single-use sign-in token
10 s
token transport options specified for the provider's security team to choose from
3

Short answer

RaftLabs built a customer rewards platform for a full-fibre broadband provider in Northern Ireland and Cumbria. Customers reach offers, coupons, and competitions from the provider's account portal with single sign-on, using a 10-second, single-use signed token. The backend runs on Vercel, Neon, and Drizzle to fit a fixed monthly hosting fee. Built and on staging, but not launched.

Engagement

The engagement

Client
A full-fibre broadband provider in Northern Ireland and Cumbria (name withheld)
Delivered through
A loyalty agency partner
Scope
Customer rewards web app inside the provider's account portal, admin console, API, and portal sign-in integration
Team
One full-stack developer, a project manager, and QA
Timeline
Scoping from May 2026; staging live on 18 June 2026; agency and brand feedback rounds from July to September 2026
Status
Built and on staging; not yet launched

The situation

A broadband subscription is a relationship most customers only notice when something breaks: a bill, an outage, a complaint. A rewards program is the one positive touchpoint the provider controls. A full-fibre broadband provider wanted its customers to get partner offers, coupons, and competitions as part of their subscription, reached from the account portal they already use. Customers shouldn't sign in twice, and the loyalty agency running the program had to keep it inside a fixed monthly hosting fee.

Those two constraints shaped the build. Sign-in had to hand a customer from the portal straight into rewards without an extra login. Hosting had to stay small enough to run and monitor inside the fee. The platform is built and on staging. It hasn't launched, so this page covers the decisions behind it. Results come after launch.

Before and after

From a new program to a rewards platform inside the portal

Before
  • No rewards program existed for the provider's broadband customers
  • A second login would have kept customers out of a program that lived outside the portal
  • The program had to run and be monitored inside a fixed monthly hosting fee
  • An import of every portal customer would have created accounts for people who never used rewards
After
  • Offers, coupons, and competitions sit behind a rewards link in the provider's account portal
  • Single sign-on takes a customer from the portal into rewards with no second login
  • A Hono API on Vercel Functions, Neon serverless Postgres, and Drizzle ORM keep hosting to one platform
  • Accounts start on a customer's first click-through, so the platform only holds people who used it
  • Participation KPIs live inside the admin console

The decisions that shaped the build

  • Hosting had to fit a fixed monthly fee

    The agency's first written concern was cost: it needed to run and monitor the program within a fixed monthly fee. That ruled out a stack of separately hosted services, each with its own sizing and upkeep.

    On 15 June, ten days into the codebase, we settled the backend on Vercel: a Hono API on Vercel Functions, Neon serverless Postgres, Drizzle ORM, Better Auth for admin sign-in, Vercel Blob for media, and Vercel Cron for an hourly lifecycle job. One platform hosts every part of the program. No production data existed yet, so the schema was written once, in Drizzle.

    Without a separate permission layer, access checks live in application code: customer queries scope to the signed-in customer, and admin routes check roles. That was the biggest correctness risk in the design, and the API's integration tests cover it. The API region sits in London, next to the database.

  • Customers should reach rewards without a second login

    Customers arrive from the provider's portal and shouldn't sign in twice. When a customer clicks the rewards link, the portal signs a token. The rewards platform checks the signature, rejects anything older than 10 seconds, accepts each token once, and sets its own 24-hour session. Replay protection and secret rotation are built in, so the shared secret can change without a coordinated cutover.

    The sign-in contract is written up as a specification for the provider's security team. It keeps the payload to one opaque customer reference, signs it with HMAC-SHA256, and encrypts it as a JSON Web Encryption token. It offers three ways for the token to travel: an encrypted token in the URL with an immediate bounce, a POST that keeps it out of the address bar, or a back-channel exchange where the browser only carries a spent one-time code. The provider picks the one that fits their standard. It's data minimisation applied to a login. The specification awaits the provider's sign-off.

  • Accounts start on a customer's first click-through

    The early plan included an API to pre-load an account for every portal customer. The agency agreed to drop it on 7 May.

    The platform creates an account the first time a customer arrives through sign-in and refreshes their last-access time on every visit. It only stores and hosts people who actually used it, and the first-time-active and active-user KPIs count real visits instead of imported rows.

    Access stays with the provider. The portal shows the rewards link once a customer's installation is complete and hides it when they leave or are suspended. Sessions last 24 hours, so a removed customer loses access within a day at most.

  • Reporting moved into the admin console

    The agency asked whether KPIs would come through Metabase. For a program this size, a separate reporting service meant one more thing to host, size, and maintain inside the fixed fee.

    We built the KPIs into the admin console instead: active users, engaged users, first-time active users, reward views and redemptions, competition views and entries, and campaign views and redemptions. The numbers sit next to the rewards they describe, and there's no second system to keep running.

  • A full component library for the people running the program daily

    Operators use the admin to create rewards, campaigns, competitions, and homepage content, then publish and schedule them. Each change needs a confirmation step, and the target is WCAG 2.1 AA.

    On earlier projects, building admin screens from minimal shadcn/ui primitives meant hand-building accessibility, browser support, and theming for each control, and AI coding agents burned time on the same gaps. For this admin we chose Mantine, a full component library that already handles those. The customer app keeps Tailwind and shadcn/ui under the provider's brand.

System flow

How a customer gets from the portal to a reward

A simplified view based on the project repository and the SSO specification. It shows the path a provider's security and loyalty teams need to understand. Supporting services are left out.

  1. Entry

    Provider's customer portal

    Shows the rewards link to eligible customers and signs a short-lived token for each click. The provider controls who sees the link.

  2. Sign-in

    SSO route and session

    Checks the signature, the 10-second expiry, and a single-use nonce, creates the account on the first visit, and sets a 24-hour session cookie.

  3. API

    Hono on Vercel Functions

    Handles redemptions, competition entries, coupon allocation, and voucher PDFs, with access checks in application code and an hourly lifecycle job.

  4. Data and operations

    Neon, Drizzle, and the admin console

    Postgres holds rewards, campaigns, competitions, coupons, and engagement events. Operators manage them and read KPIs in the admin.

the build

What customers and operators get

The platform splits into a customer web app, an admin console, and an API, each deployed as its own Vercel project.

  1. Offers, coupons, and competitions under the provider's brand

    Customers browse partner rewards and claim coupons delivered as a text code, a redirect link, or a branded PDF voucher. Coupons can be unique per customer or shared. Competitions can include multiple-choice questions, sponsors can run video content, and a family page filters rewards by Northern Ireland county.

  2. An admin that moves rewards from draft to live to ended

    Operators author rewards, campaigns, competitions, brands, categories, and homepage content, then publish or schedule them. Business rules run on the server, and each change asks for confirmation. An hourly job expires finished campaigns, settles closed competitions, and clears spent sign-in nonces. An audit log records what changed.

  3. Participation KPIs without a separate reporting tool

    The admin shows active, engaged, and first-time active users alongside views and redemptions for rewards, competitions, and campaigns. Engagement events feed those figures directly, so the numbers operators read come from the same data the customer app writes.

Proof

What exists today, and what this page can't claim yet

The platform hasn't launched, so there are no usage, engagement, or cost results. These are the delivered and recorded facts.

ResultWhat changedPeriod or contextEvidence and limitation
Delivery speedStaging live 13 days after the codebase was created5 to 18 June 2026Project-recorded: repository history
BackendOne Drizzle schema on Neon, with a Hono API on Vercel FunctionsBackend decision on 15 June 2026Project-recorded: backend plan and repository
Sign-in10-second, single-use signed tokens with replay protection and secret rotationCurrent staging buildProject-recorded; the opaque-reference contract awaits the provider's security sign-off
Hosting modelBackend runs on Vercel and Neon with no AWS servicesStagingProject-recorded; the hosting fee is confidential and not published
OutcomesNot yet availableBefore launchKPIs are built into the admin console and will report once customers arrive

The lesson

Agree the sign-in contract with the client's security team before you build

Single sign-on from a customer portal touches the client's identity rules, and those rules differ by sector. A telecom provider's security rules can differ from what a rewards platform built for another sector assumes.

If you're adding sign-in from a customer portal into a partner platform, take the payload, the transport, and the revocation model to the client's security team before building. One review call shapes the whole contract, and it costs less on day one than in the middle of the build.

The second lesson is about where the attention went. The admin got attention first, and the agency's review rounds surfaced customer-side UX details we should have caught earlier. The customer app is where a new program earns its first impression, so start there and build the admin around what customers see.

Where to go next

What stayed out on purpose

Scope decisions made during the engagement. None of these are part of the current build.

  1. Next 01

    Features beyond the launch brief

    The brief covered offers, coupons, and competitions inside the portal. Anything new waits for a later phase.

  2. Next 02

    Instant session revocation

    Sessions expire after 24 hours for launch. A revocation webhook or a status check can close that gap before voucher campaigns, if the provider wants it.

  3. Next 03

    An in-app entry point

    Phase 1 assumes customers arrive from the web portal. An entry inside a mobile app's web view would need the redirects and session cookie reviewed first.

How it runs

Next.js
The customer app runs on Next.js with Tailwind and shadcn/ui under the provider's brand. The sign-in route, the session cookie, and a strict nonce-based content security policy live in the same app.
Hono on Vercel Functions
A small API framework on Vercel's Node runtime handles redemptions, competition entries, coupons, voucher PDFs, and the hourly lifecycle job, deployed as its own project next to the two apps.
Neon and Drizzle
Serverless Postgres with a typed schema keeps the database on the same platform as the API. Access rules live in application code, scoped by the signed-in customer and the admin's role.
React, Vite, and Mantine
The admin console uses a full component library, so tables, filters, forms, and confirmation dialogs behave the same everywhere and meet an accessibility target without hand-building each control.
Vercel
Three Vercel projects cover the customer app, admin, and API, with Vercel Blob for media and Vercel Cron for scheduled jobs. One platform keeps hosting inside a fixed monthly fee.

Common questions

The portal signs a short-lived token when the customer clicks the rewards link. The rewards platform checks the signature, rejects tokens older than 10 seconds, and accepts each token only once. On the first visit it creates the account, then sets its own 24-hour session. In the specification sent to the provider, the token carries one opaque customer reference and nothing else.

Yes, if identity is an opaque reference that only the provider can resolve to a person. The specified design keys every reward, redemption, and entry to that reference and greets customers generically. A right-to-erasure request then comes through the provider, who sends the reference so the platform can delete the activity held against it.

The provider hides the rewards link, so a former customer can't start a new session. An existing session runs out within 24 hours. A customer who later rejoins arrives under a new reference and starts fresh, with no history carried over. For immediate removal, a revocation webhook or status check can be added before voucher campaigns.

Ten seconds covers a redirect, and the window is configurable if testing shows slow devices need more. Both sides need clocks synced with NTP, and the verifier allows about two seconds of clock skew. The shared secret can also rotate: the platform accepts the previous secret during an overlap window, so rotation doesn't need a coordinated cutover.

The program had to run inside a fixed monthly hosting fee. Vercel and Neon put the API, database, scheduled jobs, and media storage on one platform, so there were fewer services to size, monitor, and pay for. Access rules moved into application code, covered by integration tests, and there was no production data to migrate yet.

Here, staging went live 13 days after the codebase was created, with scoping in May beforehand. Most of the calendar since has gone to sign-in review and brand feedback, and the platform hasn't launched yet. Plan the timeline around integration and approvals. See our loyalty program development service and pricing guide.

Work with us

Recognise this problem in your business?

Tell us what's broken. We'll diagnose it and show you exactly what to fix first, before you commit to anything.

  • Scope and cost agreed before work starts. No surprises. No obligation.
  • Working prototype within 3 weeks of kickoff.
  • Pay by milestone. You see progress before each invoice.
  • 60-day post-launch warranty. Bug fixes, UI tweaks, and deployment support. No retainer.
  • All conversations are NDA-protected.