wavespestcontrolfl

waves-design

Use for ANY UI work on any portal surface — which style system a file uses, the V2 architecture and flags, palettes and tokens, the alert-fg rule, and which spec document governs the surface.

wavespestcontrolfl 0 1 Updated 1mo ago
GitHub

Install

npx skillscat add wavespestcontrolfl/waves-customer-portal/waves-design

Install via the SkillsCat registry.

SKILL.md

Waves portal design systems

Authoritative specs (this skill is the map, those are the law):

  • docs/design/waves-portal-ui-redesign-spec.md — full monochrome admin spec
  • docs/design/waves-customer-facing-design-brief.md — customer-surface warm
    tone (do NOT apply the admin spec to customer surfaces)
  • docs/design/DECISIONS.md — architectural decisions log + full PR history;
    append new entries at bottom, never edit old ones

The two style systems (never mix in one component)

Tier 1 V2 (now-default admin) — import { Button, Badge, Card, ... } from 'components/ui'. 13 primitives in client/src/components/ui/.
Tailwind tokens in client/tailwind.config.js: zinc ramp, alert red, type
scale 11–28, border-hairline, letterSpacing label/tight/display.
darkMode: false; fontWeight restricted to 400/500 — do not add weight
600/700. Reference page at /admin/_design-system (dev-gated; excluded
from robots.txt).

Legacy / V1 / Tier 2 — inline styles + the D dark palette:

const D = {
  bg: '#0f1923', card: '#1e293b', border: '#334155',
  teal: '#0ea5e9', green: '#10b981', amber: '#f59e0b',
  red: '#ef4444', purple: '#a855f7',
  text: '#e2e8f0', muted: '#94a3b8', white: '#fff'
};

Fonts: DM Sans (body), JetBrains Mono (numbers/code), Montserrat (tech
portal headings).

Match what the file you're editing already uses.

Admin V2 architecture (shipped, default for everyone)

The Tier 1 V2 redesign for Dashboard, Dispatch, Customers + Detail,
Estimates + /new, Communications, and the admin shell is the default. The
V1 page components, the per-flag gates (DashboardGate / DispatchGate /
CustomersGate / EstimatesGate / CommunicationsGate /
AdminLayoutGate), and the V1-only MobileAdminShell were deleted.
/admin/dashboard|customers|estimates|communications route directly to
*PageV2; /admin/dispatch is AdminDispatchPage (Board tab +
DispatchPageV2 under tabs); /admin/schedule redirects to
/admin/dispatch?tab=schedule. The admin shell is AdminLayoutV2.

Retained V1 modules (named-export only, no V1 page route):
SchedulePage.jsx, CustomersPage.jsx, EstimatePage.jsx,
CommunicationsPage.jsx are shared-utility modules — they export constants
and sub-components consumed by V2 (CompletionPanel / RescheduleModal /
EditServiceModal / ProtocolPanel / MONTH_NAMES / STAGES /
STAGE_MAP / KANBAN_STAGES / LEAD_SOURCES / CustomerMap /
CustomerIntelligenceTab / STATUS_CONFIG / PIPELINE_FILTERS /
DECLINE_REASONS / classifyEstimate / getUrgencyIndicator /
detectCompetitor / ALL_NUMBERS / NUMBER_LABEL_MAP). The
export default function ...Page() component is gone from each — do not
resurrect it, and do not delete these files as "dead code".

Rules for Tier 1 V2 work

  • Visual-refresh PRs are strict 1:1 on data, endpoints, metrics, and
    behavior. Content changes and visual changes never share a PR.
  • Use components/ui primitives + Tailwind zinc ramp + border-hairline
    chrome.
  • alert-fg (red) is reserved for genuine alerts only — never decoration.

**Exception — Customers V2 status indicators (/admin/customers Directory

  • Customer 360):** colored decoration is intentional on the customers
    surface for at-a-glance triage. Specifically allowed:
  • Health score (HealthDot, HealthCircle, "Score: NN/100" label): green
    #10B981 (≥70), amber #F59E0B (40–69), red #C8312F (<40).
  • Tier badge (Customer 360): metal-coded — Platinum #E5E7EB, Gold
    #D4A017, Silver #9CA3AF, Bronze #A16207.
  • Stage badge (Customer 360): green #10B981 for
    active_customer/won; red #C8312F for everything else.

Other admin surfaces follow strict zinc + alert-fg-for-alerts-only rules.

Feature flags

useFeatureFlag('<key>') from client/src/hooks/useFeatureFlag.js.
DB-backed via user_feature_flags, session-cached in memory, fails closed
(returns false if the API is unreachable). No localStorage persistence,
no percentage rollouts, no environment variants — the schema is
intentionally minimal. The retired V2 keys (dashboard-v2, dispatch-v2,
customers-v2, estimates-v2, comms-v2, mobile-shell-v2,
admin-shell-v2) are no longer read by the client; stale rows are inert.

Customer surfaces are GLASS

Customer-facing pages (portal PWA, newsletter email chrome + every landing
page reached from it, and ALL secondary customer pages, React or
server-rendered) use the glass token system — frosted cards, gold action
bars — via GLASS_THEME (email-template.js) / useGlassSurface
(glass-engine). Canonical ink navy is #04395E (never remap it), and the
font stack under html[data-glass-theme] is the clean system stack — no
Anton / Luckiest Guy / Baloo there. Full decisions:
docs/design/DECISIONS.md (2026-07-17 entries) + the customer design brief.

Hard lines (both systems)

  • 14px minimum for readable text (Virginia uses this 8 hours a day).
    POLICY on customer surfaces: 16px body / 14px label floors, and no raw
    emoji in JSX source (including comments — use icon components). The
    mechanical gate (npm run check:portal-brand, runs in Railway prebuild
    — one violation kills EVERY build) enforces only a SUBSET: selected
    customer directories (components/estimate excluded) and inline
    fontSize: 11/13 literals — so a passing gate is NOT proof of
    compliance; the policy applies repo-wide regardless of gate coverage.
  • Never apply customer-facing brand styling (Luckiest Guy / Baloo 2 / gold
    pill / mascot) inside /admin/* — admin stays monochrome.
  • iOS PWA safe areas: viewport-fit=cover is global in the standalone
    PWA, so ANY new top:0 fixed/sticky header or full-screen overlay (admin,
    customer, or tech) must pad with
    calc(<base> + env(safe-area-inset-top, 0px)) — fixed bottom bars use
    safe-area-inset-bottom — or it sits under the status bar. Panels use
    h-full, never h-screen/100vh. None of this reproduces in desktop
    Chrome emulation.
  • Company name in written copy is "Waves Pest Control" — never
    "Waves Lawn & Pest". The mascot LOGO artwork carrying the old name is
    CURRENT and intentional; never flag or swap the asset.
  • Before requesting review on any UI-touching PR, run the ui-verify
    skill
    (render, screenshot, compare against the spec).

Full per-PR detail (endpoints touched, subcomponents shipped, alert-fg
rules per page): docs/design/DECISIONS.md.

Categories