Commit Graph

110 Commits

Author SHA1 Message Date
Scarlett 9fdc6b6032 fix(a11y): visible focus indicator, aria-expanded, and six Label-in-Name failures
Batch 10, and only three of its six issues were real. The other three are
answered on the tracker with the arithmetic.

#189 — focus indicator. Footer and Home carried zero focus styling across 17
links. Added one global :focus-visible rule rather than sprinkling classes,
because the issue's own scope was "all interactive <a> and <Link> elements".

Not the ring the issue asked for. It suggested ring-primary-cyan; #22D3EE is
6.26:1 on navy and 2.38:1 on white, so on this light-first design that ring
would have failed WCAG 1.4.11 across most of the site. Two rings instead — white
inside, navy outside — so the white carries the dark bands and the navy carries
the light sections. Worst case across every background in the palette is
13.62:1. box-shadow so both rings follow each element's own border-radius, plus
a transparent outline for forced-colors mode.

#192 — aria-expanded={isOpen} and aria-controls on the mobile nav trigger, and
the id on SheetContent it now points at. Confirmed as "false" in the
prerendered HTML.

#193 — INVERTED. The issue asked for aria-labels to be added consistently to
hero CTAs. The aria-labels already there were WCAG 2.5.3 Label in Name failures,
Level A: "Schedule a consultation" is not a superset of the visible "Schedule
Consultation", so a voice-control user saying what they see cannot activate the
link. Doing what the issue asked would have spread a Level A failure. Removed
the six that broke it; kept the eight that genuinely add context and do contain
their visible text, including the icon-only header logo link that needs one.

Audit now reports 0 failures across Home, Services, Footer and Header.

Verified: npm run build; the ring is in the built CSS, aria-expanded="false" and
id="mobile-nav-content" are in the prerendered HTML, all six removed labels are
absent from it, and the visible CTA text still renders.

NOT verified: nothing has been walked keyboard-only in a browser, and no screen
reader has been used. That gap is recorded in docs/qa/ClaudeQACoverage.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 02:31:13 -05:00
null ac6f5d1f78 feat(seo): publish privacy policy, remove street address, prerender all routes (batch 0.9.3)
Client directive (Levi Halford, 2026-08-01) ahead of Google/Meta lead forms.

Privacy policy:
- Publish approved policy verbatim at /privacy-policy (src/data/privacyPolicy.js
  is the single source of truth; 292/292 source lines verified present)
- Privacy Policy link in the footer of every page
- Effective/Last Updated 2026-07-31, privacy@queuenorth.com as mailto

Remove St. Petersburg street address from every surface named in the brief:
footer, contact page, schema markup, SEO metadata, Google Maps links. Collapse
ProfessionalService + Organization schema into a single Organization with
areaServed: United States; drop geo coordinates, priceRange, openingHours.
Add the approved US-coverage sentence to About. No replacement address.

Crawler visibility (the site previously served 0 bytes of body HTML without JS):
- Prerender all 19 routes at build time via src/entry-server.jsx + scripts/prerender.js
- Hoist title/meta/canonical/JSON-LD into <head>; renderToString does not do this
  and react-helmet-async's context is empty under React 19
- Serve prerendered HTML; return a real 404 for unknown paths instead of 200
- Hydrate instead of discarding the prerendered markup

SEO/perf:
- Titles <=60 and descriptions <=160 chars across all pages
- Add BreadcrumbList to interior pages, WebSite to home
- Generate sitemap.xml from the route list with git-derived lastmod
- 301 duplicate URL forms (trailing slash, //, /index.html), preserving query
- Immutable caching for content-hashed assets; no-cache for HTML
- Split the 522 KB bundle into app/react-vendor/router/icons
- loading/decoding/fetchpriority + per-route hero preload; drop unused asset

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 01:45:52 -05:00
null 196389ddf3 fix(brand): update veteran-owned badge to certified mark logo (batch 0.9.2) 2026-06-14 16:17:42 -05:00
null d074e597b2 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
null 05b27d216a feat: Dockerfile/docker-compose updates, server improvements, contact form with recaptcha, API integration (batch 0.9.0) 2026-06-14 15:37:26 -05:00
null a8d9492a80 added 404 2026-05-28 00:41:24 -05:00
null 0f272fcf19 error and injection 2026-05-28 00:18:08 -05:00
null 3a61000c12 fix scroll 2026-05-27 23:40:09 -05:00
null e625a24b6e redirect to contact form 2026-05-27 22:33:54 -05:00
null f35de43952 fix footer 2026-05-27 22:19:04 -05:00
null c43d3bc955 company name footer one line 2026-05-27 22:08:46 -05:00
null ec14701795 center footer 2026-05-27 21:54:44 -05:00
null 78967ff56f phone 2026-05-27 21:49:21 -05:00
null cc1970fd1d added phone numebr hamburger 2026-05-27 21:44:06 -05:00
null 8c1e0f4c3d ui 2026-05-27 21:35:12 -05:00
null fb12d8cf3c 1 2026-05-27 21:23:17 -05:00
null a3ba03b7e1 cisco about 2026-05-27 21:15:54 -05:00
null f59d053afd mobile navbar text per owner 2026-05-27 21:04:30 -05:00
null 033bdf6625 Form now POSTs to Zoho 2026-05-27 20:57:55 -05:00
null 548e20e6f0 . 2026-05-27 14:43:50 -05:00
null 8f20670292 breadcrumbs 2026-05-27 14:27:30 -05:00
null 4410f01d48 Missing `Description` or `aria-describedby={undefined}` for {DialogContent}. 2026-05-27 14:11:48 -05:00
null 6bab4b5c89 corrections 2026-05-27 14:10:28 -05:00
null f9b36c198b badges size 2026-05-27 13:58:31 -05:00
null 4b17e9f109 badges 2026-05-27 13:28:13 -05:00
null 6de9490764 badge center 2026-05-27 12:51:08 -05:00
null a81e97fb31 mobile view 2026-05-27 12:42:25 -05:00
null 362a7e0059 heatmap 2026-05-26 17:08:55 -05:00
null 510edace07 removed duplicate card 2026-05-26 13:41:46 -05:00
null 8731903463 updated badges homepage 2026-05-26 13:36:16 -05:00
null a2a32687ff branding 2026-05-26 13:29:37 -05:00
null f0f0cfd599 #181 2026-05-26 13:04:57 -05:00
null 335601b00e remove submit ticket 2026-05-26 12:55:23 -05:00
null 85d7ae4bb1 logo enlarge 2026-05-26 12:44:10 -05:00
null bfcf7f114c #176 2026-05-26 12:31:26 -05:00
null f2a5e2c1bc Hero name widen 2026-05-26 12:26:13 -05:00
null d626c34ba2 parternership branding 2026-05-26 12:22:11 -05:00
null fd1e2b6f50 update 2026-05-25 20:26:50 -05:00
null afec6547c1 RECAPTCHA 2026-05-25 20:20:15 -05:00
null 7f48847049 CTA 2026-05-25 20:08:04 -05:00
null 07a43b9b7c visual update services 2026-05-25 20:03:56 -05:00
null 9b5f9f885c text 2026-05-25 20:02:36 -05:00
null fca9336656 close 184 2026-05-25 19:54:39 -05:00
null e489245104 service military 2026-05-25 19:51:03 -05:00
null 80b1747ffe branding 2026-05-25 19:44:10 -05:00
null bc6bc9a787 logo 2026-05-25 19:40:18 -05:00
null 1d687c5fa1 branch footer 2026-05-25 19:23:37 -05:00
null 52d9a16462 branch footer 2026-05-25 18:35:40 -05:00
null c17ac83b52 services 2026-05-25 18:33:19 -05:00
null 09926fed6d Contact.jsx (line 23): added ZIP to validation/error state, rendered it as required, and shows ZIP code is required.
server/index.js (line 253): backend Zod schema now rejects missing or blank ZIP.
api.js (line 3): preserves backend field errors for display.
2026-05-25 18:17:16 -05:00