# Queue North Website — Project Plan

```
Status: Current
Owner: _null
Last reviewed: 2026-08-18
Governs: scope, audience, and what this project deliberately is not
Review trigger: Any change of scope, audience, or platform
```

> The vision. The **milestones in this repository's issue tracker** hold the
> sequence of work; this holds what the work is *for*. When the two disagree,
> this one is the argument and those are the plan — resolve it rather than
> letting both stand.
>
> Deliberately no batch list here. A schedule in a document goes stale the day
> after it is written and nothing notices; a schedule in the tracker is updated
> by the act of doing the work.
>
> The engineering standards that go with this — stack, frontend, backend,
> database, code quality and security rules — are in
> [`REQUIREMENTS.md`](REQUIREMENTS.md), which carries its own change policy and
> is not summarised here.

## What this is

The business website for Queue North Technologies — an 8x8 Certified Partner and
Cisco partner delivering UCaaS, contact centre, networking, cabling, wireless and
managed lifecycle support to SMB and enterprise organisations. It replaces a
static early-2000s HTML/CSS/JS site with a Vite + React SPA and a small Express
API that captures consultation and support requests.

Its single job is conversion: a business decision-maker arrives, understands
within seconds that Queue North is a credible communications and IT partner, and
submits a consultation or support request that reaches the CRM.

## Who it is for

**Primary:** SMB and mid-market decision-makers — owners, operations managers, IT
managers — evaluating a communications or managed-IT partner. They are usually on
a phone, they are comparing two or three vendors, and they are buying risk
reduction rather than technology.

**Secondary:** existing Queue North customers looking for the support path.

Not developers, not procurement at a Fortune 500, and not people who already know
what UCaaS stands for.

## What it is deliberately not

The most useful section in this file. Every entry is a decision that stops being
re-litigated.

- **Not Next.js.** Vite + React SPA, no SSR at request time, no server
  components. Stated as a requirement rather than a preference in
  `REQUIREMENTS.md` because it kept being re-proposed. The build does prerender
  every route to static HTML, which is a build step and not a framework change.
- **Not a CMS.** Content lives in `src/data/*.js` and in the page components. A
  blog is an open question (#70), not a commitment, and if it happens it starts
  as hard-coded articles.
- **No user accounts.** There is no login, no session, no authorisation, and none
  is planned. This is why `docs/security/SECURITY_CHECKLIST.md` has no
  authorisation section and `docs/qa/ClaudeQAPlan.md` has no pass for it.
- **No money moves through it.** No checkout, no subscriptions, no refunds. Pass
  I of the QA plan is deleted rather than carried as permanently skipped.
- **Not a developer portfolio.** The failure mode this rebuild exists to fix.
  `docs/design/REDESIGN_REVIEW.md` is the standard: hacker aesthetic, terminal
  cosplay and infrastructure in-jokes destroy enterprise trust faster than
  anything else on the page.
- **Not a support ticketing system.** `/api/support` records a request and
  forwards it. It does not track state, assign, or escalate — Zoho does that.

## Stack and platform

| Concern | Choice | Why |
| --- | --- | --- |
| Build | Vite 6 | Fast, and the project needed a client bundle rather than a framework |
| Frontend | React 19, React Router 7 | SPA with client routing; every route also prerendered at build time |
| Styling | Tailwind 3 with a custom Queue North theme | Tokens in `docs/design/OVERHAUL_PLAN.md` |
| Components | shadcn/ui-style local primitives | Copied in, not depended on. Seven primitives is less surface than a component library |
| Backend | Express 4 | Two POST endpoints and a health check. A framework would be larger than the thing |
| Storage | SQLite via better-sqlite3 | Two tables, low write volume, one process. Synchronous by design, which suits a request-scoped insert |
| CRM | Zoho, WebToLead by default | Fire-and-forget behind SQLite, so a CRM outage cannot cost a lead |
| Anti-abuse | Google reCAPTCHA v3 plus a honeypot field | The forms are the only writable surface |
| Hosting | Docker on **nebula**, container `qn-website-dev`, image `dream.scheller.ltd/null/queue-north-website:dev`. Served at **queuenorth.com** through nginx-proxy-manager, and at `qn.isnull.dev` through Cloudflare — two ingresses, one container | See `docs/OPERATIONS.md` |

## Success looks like

Observable, in this order:

1. A first-time visitor on a phone can tell what Queue North does and reach the
   consultation form without pinch-zooming or hunting.
2. A submitted contact form produces a row in `leads` **and** a lead in Zoho, and
   the visitor sees a confirmation either way.
3. The site passes WCAG 2.1 AA on the pages a buyer actually walks — currently it
   does not, which is what `Batch 10` in the tracker is for.
4. Nothing on the page is a claim the business cannot substantiate. Two open
   issues say it currently is (#108, #110).

## Known risks

- **Unverifiable marketing claims are live.** A fabricated-looking certification
  number and an unverified "25+ years" both ship today (#108, #110). This is the
  only risk here that is a credibility problem rather than an engineering one,
  and neither can be fixed without the owner.
- **The lead database has no backup.** `/app/db/queuenorth.db` in a Docker named
  volume on nebula is the only copy of every inbound lead and support request.
  Tracked in `Batch 15`. Until a restore has been proven, this project has a
  backup script and not backups.
- **Owner-blocked content is the long pole.** Testimonials (#69), the blog (#70)
  and the About corrections (#68, #162) are all waiting on somebody who is not on
  this team. They should not be counted as engineering progress.
- **No automated tests at all.** No test runner, no typecheck. `npm run build` is
  the only gate, and it catches syntax and imports rather than behaviour. Recorded
  as a standing gap in `docs/qa/ClaudeQACoverage.md`.
- **Deployment is scripted but has never been run end to end.** `npm run
  release` publishes and `npm run deploy` moves Portainer stack 58, both added
  2026-08-18 and both exercised only in `--dry-run`. The first real run of either
  is still ahead.
