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.
- Next.js App Router
- TypeScript
- Sanity v3
- GROQ
- next-intl
- Tailwind
- Vercel
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.
What the audit fixed
- 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.
- 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.
- 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.
- 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
