# Queue North Website ``` Status: Current Owner: _null Last reviewed: 2026-08-18 Governs: package.json, src/routes.jsx, Dockerfile, docker-compose.yml — the project-facing overview, whose stack, route list and Docker story all describe those files Review trigger: Any change to the stack, the route list, the Docker or deployment story, the agent pipeline, or where a document lives ``` The business website for Queue North Technologies — an 8x8 Certified Partner delivering UCaaS, contact centre, networking and managed support for SMB and enterprise organisations. Live at **[queuenorth.com](https://queuenorth.com)**, with [qn.isnull.dev](https://qn.isnull.dev) reaching the same container through a second ingress. ## Objective Queue North Website is the modern rebuild of the Queue North Technologies business website. The goal is to replace the current static early-2000s-style HTML/CSS/JS site with a polished 2026 business website that clearly presents Queue North as a trustworthy communications, contact center, networking, and managed support partner. The site should feel: - Bright and professional - Modern but not flashy - Business-first, not cyber/gaming/crypto - Easy to navigate - Clear about Queue North's 8x8 partnership and service expertise - Optimized for consultation and support request conversion ## Target Stack - **Vite** — build tool, not Next.js - **React** — SPA frontend - **React Router** — client-side routing - **Tailwind CSS** — utility-first styling - **shadcn/ui** — component primitives - **Sonner** — toast notifications - **TanStack Query** — server state management - **Express** — backend API - **better-sqlite3** — SQLite database ## Layout Direction The design direction is a light-first B2B technology layout with strategic dark navy sections. Primary structure: 1. **Hero** - Dark navy section - Clear headline and value proposition - Primary CTA: `Request Consultation` - Secondary CTA: `Explore Services` - Trust chips: 8x8 Certified Partner, Veteran Owned, 25+ Years Experience, SMB to Enterprise 2. **Trust / Certification Bar** - Light section - Reinforces 8x8 partner credibility 3. **Services Preview** - White cards on a bright background - Concise service explanations - Links to service detail pages 4. **Why Queue North** - Three-pillar section: - Architecture - Deployment - Lifecycle Support 5. **Industries** - Healthcare - Retail - Manufacturing - Education & Finance 6. **Final CTA** - Dark navy conversion band - Consultation-focused message ## Routes ```txt / Home /about About /services Services index /services/:slug 7 service detail pages /industries Industries index /industries/:slug 4 industry detail pages /contact Contact form → POST /api/leads /support Support form → POST /api/support /privacy-policy Privacy policy * 404 ``` Defined in `src/routes.jsx`. **Every one of them is prerendered to static HTML at build time** by `scripts/prerender.js` — the SPA hydrates on top. `/privacy-policy` additionally has a server-rendered fallback because Meta's crawler does not run JavaScript. The standalone `/8x8` route was removed at `0.6.6`; that content now lives inside the UCaaS and contact-centre service pages. ## Where the work is **Open work lives in the issue tracker, not in this file.** Milestones are batches, issues are deliverables. There used to be a phase checklist here and in four other documents; by the time it was removed it said *"Phase 5 — In Progress"* while the last four commits said *batch 0.9.3*. That is the second record this convention exists to remove. - **What is left, and what is next:** the milestones at [dream.scheller.ltd/null/Queue-North-Website](https://dream.scheller.ltd/null/Queue-North-Website/milestones) - **What is broken:** issues labelled `P0`, `P1`, `P2` - **What the batches were, before the tracker held them:** [docs/history/BATCH_LEDGER.md](docs/history/BATCH_LEDGER.md) The rebuild itself is done: phases 1 through 10 completed between May and August 2026, from the original static HTML site to the current Vite + React SPA with a prerendered build. `docs/history/DEVELOPMENT_LOG.md` has it version by version. ### Where the tracker is **[dream.scheller.ltd](https://dream.scheller.ltd)** — a Forgejo instance, and naming it matters. The convention is portable; the *reporting* is not. Every figure on this project's card at [privacyllc.dev](https://privacyllc.dev) is read from this Forgejo repository. Credentials are in `~/.openclaw/docker-registry.env`: ```bash set -a; . ~/.openclaw/docker-registry.env; set +a python3 scripts/forgejo-issue.py list ``` Despite its name that token is not registry-scoped — it works across the whole API, with push and pull. Never print it into a log or a chat. Two traps that cost an hour each otherwise. **Cloudflare fronts the instance and 1010-blocks clients that do not look like a browser or curl** — Python's `urllib` among them — so every request needs `User-Agent: curl/8.5.0`; `scripts/forgejo-issue.py` already sends it and anything new must too. And **`/issues` returns pull requests too** unless `type=issues` is passed. **Labels are exactly `P0`, `P1`, `P2`, `release-blocker`.** They are queried by name. A fifth label, `P3`, exists on 21 closed issues from before adoption and is frozen — nothing new gets it, because nothing counts it. ## Backend Goals Initial API endpoints: ```txt GET /api/health POST /api/leads POST /api/support ``` Initial SQLite tables: - `leads` - `support_requests` Contact and support forms should submit through Express, save to SQLite, and show user feedback with Sonner. ## Agent Plan The overhaul is handled through the agent pipeline below: 1. **Scarlett** — design system, Tailwind/shadcn layout direction, responsive polish, accessibility review 2. **Neo** — Vite/React implementation, Express API, SQLite/database work, build-system changes 3. **Private Hudson** — security review for API routes, form handling, validation, data exposure, dependency risks, and backend hardening 4. **Scarlett** — UI polish pass after implementation changes 5. **Bishop** — build/runtime verification, route checks, documentation verification, version consistency 6. **Ripley** — final local checks, commit, tag, and push to `dev` Agents do not touch git. Ripley owns all commits, tags, and pushes. This pipeline says **who does which part**. `docs/WORK_CYCLE.md` says **what must be true before a piece of work counts as finished** — closing the issue with its evidence, closing the milestone if the batch landed, updating the documents the change triggered in the same commit, and recording the next action. They are different questions and both apply. `.learnings/` holds each agent's accumulated notes and error logs. It is gitignored and local to this machine. ## Batch Pipeline Rule Work is dispatched as task batches. A batch runs through the required agents, then Ripley pushes that completed batch once. Example Docker batch: ```txt Neo → Private Hudson → Bishop → Ripley ``` The whole batch is one push, not one push per agent. **A batch is a milestone in the tracker.** Closing the last issue under it does not close the milestone, and a complete-but-open milestone reads as a batch still in progress — closing it is what marks the batch *shipped*, and it moves a figure on the project card the same day. > **Version numbers no longer encode the phase.** Until 2026-08-18 the rule was > that the minor version *was* the phase number — Phase 5 releases are `0.5.x` — > with Bishop responsible for keeping `package.json` in agreement with two > root-level documents — PROJECT.md and HISTORY.md, named here without backticks > because both were retired on 2026-08-18 and a backticked path is a claim that > a file exists. It drifted twice; the second time `package.json` said `0.8.3` > for two and a half months while commits said *batch 0.9.3*. The tracker holds > the batch now, and > [docs/history/HISTORY.md](docs/history/HISTORY.md) has the full reasoning. ## Design Direction Based on the redesign review (see [docs/design/REDESIGN_REVIEW.md](docs/design/REDESIGN_REVIEW.md)), the site should feel: - **Modern, clean, stable** — not experimental, not hacker aesthetic - **Business-first** — B2B UCaaS/IT partner, not a dev portfolio - **Trust-forward** — 8x8 partnership, certifications, uptime SLAs front and center - **Human but competent** — less corporate fluff, more concrete outcomes Color palette evolution (not rip-and-replace): - Keep navy dark base, add teal/cyan accents for depth and hierarchy - Improve contrast and spacing - Mobile-first — SMB decision-makers browse on phones Reference brands: RingCentral, Cloudflare, Dialpad — modern but enterprise-trustworthy. See [docs/design/REDESIGN_REVIEW.md](docs/design/REDESIGN_REVIEW.md) for the full redesign assessment. ## Docker Deployment The application can be containerized using Docker for consistent deployment across environments. ### Prerequisites - Docker (v20+) - Docker Compose (v2+) ### Quick Start #### Using Docker Compose (Recommended) ```bash # Build and start the container npm run docker:compose:up # View logs npm run docker:compose:logs # Stop the container npm run docker:compose:down ``` #### Manual Docker Build ```bash # Build the image npm run docker:build # Run the container npm run docker:run ``` ### Environment Variables Set the following in the `.env` file (not included in image by default): ```env NODE_ENV=production SERVER_PORT=3001 ``` ### Data Persistence SQLite database is persisted in the `./db` directory. Data will survive container restarts. **Note on data persistence:** The application uses Docker named volumes (`queuenorth-db` and `queuenorth-logs`) to persist data. Docker manages the ownership and permissions of these volumes automatically, so no manual setup is required. If you prefer to use host bind mounts instead, ensure your host `./db` and `./logs` directories are owned by UID 1001: ```bash mkdir -p ./db ./logs sudo chown -R 1001:1001 ./db ./logs ``` If you encounter "unable to open database file" errors, verify the host directory is writable by the container's UID (1001) or use named volumes as shown above. ### Health Check The container includes a health check at `/api/health`. A healthy container returns: ```json {"status":"ok","timestamp":"2026-05-12T..."} ``` ### Ports - Backend API: `3001` (host) → `3001` (container) ### Build Optimization The `.dockerignore` excludes: - `node_modules` (reinstalled in container) - `dist` (built in container) - `db/` (mounted as volume) - `.git`, logs, private docs This ensures minimal image size and reproducible builds. ## Run Locally ```bash npm install git config core.hooksPath .githooks # per clone — see below npm run dev # Vite on 5173, Express on 3001 ``` `npm run build` is the real gate: client bundle, SSR bundle, then prerender. `docs/TOOLS.md` has every script and which ones can stop you. ### The git hooks Four hooks live in `.githooks/` because `.git/hooks` is not versioned. **The `core.hooksPath` line above is per clone**, so every checkout runs it once; an uninstalled hook fails silently. | Hook | What it does here | | --- | --- | | `pre-commit` | scans the staged diff for credentials, then runs `npm run build` if source is staged | | `commit-msg` | refuses a message with no conventional type (`feat`, `fix`, `ui`, `docs`, `test`, `refactor`, `security`, `perf`, `chore`) | | `post-commit` | **pushes to `origin`** | | `pre-push` | refuses a push that leaves uncommitted or staged edits behind | **`post-commit` pushes.** That is deliberate — work that exists on one laptop is one disk away from gone — but it has a consequence: whatever documentation was not in that commit is now behind the code by one push. That is the mechanical reason documentation edits ride in the same commit as the change that caused them. `SKIP_GUARDS=1` and `SKIP_PUSH=1` are the escape hatches, both loud. ## Project Docs `README.md` is the landing page. Detailed procedures belong in `docs/`, and open work belongs in the tracker. **[docs/DOC_TRUST_MAP.md](docs/DOC_TRUST_MAP.md) is the entry point** — read it before trusting anything else in `docs/`. | Doc | Purpose | | --- | --- | | [docs/DOC_TRUST_MAP.md](docs/DOC_TRUST_MAP.md) | Which document owns which answer, and which source wins when records disagree | | [docs/WORK_CYCLE.md](docs/WORK_CYCLE.md) | What happens at the end of a piece of work, and what privacyllc.dev will and will not update on its own | | [docs/TOOLS.md](docs/TOOLS.md) | Where the scripts are, which ones can stop you, and this project's npm commands | | [docs/OPERATIONS.md](docs/OPERATIONS.md) | What is deployed and where, what watches it, and what to run when it is down | | [docs/planning/PROJECT_PLAN.md](docs/planning/PROJECT_PLAN.md) | Scope, audience, and what this project deliberately is not | | [docs/planning/REQUIREMENTS.md](docs/planning/REQUIREMENTS.md) | Engineering standards. Not changeable without `_null`'s approval | | [docs/architecture/README.md](docs/architecture/README.md) | Module boundaries, the database schema, every API response shape | | [docs/architecture/GUARDS.md](docs/architecture/GUARDS.md) | How to write a check that can actually fail | | [docs/architecture/zoho-setup.md](docs/architecture/zoho-setup.md) | The CRM integration, end to end | | [docs/design/OVERHAUL_PLAN.md](docs/design/OVERHAUL_PLAN.md) | The visual system: tokens, type scale, spacing, layout blueprints | | [docs/design/REDESIGN_REVIEW.md](docs/design/REDESIGN_REVIEW.md) | Brand positioning and the messaging standard | | [docs/security/SECURITY.md](docs/security/SECURITY.md) | Threat model, secrets, third parties, what is out of scope | | [docs/security/SECURITY_CHECKLIST.md](docs/security/SECURITY_CHECKLIST.md) | The list to work through before a release | | [docs/qa/ClaudeQAPlan.md](docs/qa/ClaudeQAPlan.md) | What a QA round consists of | | [docs/qa/ClaudeReport.md](docs/qa/ClaudeReport.md) | The QA verdict — quoted verbatim on the project card | | [docs/qa/ClaudeQACoverage.md](docs/qa/ClaudeQACoverage.md) | What each pass actually reached, and the standing gaps | | [docs/history/DEVELOPMENT_LOG.md](docs/history/DEVELOPMENT_LOG.md) | Dated, append-only: what happened and when | | [docs/history/HISTORY.md](docs/history/HISTORY.md) | The narrative: decisions, and what was tried and dropped | | [docs/history/BATCH_LEDGER.md](docs/history/BATCH_LEDGER.md) | Archived. What the batches were before the tracker held them | ## Agent Notes - Product truth comes from the code and the tracker before prose. - **Do not keep a work list in this README**, or in any markdown file. That is what the tracker is for, and this project has already paid for the lesson. - Finish with [docs/WORK_CYCLE.md](docs/WORK_CYCLE.md), every time: close the issues you finished with the evidence that proves it, close the milestone if the batch landed, update the documents the change triggered **in the same commit**, then record the next action and any blockers before you stop. - Nothing on privacyllc.dev writes itself except the tracker counts and the pushed docs. The summary and next action change only when they are sent; the milestone and blocker tables there change only when a human edits them. - Do not claim a feature is built unless you can cite the route, file, or screenshot that proves it. **There is no test suite to cite.**