# 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`, fronted by Cloudflare at `qn.isnull.dev` | 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`. - **The roll-forward procedure is not written down.** Publishing is `scripts/docker-push.sh`; how nebula moves to a new image is currently in somebody's head. Noted in `docs/OPERATIONS.md`.