Skip to main content

Work / WestTelecom

WestTelecom

A bilingual plan catalogue for a telecom reseller: staff edit plans in an embedded studio and the site updates without a redeploy. The live demo runs on fictional data.

product lines
5
languages
2
content schemas
9
Role
Sole developer, client project
When
2024, hardened 2026
  • Next.js App Router
  • TypeScript
  • Sanity v3
  • GROQ
  • next-intl
  • Tailwind
  • Vercel
WestTelecom is a fictional name. The real site was built for a client in 2024 and is shown here with their branding removed.

The brief

A Canadian telecom reseller needed a bilingual site where customers browse mobile, internet, television, home-security and special-number plans, filter and compare them, then pay through a provider link or leave an enquiry. Retail staff, none of them technical, had to change plans themselves the same day.

I built it in 2024 on the Next.js App Router with an embedded Sanity Studio. In 2026 I audited my own code before showing it publicly, and the fixes are below.

How content moves

Every page is a server component that queries the content store directly. Filters and sorts live in the URL, so a filtered view is a shareable, server-rendered link. A document store fits because plans change shape all the time: a new network tier, another province on a coverage list. In SQL that is a steady stream of migrations.

Staff editorsno deploy neededEmbedded studionine schemas as codeper-document translationContent lakethe only datastoresigned webhookRevalidate routeonly the pages touchedServer componentsparameterised queriesEnglish and ChineseVisitorsfilter, compare, enquireCRM leads

What the audit fixed

  1. 3secrets moved off the browser

    Credentials that shipped in the bundle

    The CMS token, the CRM token and the webhook secret all carried a public prefix. They are server-only now, and an accidental client import fails the build.

  2. 2injection paths closed

    Queries built from the URL

    A job slug and a sort parameter went straight into the query string. Values are bound parameters now, and sort direction is limited to ascending or descending.

  3. 404since day one

    A webhook that never existed

    The revalidation endpoint was saved under a file name the router ignores, so published content never propagated. It is a real route with signature checks now.

  4. 17hidden type errors

    Type checking switched back on

    The build was set to ignore type errors. Clearing them found four with one root cause: five copies of the React types in the dependency tree.

See it running

The demo needs no CMS project: the site's real GROQ queries run against an in-memory sample dataset, every login, studio and checkout route returns 404, and a banner says the brand is fictional. Try it in English and Chinese.

Stack

App
  • Next.js App Router
  • React Server Components
  • TypeScript
  • Tailwind
  • next-intl
Content
  • Sanity v3 embedded studio
  • GROQ
  • signed webhooks
  • on-demand revalidation
Integrations
  • HubSpot
  • NextAuth
  • Vercel Analytics