Go to file
Ripley 2732d1fc4f fix(security): stop secrets.sh flagging every prerendered page, and clear the dangling doc claims
secrets.sh --built reported ten credentials in dist/ and all ten were the same
false positive: the template's user:pass@host pattern reads the schema.org
JSON-LD on every prerendered page — //queuenorth.com"},"areaServed":{"@ — as a
host, a password and an @. One more finding for every page added, which is the
noise that turns a scanner into something people mute.

Quotes, braces, commas and angle brackets cannot occur in a real userinfo
component. Checked against a database URL with an inline password, one
percent-encoded, and a git remote carrying a token — all three still caught, all
ten false positives gone, and the historical Zoho leak from 033bdf6 still caught
when replayed.

The first version of that fix wrote its three test cases out literally in the
header, and --tracked then reported two credentials in the scanner itself. The
placeholders now use angle brackets, which are in the exclusion class the
comment is describing — so the examples cannot match the pattern they
illustrate. Same shape as the trap DOC_TRUST_MAP.md records about Exempt: lines.

doc-claims: 240 claimed paths, all present, up from 5 dangling. DOC_TRUST_MAP
was claiming banner.webp exists while saying it does not; GUARDS.md pointed at
prove-guard.sh, which this project declined. docs/history/ is excluded rather
than corrected — its entries name files that existed when they were written, and
editing an append-only log to satisfy a present-tense check is a category error.
TOOLS.md records the exclusion and why.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 01:40:46 -05:00
.githooks chore: port the existing pre-push hook into .githooks before activating hooksPath 2026-08-18 01:22:33 -05:00
assets feat(zoho): WebToLead forwarding mode, veteran-owned certified badge, Docker/env/CI updates (batch 0.9.1) 2026-06-14 16:08:29 -05:00
docs fix(security): stop secrets.sh flagging every prerendered page, and clear the dangling doc claims 2026-08-18 01:40:46 -05:00
public feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) 2026-08-01 01:45:52 -05:00
scripts fix(security): stop secrets.sh flagging every prerendered page, and clear the dangling doc claims 2026-08-18 01:40:46 -05:00
server feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) 2026-08-01 01:45:52 -05:00
src feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) 2026-08-01 01:45:52 -05:00
.dockerignore feat: Docker batch 0.2.1 — production-ready containerization 2026-05-12 01:57:55 -05:00
.env.example feat(zoho): WebToLead forwarding mode, veteran-owned certified badge, Docker/env/CI updates (batch 0.9.1) 2026-06-14 16:08:29 -05:00
.gitignore docs: adopt project template, retire the markdown backlog 2026-08-18 01:21:13 -05:00
Dockerfile feat(zoho): WebToLead forwarding mode, veteran-owned certified badge, Docker/env/CI updates (batch 0.9.1) 2026-06-14 16:08:29 -05:00
README.md chore: port the existing pre-push hook into .githooks before activating hooksPath 2026-08-18 01:22:33 -05:00
docker-compose.yml feat(zoho): WebToLead forwarding mode, veteran-owned certified badge, Docker/env/CI updates (batch 0.9.1) 2026-06-14 16:08:29 -05:00
docker-entrypoint.sh fix(security): Hudson remediation + batch 0.5.3 trust signals 2026-05-17 14:45:55 -05:00
index.html feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) 2026-08-01 01:45:52 -05:00
package-lock.json fix: remove React Query, add HTTPS redirect, document CSP Zoho note (#128 #127 #129) (batch 10.0) 2026-05-17 22:33:11 -05:00
package.json chore: adopt template scripts and git hooks, retire phase-versioning 2026-08-18 01:18:20 -05:00
postcss.config.js feat: complete phase 1 foundation 2026-05-12 01:04:17 -05:00
tailwind.config.js feat: Phase 5 SPA fixes, mobile menu, assets, and redesign planning 2026-05-13 22:07:35 -05:00
vite.config.js feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3) 2026-08-01 01:45:52 -05:00

README.md

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 qn.isnull.dev.

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

/                              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.

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 — 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 is read from this Forgejo repository.

Credentials are in ~/.openclaw/docker-registry.env:

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:

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:

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 has the full reasoning.

Design Direction

Based on the redesign review (see 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 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

# 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

# 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):

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:

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:

{"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

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 is the entry point — read it before trusting anything else in docs/.

Doc Purpose
docs/DOC_TRUST_MAP.md Which document owns which answer, and which source wins when records disagree
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 Where the scripts are, which ones can stop you, and this project's npm commands
docs/OPERATIONS.md What is deployed and where, what watches it, and what to run when it is down
docs/planning/PROJECT_PLAN.md Scope, audience, and what this project deliberately is not
docs/planning/REQUIREMENTS.md Engineering standards. Not changeable without _null's approval
docs/architecture/README.md Module boundaries, the database schema, every API response shape
docs/architecture/GUARDS.md How to write a check that can actually fail
docs/architecture/zoho-setup.md The CRM integration, end to end
docs/design/OVERHAUL_PLAN.md The visual system: tokens, type scale, spacing, layout blueprints
docs/design/REDESIGN_REVIEW.md Brand positioning and the messaging standard
docs/security/SECURITY.md Threat model, secrets, third parties, what is out of scope
docs/security/SECURITY_CHECKLIST.md The list to work through before a release
docs/qa/ClaudeQAPlan.md What a QA round consists of
docs/qa/ClaudeReport.md The QA verdict — quoted verbatim on the project card
docs/qa/ClaudeQACoverage.md What each pass actually reached, and the standing gaps
docs/history/DEVELOPMENT_LOG.md Dated, append-only: what happened and when
docs/history/HISTORY.md The narrative: decisions, and what was tried and dropped
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, 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.