diff --git a/README.md b/README.md index dd30173..d2704f0 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Version numbers correlate directly to the active phase: - ~~Refined service/industry cards and CTA sections~~ ✅ - ~~Mobile-first layout polish~~ ✅ -- **Phase 4 — Forms + Backend Hardening**: `0.4.x` 🔄 In Progress +- **Phase 4 — Forms + Backend Hardening**: `0.4.x` ✅ Complete - ~~Contact and support forms fully wired to Express~~ ✅ - ~~SQLite persistence verified~~ ✅ - ~~Client-side validation + Sonner feedback~~ ✅ @@ -124,11 +124,24 @@ Version numbers correlate directly to the active phase: - ~~Rate limiting + security headers + CORS~~ ✅ - ~~Backend/API hardening as needed~~ ✅ -- **Phase 5 — Verification + Release Readiness**: `0.5.x` - - Build/runtime verification - - Route and form testing +- **Phase 5 — Verification + Redesign**: `0.5.x` 🔄 In Progress + - ~~SPA router fix (BrowserRouter → RouterProvider)~~ ✅ + - ~~TS generics stripped from .jsx files~~ ✅ + - ~~Mobile menu Sheet/Dialog fix~~ ✅ + - ~~DialogTitle accessibility fix~~ ✅ + - ~~SPA catch-all route for client-side navigation~~ ✅ + - ~~Image assets copied to public/ (were 404)~~ ✅ + - ~~Real Queue North logo replacing placeholder~~ ✅ + - ~~CSP updated for Google Fonts~~ ✅ + - ~~Hamburger menu + SheetContent CSS fix~~ ✅ + - ~~tailwindcss-animate installed and configured~~ ✅ + - Hero section rewrite — B2B clarity, 8x8 partnership prominence + - Trust signals section — metrics, badges, certifications + - Services rewrite — business outcomes over technical jargon + - Why Queue North refinement — concrete differentiators + - Footer + CTA pass — contact paths everywhere + - Remaining P0/P1 audit fixes (Zoho, su-exec, email constraint) - Accessibility checks - - Documentation and release cleanup - Final push to `dev` for the completed phase Patch versions increment for completed task batches after the full pipeline finishes. Dispatch a task batch, run it through the required agents, then push that completed batch once. Example: Docker task batch goes through Neo → Private Hudson → Bishop → Ripley, then pushes as `0.2.1`. Notes/tags should use the version number only. @@ -179,9 +192,23 @@ Do not increment the patch version for each individual agent inside the same bat Notes, tags, and checkpoint labels should use only the version number, such as `0.2.1`. -## Design Source of Truth +## Design Direction -See [OVERHAUL_PLAN.md](./OVERHAUL_PLAN.md) for the full rebuild plan and Scarlett's design implementation brief. +Based on the redesign review (see `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 [review.md](./review.md) for the full redesign assessment. ## Docker Deployment diff --git a/package-lock.json b/package-lock.json index 8bb50f2..fc7e547 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "queuenorth-website", - "version": "0.4.6", + "version": "0.4.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "queuenorth-website", - "version": "0.4.6", + "version": "0.4.8", "dependencies": { "@radix-ui/react-dialog": "^1.1.0", + "@radix-ui/react-visually-hidden": "^1.2.4", "@tanstack/react-query": "^5.62.0", "better-sqlite3": "^11.8.0", "cors": "^2.8.6", @@ -20,6 +21,7 @@ "react-dom": "^19.0.0", "react-router-dom": "^7.1.3", "sonner": "^1.7.0", + "tailwindcss-animate": "^1.0.7", "zod": "^3.24.2", "zustand": "^5.0.3" }, @@ -40,7 +42,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -777,7 +778,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -799,7 +799,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -809,14 +808,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -827,7 +824,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -841,7 +837,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -851,7 +846,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -1192,6 +1186,70 @@ } } }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.4.tgz", + "integrity": "sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1848,14 +1906,12 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -1869,7 +1925,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, "license": "MIT" }, "node_modules/aria-hidden": { @@ -1975,7 +2030,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2047,7 +2101,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -2156,7 +2209,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -2217,7 +2269,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -2242,7 +2293,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -2296,7 +2346,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -2391,7 +2440,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -2487,14 +2535,12 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, "license": "Apache-2.0" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, "license": "MIT" }, "node_modules/dunder-proto": { @@ -2738,7 +2784,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -2755,7 +2800,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -2768,7 +2812,6 @@ "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -2784,7 +2827,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -2868,7 +2910,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -2964,7 +3005,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -3114,7 +3154,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -3127,7 +3166,6 @@ "version": "2.16.2", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.3" @@ -3143,7 +3181,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3163,7 +3200,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -3176,7 +3212,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -3186,7 +3221,6 @@ "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -3229,7 +3263,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, "license": "MIT", "engines": { "node": ">=14" @@ -3242,7 +3275,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, "license": "MIT" }, "node_modules/lru-cache": { @@ -3295,7 +3327,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -3314,7 +3345,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -3394,7 +3424,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0", @@ -3406,7 +3435,6 @@ "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, "funding": [ { "type": "github", @@ -3471,7 +3499,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3490,7 +3517,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -3542,7 +3568,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-to-regexp": { @@ -3555,14 +3580,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -3575,7 +3598,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -3585,7 +3607,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -3595,7 +3616,6 @@ "version": "8.5.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3624,7 +3644,6 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", @@ -3642,7 +3661,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3668,7 +3686,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3711,7 +3728,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -3737,7 +3753,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -3751,7 +3766,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, "license": "MIT" }, "node_modules/prebuild-install": { @@ -3823,7 +3837,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -4034,7 +4047,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^2.3.0" @@ -4058,7 +4070,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -4081,7 +4092,6 @@ "version": "1.22.12", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4103,7 +4113,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -4159,7 +4168,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -4441,7 +4449,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -4506,7 +4513,6 @@ "version": "3.35.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -4545,7 +4551,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4558,7 +4563,6 @@ "version": "3.4.19", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", - "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -4592,6 +4596,15 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -4624,7 +4637,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0" @@ -4634,7 +4646,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -4647,7 +4658,6 @@ "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -4664,7 +4674,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -4682,7 +4691,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4695,7 +4703,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -4727,7 +4734,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, "license": "Apache-2.0" }, "node_modules/tslib": { diff --git a/package.json b/package.json index 123c213..a97b380 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "@radix-ui/react-dialog": "^1.1.0", + "@radix-ui/react-visually-hidden": "^1.2.4", "@tanstack/react-query": "^5.62.0", "better-sqlite3": "^11.8.0", "cors": "^2.8.6", @@ -28,6 +29,7 @@ "react-dom": "^19.0.0", "react-router-dom": "^7.1.3", "sonner": "^1.7.0", + "tailwindcss-animate": "^1.0.7", "zod": "^3.24.2", "zustand": "^5.0.3" }, diff --git a/public/assets/8x8_Logo_White.svg b/public/assets/8x8_Logo_White.svg new file mode 100644 index 0000000..5688274 --- /dev/null +++ b/public/assets/8x8_Logo_White.svg @@ -0,0 +1,13 @@ + + \ No newline at end of file diff --git a/public/assets/Cabling.png b/public/assets/Cabling.png new file mode 100644 index 0000000..0c11adc Binary files /dev/null and b/public/assets/Cabling.png differ diff --git a/public/assets/Consulting & Training.png b/public/assets/Consulting & Training.png new file mode 100644 index 0000000..8b62d8d Binary files /dev/null and b/public/assets/Consulting & Training.png differ diff --git a/public/assets/Financial Services.png b/public/assets/Financial Services.png new file mode 100644 index 0000000..58aff01 Binary files /dev/null and b/public/assets/Financial Services.png differ diff --git a/public/assets/Healthcare.png b/public/assets/Healthcare.png new file mode 100644 index 0000000..78af388 Binary files /dev/null and b/public/assets/Healthcare.png differ diff --git a/public/assets/JointLogoWhite.png b/public/assets/JointLogoWhite.png new file mode 100644 index 0000000..bc0629c Binary files /dev/null and b/public/assets/JointLogoWhite.png differ diff --git a/public/assets/Local Networking.png b/public/assets/Local Networking.png new file mode 100644 index 0000000..4da244c Binary files /dev/null and b/public/assets/Local Networking.png differ diff --git a/public/assets/Managed Support.png b/public/assets/Managed Support.png new file mode 100644 index 0000000..8f132fe Binary files /dev/null and b/public/assets/Managed Support.png differ diff --git a/public/assets/Manufacturing.png b/public/assets/Manufacturing.png new file mode 100644 index 0000000..625191b Binary files /dev/null and b/public/assets/Manufacturing.png differ diff --git a/public/assets/Modern call center in action.png b/public/assets/Modern call center in action.png new file mode 100644 index 0000000..e6d03dc Binary files /dev/null and b/public/assets/Modern call center in action.png differ diff --git a/public/assets/Retail.png b/public/assets/Retail.png new file mode 100644 index 0000000..bb3a9ed Binary files /dev/null and b/public/assets/Retail.png differ diff --git a/public/assets/Unified communications in a modern office.png b/public/assets/Unified communications in a modern office.png new file mode 100644 index 0000000..f0e3690 Binary files /dev/null and b/public/assets/Unified communications in a modern office.png differ diff --git a/public/assets/Wireless.png b/public/assets/Wireless.png new file mode 100644 index 0000000..1a55539 Binary files /dev/null and b/public/assets/Wireless.png differ diff --git a/public/assets/about-image.png b/public/assets/about-image.png new file mode 100644 index 0000000..c6e5b0b Binary files /dev/null and b/public/assets/about-image.png differ diff --git a/public/assets/contact.png b/public/assets/contact.png new file mode 100644 index 0000000..a63d78b Binary files /dev/null and b/public/assets/contact.png differ diff --git a/public/assets/hero-tech.png b/public/assets/hero-tech.png new file mode 100644 index 0000000..65fd32e Binary files /dev/null and b/public/assets/hero-tech.png differ diff --git a/public/assets/icons/logo128.png b/public/assets/icons/logo128.png new file mode 100644 index 0000000..e832c43 Binary files /dev/null and b/public/assets/icons/logo128.png differ diff --git a/public/assets/icons/logo16.png b/public/assets/icons/logo16.png new file mode 100644 index 0000000..825d809 Binary files /dev/null and b/public/assets/icons/logo16.png differ diff --git a/public/assets/icons/logo180.png b/public/assets/icons/logo180.png new file mode 100644 index 0000000..89098e6 Binary files /dev/null and b/public/assets/icons/logo180.png differ diff --git a/public/assets/icons/logo192.png b/public/assets/icons/logo192.png new file mode 100644 index 0000000..98fe7bb Binary files /dev/null and b/public/assets/icons/logo192.png differ diff --git a/public/assets/icons/logo256.png b/public/assets/icons/logo256.png new file mode 100644 index 0000000..8f0513c Binary files /dev/null and b/public/assets/icons/logo256.png differ diff --git a/public/assets/icons/logo32.png b/public/assets/icons/logo32.png new file mode 100644 index 0000000..5e7362b Binary files /dev/null and b/public/assets/icons/logo32.png differ diff --git a/public/assets/icons/logo48.png b/public/assets/icons/logo48.png new file mode 100644 index 0000000..2789bf6 Binary files /dev/null and b/public/assets/icons/logo48.png differ diff --git a/public/assets/icons/logo512.png b/public/assets/icons/logo512.png new file mode 100644 index 0000000..9028c1c Binary files /dev/null and b/public/assets/icons/logo512.png differ diff --git a/public/assets/icons/logo64.png b/public/assets/icons/logo64.png new file mode 100644 index 0000000..cf35d2b Binary files /dev/null and b/public/assets/icons/logo64.png differ diff --git a/public/assets/icons/logo96.png b/public/assets/icons/logo96.png new file mode 100644 index 0000000..b2a7948 Binary files /dev/null and b/public/assets/icons/logo96.png differ diff --git a/public/assets/logo2.png b/public/assets/logo2.png new file mode 100644 index 0000000..61038a5 Binary files /dev/null and b/public/assets/logo2.png differ diff --git a/public/assets/old-logo.png b/public/assets/old-logo.png new file mode 100644 index 0000000..db8106d Binary files /dev/null and b/public/assets/old-logo.png differ diff --git a/public/assets/services-image.png b/public/assets/services-image.png new file mode 100644 index 0000000..6f137b0 Binary files /dev/null and b/public/assets/services-image.png differ diff --git a/public/assets/support.png b/public/assets/support.png new file mode 100644 index 0000000..341d83c Binary files /dev/null and b/public/assets/support.png differ diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..61e8dbf --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/review.md b/review.md new file mode 100644 index 0000000..5555cae --- /dev/null +++ b/review.md @@ -0,0 +1,373 @@ +# Queue North Website Redesign Strategy + +# Core Problem + +Current website branding feels: + +* too abstract +* too technical +* too personal +* too experimental + +The site currently resembles: + +* a developer portfolio +* infrastructure hobby project +* underground tech blog + +Instead of: + +* a mature B2B UCaaS provider +* managed IT partner +* enterprise communications company + +This creates trust friction immediately. + +Business buyers need confidence within seconds. + +--- + +# Business Positioning + +Queue North should position itself as: + +## Primary Identity + +Reliable business communications and IT infrastructure partner for SMB and enterprise clients. + +## Supporting Identity + +Modern, technically competent, responsive, security conscious. + +Not: + +* hacker aesthetic +* underground engineering lab +* mysterious tech collective + +--- + +# Recommended Brand Direction + +## Desired Feel + +The website should feel: + +* modern +* clean +* stable +* operationally mature +* enterprise capable +* technically sharp +* trustworthy + +Think: + +* RingCentral +* Zoom +* Cloudflare +* Cisco Meraki +* Dialpad +* 8x8 +* Microsoft business products + +But less corporate and less soulless. + +Human but competent. + +--- + +# Homepage Structure + +# 1. Hero Section + +## Goal + +Instant clarity. + +User should immediately understand: + +* what Queue North does +* who it serves +* why it matters + +## Recommended Headline + +Business communications and IT that actually work. + +Alternative: + +Modern UCaaS and managed IT for businesses that cannot afford downtime. + +## Supporting Text + +Queue North delivers cloud communications, networking, managed IT, and infrastructure support for SMBs and enterprise teams. + +## CTA Buttons + +* Schedule Consultation +* View Services + +Optional secondary: +* Contact Support + +--- + +# 2. Trust Signals Section + +This section should appear immediately after hero. + +## Include + +* uptime guarantees +* support response times +* certifications +* vendor partnerships +* years in business +* client industries +* deployment count +* SLA metrics + +## Example Metrics + +* 99.99% uptime +* 24/7 support +* multi site deployments +* secure cloud infrastructure +* enterprise grade failover + +This is critical. + +B2B buyers purchase risk reduction, not technology. + +--- + +# 3. Services Section + +## Recommended Layout + +Clean enterprise card grid. + +## Service Categories + +### UCaaS + +* hosted VoIP +* business phones +* call routing +* conferencing +* remote workforce support + +### Managed IT + +* endpoint management +* helpdesk +* patching +* infrastructure monitoring + +### Networking + +* SD WAN +* VPN +* firewall management +* switching +* wireless deployments + +### Security + +* MFA +* endpoint protection +* backups +* compliance +* monitoring + +Each card should explain business outcomes, not technical jargon. + +Bad: +"Kubernetes managed SIP orchestration" + +Good: +"Reliable business communications with centralized management and failover" + +Humans love inventing incomprehensible wording and then wondering why sales calls disappear. + +--- + +# 4. Industry Use Cases + +Very important for B2B trust. + +## Example Industries + +* healthcare +* logistics +* retail +* manufacturing +* legal +* finance +* distributed offices + +Each section should explain: + +* operational problems +* compliance needs +* uptime requirements +* remote work needs + +--- + +# 5. Why Queue North + +## Focus On + +* responsiveness +* reliability +* technical depth +* direct support +* proactive monitoring +* vendor neutrality + +## Avoid + +Generic corporate fluff like: + +* innovative solutions +* digital transformation +* next generation synergy nonsense + +Every B2B site writes this garbage and nobody believes any of it anymore. + +--- + +# 6. Testimonials / Case Studies + +Mandatory. + +Enterprise buyers need validation. + +## Include + +* measurable outcomes +* reduced downtime +* migration success +* support quality +* deployment scale + +Even 2 or 3 strong case studies massively improve credibility. + +--- + +# 7. Support & Operations + +This is where technical sophistication can appear. + +## Good Technical Signals + +* network operations center visuals +* uptime dashboards +* support workflows +* monitoring systems +* escalation paths + +## Bad Technical Signals + +* hacker visuals +* terminal cosplay +* random code snippets +* obscure infrastructure references + +Technical competence should feel controlled and operational. + +Not chaotic. + +--- + +# Visual Design Recommendations + +# Colors + +## Base + +* white +* dark slate +* muted blue +* graphite + +## Accent + +* blue +* teal +* restrained cyan + +Avoid: + +* neon green +* hacker black/red +* cyberpunk palettes + +Those aesthetics destroy enterprise trust surprisingly fast. + +--- + +# Typography + +## Recommended + +* Inter +* Geist +* IBM Plex Sans + +Professional sans serif. + +Monospace only for tiny UI accents if needed. + +--- + +# Layout Style + +## Use + +* large spacing +* strong hierarchy +* clean sections +* restrained motion +* clear CTAs + +## Avoid + +* excessive animations +* overloaded visuals +* scrolling gimmicks +* terminal-first design + +Enterprise sites should feel efficient. + +--- + +# Recommended Technical Stack + +## Best Option + +### Astro or Next.js + +With: + +* Tailwind +* Framer Motion lightly used +* CMS integration +* fast performance +* accessibility focus + +--- + +# Key Messaging Shift + +## Current Impression + +"Interesting technical person" + +## Required Impression + +"Reliable communications and IT partner for serious businesses" + +That distinction changes everything about the design language. \ No newline at end of file diff --git a/server/index.js b/server/index.js index 70348e8..920bfd8 100644 --- a/server/index.js +++ b/server/index.js @@ -59,7 +59,7 @@ const apiLimiter = rateLimit({ const cspDirectives = { defaultSrc: ["'self'"], scriptSrc: ["'self'"], - styleSrc: ["'self'", "'unsafe-inline'"], + styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:'], connectSrc: ["'self'"], @@ -424,9 +424,19 @@ app.use((req, res, next) => { next() }) -// Static file serving for SPA (falls through to SPA router) +// Static file serving for SPA app.use(express.static(path.join(__dirname, '../dist'))) +// SPA catch-all — serve index.html for any non-API, non-asset route +// This lets React Router handle client-side routing +app.get('*', (req, res, next) => { + // Skip API routes (already handled above) and requests for static assets + if (req.path.startsWith('/api/') || req.path.includes('.')) { + return next() + } + res.sendFile(path.join(__dirname, '../dist/index.html')) +}) + // --- Request timeout middleware (30 seconds) --- const REQUEST_TIMEOUT_MS = 30000 diff --git a/src/App.jsx b/src/App.jsx index 27d1100..edf5744 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,14 +1,12 @@ import { Outlet } from 'react-router-dom' import Header from './components/layout/Header.jsx' import Footer from './components/layout/Footer.jsx' -import MobileNav from './components/layout/MobileNav.jsx' import './index.css' function App() { return (
>( +const CardContent = React.forwardRef( ({ className = '', ...props }, ref) => (
) ) CardContent.displayName = 'CardContent' -const CardFooter = React.forwardRef