Axil_Accountants/implementation_plan.md
Vadym Samoilenko 83a8878f4a feat: redesign HeroSection to 3-column MinimalistHero layout
- HeroSection: 3-col layout (copy | concentric circles+dashboard | display headline)
  - 'use client' + framer-motion entrance animations (slide in from sides, scale centre)
  - DashboardPreview inline component (compact portal mockup)
  - Two floating stat mini-cards (Avg Tax Saved, Response Time)
  - Mobile: stacked layout, right headline column hidden, H1 in left column
- ContainerScroll: simplified — removed 72rem scroll container and scroll transforms;
  now plain layout wrapper with CSS fadeInUp entrance
- Header: logo size increased h-10 → h-13 (40px → 52px)
- fix: escape apostrophes in ProcessSection, SolutionSection, TestimonialsSection
- fix: remove unused customSize param from SpotlightCard
- docs: update CONTEXT_HANDOVER.md with session 4 changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 21:20:42 +00:00

40 KiB
Raw Permalink Blame History

Axil Accountants — Implementation Plan

Based on: Concept.md v1.0 Stack: Next.js 15 · TypeScript · Tailwind CSS v4 · Payload CMS 3 · PostgreSQL (Neon) · Vercel Each feature is isolated and can be developed, tested, and reviewed independently.


Legend

  • [ ] — Not started
  • [x] — Complete
  • [~] — In progress
  • [!] — Blocked / needs decision

Feature 1 — Project Setup & Repository

  • Scaffold Next.js 16.1.6 project with App Router and TypeScript (create-next-app)
  • Configure TypeScript (tsconfig.json): strict mode, path aliases (@/*)
  • Install and configure Tailwind CSS v4
  • Install and configure ESLint 9 (Next.js preset)
  • Install and configure Prettier with Tailwind class sorting plugin
  • Set up Husky 9 + lint-staged 16 (pre-commit: lint + format)
  • Define .env.local structure and .env.example template
  • Create src/ directory structure (app, components/ui/layout/sections/three/cms, lib, hooks, types, payload)
  • Initialise Git repository, create main and develop branches
  • Docker: multi-stage Dockerfile (dev/build/production) + docker-compose.yml (app + PostgreSQL 17)
  • Create Vercel projectN/A: self-hosted on Ubuntu
  • Configure Vercel environment variablesN/A: .env.local on server

Feature 2 — Database & Infrastructure

  • Docker PostgreSQL 17 — сервис db в docker-compose.yml (user: axil, db: axil)
  • DATABASE_URI прописан в .env.localpostgresql://axil:axil_dev@db:5432/axil
  • Verify database connectivity — healthcheck в docker-compose (pg_isready)
  • Media storage — Payload local disk storage (/public/media) — без внешних сервисов
  • Email (Resend) — настроить позже (Feature 19, когда нужны реальные письма)

Feature 3 — Payload CMS — Core Installation

  • Install Payload CMS 3 into the Next.js project
  • Configure payload.config.ts (serverURL, secret, db, editor, admin)
  • Mount Payload API handler at src/app/(payload)/api/[...slug]/route.ts
  • Mount admin panel at src/app/(payload)/admin/[[...segments]]/page.tsx
  • Add layout.tsx with RootLayout from @payloadcms/next/layouts (provides ConfigProvider)
  • Configure local disk storage for Payload media (/public/media)
  • Email adapter — deferred (Feature 19, Resend)
  • Verify admin panel loads at /adminconfirmed
  • Install Payload Form Builder plugin (@payloadcms/plugin-form-builder) — installed, re-enabled in Feature 4
  • Downgrade Next.js 16.1.6 → 15.4.11 (peer dep compatibility with Payload 3.77)
  • Upgrade Docker Node.js 20 → 22 (undici/tsx compatibility)

Feature 4 — CMS Collections Schema

Define all Payload collections and globals. Each collection = one content type the client manages.

4.1 — Media Collection

  • Media collection с локальным хранилищем (/public/media)
    • Fields: alt (text, required), caption (text, optional)
    • Image sizes: thumbnail (400×300), card (800×600), hero (1920×1080)

4.2 — Users Collection

  • Users collection (extends Payload default)
    • Fields: name, email, role (select: admin | editor)
    • Role-based access control: editors can manage content, not settings

4.3 — Services Collection

  • Services collection
    • title (text, required)
    • slug (slug, auto from title, unique)
    • icon (select: bookkeeping | tax | payroll | vat)
    • tagline (text — short subtitle)
    • description (rich text — full description)
    • whatsIncluded (array of bullet strings)
    • whoItsFor (array: { audience: select, description: text })
    • howItWorks (array of 3: { step: number, title: text, description: text })
    • faq (array: { question: text, answer: rich text })
    • relatedTestimonials (relationship → Testimonials, many)
    • seo group: { metaTitle, metaDescription, ogImage → Media }
    • publishedAt (date), status (select: draft | published)

4.4 — Blog Posts Collection

  • Posts collection
    • title (text, required)
    • slug (slug, unique)
    • author (relationship → Users)
    • category (relationship → Categories)
    • coverImage (upload → Media)
    • excerpt (textarea, 150 chars max)
    • content (rich text — Lexical with full feature set)
    • readingTime (number, auto-calculated on save via hook)
    • publishedAt (date)
    • status (select: draft | published | scheduled)
    • tags (array of text)
    • seo group: { metaTitle, metaDescription, ogImage → Media }

4.5 — Categories Collection

  • Categories collection
    • name (text, required)
    • slug (slug)
    • colour (text — hex, for tag colour)

4.6 — Team Members Collection

  • TeamMembers collection
    • name (text, required)
    • role (text)
    • qualifications (text — e.g. "ACCA, MAAT")
    • bio (textarea)
    • photo (upload → Media)
    • linkedIn (text — URL)
    • order (number — display order)

4.7 — Testimonials Collection

  • Testimonials collection
    • clientName (text, required)
    • businessName (text)
    • businessType (select: sole-trader | limited-company | startup | other)
    • rating (select: 15)
    • quote (textarea, required)
    • photo (upload → Media, optional)
    • source (select: google | manual)
    • service (relationship → Services, optional — for filtering)
    • featured (checkbox — show in homepage carousel)
    • publishedAt (date)

4.8 — FAQs Collection

  • FAQs collection (global FAQ bank)
    • question (text, required)
    • answer (rich text)
    • service (relationship → Services, optional)
    • global (checkbox — show on generic FAQ sections)
    • order (number)

4.9 — Form Builder (Payload Plugin Collections)

  • Enable @payloadcms/plugin-form-builder — provides:
    • Forms collection (drag-and-drop field builder in admin)
    • FormSubmissions collection (stores all submissions)
  • Configure supported field types: text, email, phone, select, checkbox, textarea
  • Configure submission handlers:
    • Email notification (to: configurable per form)
    • Webhook trigger (URL: from webhook registry in Site Settings)
    • Redirect URL or confirmation message (per form)

4.10 — Navigation Global

  • Navigation global
    • items (array):
      • label (text)
      • href (text, optional — for simple links)
      • isDropdown (checkbox)
      • children (array, conditional): { label, href, icon, description }
  • Footer global
    • columns (array of 4):
      • heading (text)
      • links (array: { label, href })
    • contactInfo group: { address, phone, email }
    • socialLinks group: { linkedIn, facebook, instagram }
    • legalLinks (array: { label, href })
    • copyrightText (text)

4.12 — Site Settings Global

  • SiteSettings global
    • Brand: siteName, tagline, logo → Media, logoDark → Media, favicon → Media
    • Contact: address, phone, email, officeHours
    • Social: linkedIn, facebook, instagram
    • Analytics: googleAnalyticsId, googleTagManagerId, facebookPixelId
    • Booking: calendlyUrl, calendlyInline (checkbox)
    • Chat Bot: chatBotMode (select: disabled | ai | livechat | leadcapture), chatBotCustomCode (code field — for Tawk.to etc.)
    • Webhooks Registry: webhooks (array: { name, url, active })
    • Email: notificationEmail (default recipient for form submissions)
    • SEO Defaults: defaultMetaTitle, defaultMetaDescription, defaultOgImage → Media
    • Scripts: headerScripts (code), footerScripts (code) — for third-party embeds

Feature 5 — Design System & Base UI Components

  • Configure Tailwind CSS with custom design tokens:
    // globals.css (@theme inline)
    colors: {
      emerald: {
        DEFAULT: '#3CC68A',  // primary — CTA кнопки, иконки, border
        dark:    '#27A870',  // hover / active
        deeper:  '#1A8C5B',  // тёмные секции
        light:   '#7DDCB0',  // tints
        mist:    '#E8F8F1',  // светлые фоны секций
      },
      blue: {
        DEFAULT: '#1B9AD6',  // secondary — заголовки, trust, links
        dark:    '#1480B8',  // hover
        light:   '#6CC4E8',  // tints
        mist:    '#E8F5FC',  // светлые фоны
      },
      charcoal: '#162520',   // основной текст
      muted:    '#6B7280',   // второстепенный текст
      bg:       '#F5FEFA',   // фоновый off-white
    }
    borderRadius: { card: '16px', hero: '24px', pill: '999px' }
    fontFamily: {
      sans:    ['Inter', 'sans-serif'],
      display: ['Satoshi', 'sans-serif'],
      mono:    ['DM Mono', 'monospace'],
    }
    
  • Set up fonts:
    • Satoshi (variable font) — Fontshare CDN (<link> in layout.tsx, CSS var reference in @theme)
    • Internext/font/google--font-inter--font-sans
    • DM Mononext/font/google--font-dm-mono--font-mono
  • Create CSS variables in globals.css for all design tokens (enables runtime theming)
  • Button component (src/components/ui/Button.tsx):
    • Variants: primary (green fill), secondary (outline), ghost (text only)
    • Sizes: sm, md, lg
    • States: hover (scale + colour shift), focus (ring), loading (spinner), disabled
    • Optional: trailing arrow icon, leading icon
  • Icon system (src/components/ui/icons/):
    • Custom SVG line icons for each service (Bookkeeping, Tax, Payroll, VAT)
    • Shared icons: ArrowRight, CheckCircle, Star, Menu, X, ChevronDown
    • All exported as React components with size and color props
  • Heading component — h1h4 with correct size + weight from design system
  • Tag/Badge component — pill with colour variant (green, grey, blue)
  • StarRating component — 15 filled star SVGs
  • GlassCard component — frosted glass base with emerald border, hover glow (light + dark variants)
  • Section layout wrapper — max-w-[1440px], horizontal padding
  • Divider component — subtle emerald gradient horizontal rule
  • Spinner component — loading state for forms and async content

Feature 6 — Animation Infrastructure

  • Install dependencies: gsap, @gsap/react, lenis, framer-motion, @react-three/fiber, three
  • Lenis smooth scroll provider (src/lib/lenis.tsx):
    • LenisProvider wraps the app in root layout
    • Integrates with GSAP ticker for synchronized animations
    • Disabled on mobile if causing performance issues
  • GSAP context provider (src/lib/gsap.ts):
    • Registers ScrollTrigger plugin
    • Exports gsap instance with plugins pre-registered
    • Custom hook useGSAP for component-level animation cleanup
  • useAnimateOnScroll hook (src/hooks/useAnimateOnScroll.ts):
    • Accepts ref, animation type (fadeUp, fadeIn, slideLeft, etc.), delay, stagger
    • Returns trigger state
    • Uses ScrollTrigger under the hood
  • useCountUp hook (src/hooks/useCountUp.ts):
    • Accepts target (number), duration, prefix (£, +), suffix (%, +)
    • Triggers animation when element enters viewport
    • Returns current display value (string)
  • AnimatedText component (src/components/ui/AnimatedText.tsx):
    • Splits text into words or lines
    • Each word/line slides up on a stagger delay
    • GSAP-driven, respects prefers-reduced-motion
  • FadeInSection component (src/components/ui/FadeInSection.tsx):
    • Wraps any content
    • Fades + translates up when enters viewport
    • Accepts delay and duration props
  • Framer Motion page transition (src/components/layout/PageTransition.tsx):
    • Wraps each page with AnimatePresence
    • Default: fade + subtle Y translate
    • Used in root layout
  • prefers-reduced-motion utility — all animation components check and skip if enabled

Feature 7 — Header & Navigation

  • Header component (src/components/layout/Header.tsx):
    • Fixed/sticky at top, z-50
    • On scroll: applies backdrop-blur + white/85% opacity background (Framer Motion)
    • Transparent when at top of page
    • Max-width container, flex layout: logo | nav | CTA
  • Logo component — renders logo image from CMS Site Settings, supports light/dark variant
  • Desktop navigation (src/components/layout/DesktopNav.tsx):
    • Renders items from CMS Navigation global
    • Simple links: hover underline slide-in animation
    • Dropdown trigger: Services ▾ — renders ServicesDropdown
  • ServicesDropdown component:
    • Opens on hover/focus, closes on blur/outside click
    • Grid of service cards: icon + name + short description
    • Framer Motion: animate-in (scale + fade from top)
  • Header CTA button — "Book a Free Consultation" → opens booking modal
  • MobileMenu component (src/components/layout/MobileMenu.tsx):
    • Hamburger icon button (animated → X on open)
    • Full-screen overlay, fixed inset-0, dark green tint background
    • Framer Motion: slide-in from right or fade-in
    • Staggered nav item reveal
    • Large CTA button at bottom
    • Closes on link click or backdrop click
  • Fetch navigation data from Payload at build/request time (cached)

  • Footer component (src/components/layout/Footer.tsx):
    • 4-column grid (collapses to 2×2 on tablet, 1 column on mobile)
    • Column 1: Logo, tagline, social icon links
    • Column 2: Services links
    • Column 3: Company links (About, Blog, Contact)
    • Column 4: Contact info (address, phone, email) + ICAEW/ACCA badges
  • Social icon links (LinkedIn, Facebook, Instagram) — SVG icons, hover colour transition
  • ICAEW / ACCA badge images (stored in media, linked from Site Settings)
  • Bottom bar: copyright text | Privacy Policy | Cookie Policy
  • Data fetched from CMS Footer global + Site Settings global

Feature 9 — 3D Hero Scene (Three.js / R3F)

  • Install: @react-three/fiber, @react-three/drei, three
  • GlobeScene component (src/components/three/GlobeScene.tsx):
    • Canvas with @react-three/fiber
    • Camera position, fog, ambient + directional lighting (soft green tint)
  • Globe mesh:
    • SphereGeometry with high segment count
    • Custom PointsMaterial shader: dot-matrix surface pattern
    • Colour: sage green #6BAF7D on near-white background
    • Slow auto-rotation around Y axis (useFrame)
  • ParticleNetwork:
    • 150300 floating particle nodes (reduced on mobile: 6080)
    • Lines connecting nearby particles (LineSegments)
    • Nodes float with subtle Perlin noise movement
    • Colour: soft mint with 40% opacity
  • Mouse parallax interaction:
    • Track mousemove on hero section
    • Globe and particle network shift slightly (opposite to mouse direction)
    • useSpring (React Spring or Framer Motion) for smooth interpolation
  • Device-adaptive performance:
    • Detect mobile / low-power device
    • Reduce particle count, disable post-processing effects
    • React.Suspense boundary with skeleton loader during WebGL init
  • Mobile fallback (src/components/three/GlobeFallback.tsx):
    • 2D SVG animated globe (CSS animation, no WebGL)
    • Shown when WebGL unavailable or prefers-reduced-motion is set
  • useWebGLSupport hook — detects WebGL availability, returns boolean

Feature 10 — Home Page: Hero Section

  • HeroSection component (src/components/sections/home/HeroSection.tsx)
  • Full-viewport height (min-h-screen), flex / grid split layout
  • Left column:
    • Eyebrow tag (e.g. "Trusted by 500+ UK Businesses") — Badge component, fade-in
    • AnimatedText H1: "Smart Accounting for Growing British Businesses" — word stagger
    • Subheadline paragraph — fade-in with delay
    • Button group: Primary CTA + Secondary CTA (with arrow icon)
    • Trust strip: star rating + "4.9 Google Rating" · "ICAEW Certified" · "500+ Clients Served"
  • Right column: GlobeScene (or GlobeFallback on mobile/no WebGL)
  • Mobile layout: stacked, 3D scene below text, reduced height
  • Content driven from CMS Pages collection (hero fields)

Feature 11 — Home Page: Pain Points Section

  • PainPointsSection component
  • Dark green background (#1A2E1F), full-width
  • Headline + subtext — AnimatedText reveal
  • 3 GlassCard components (frosted glass on dark background):
    • Card 1: "Missed deadlines & HMRC penalties"
    • Card 2: "Confused by tax rules that keep changing"
    • Card 3: "Hours wasted on bookkeeping instead of growing"
  • ScrollTrigger staggered reveal: cards slide up 100ms apart
  • Subtle parallax: background shifts 20px on scroll

Feature 12 — Home Page: Services Overview Section

  • ServicesSection component
  • Section header: headline + subheadline
  • 2×2 GlassCard grid (CSS Grid, responsive)
  • Each card:
    • Custom SVG icon (from icon system)
    • Service name (heading)
    • Short description (from CMS)
    • "Learn More →" link to /services/[slug]
    • Hover: translateY(-4px) + sage green border glow (box-shadow)
  • ScrollTrigger staggered card reveal
  • CTA block below grid: "Not sure which service you need? → Let's Talk"
  • Data: fetch all Services from Payload

Feature 13 — Home Page: Why Choose Axil Section

  • WhyAxilSection component
  • Section headline: "Why Businesses Choose Axil"
  • Stat counter row (4 stats):
    • 500+ Businesses Served
    • 98% Client Retention Rate
    • £2M+ Tax Saved for Our Clients
    • 12+ Years of Experience
    • Each uses useCountUp hook, triggers on ScrollTrigger enter
    • Numbers in DM Mono font
  • 4 USP blocks (icon + heading + description):
    • ICAEW & ACCA Qualified
    • Fixed Monthly Engagement
    • Dedicated Account Manager
    • Cloud-Based & Paper-Free
  • FadeInSection wrapper per block, staggered

Feature 14 — Home Page: Testimonials Section

  • TestimonialsSection component
  • Auto-scrolling marquee carousel (infinite horizontal scroll, CSS animation)
    • Pause on hover
    • Two rows scrolling in opposite directions (optional premium touch)
  • TestimonialCard component:
    • Client name + business type
    • StarRating (15)
    • Quote text (truncated at 3 lines, expand on click)
    • Optional client avatar (from Media, fallback to initials)
  • Google Reviews badge (static badge image or API widget)
  • ICAEW / ACCA certification badge display
  • CTA below: "Join hundreds of satisfied UK businesses → Book Your Free Consultation"
  • Data: fetch featured testimonials from Payload (where featured = true)

Feature 15 — Home Page: Who We Work With Section

  • AudienceSection component
  • 3 audience cards:
    • Sole Traders — illustrated icon, description, "Learn More →"
    • Limited Companies — illustrated icon, description, "Learn More →"
    • Startups — illustrated icon, description, "Learn More →"
  • Illustrated icons: custom SVG per audience type
  • Cards: GlassCard, hover lift effect
  • FadeIn reveal on scroll

Feature 16 — Home Page: How It Works Section

  • HowItWorksSection component
  • 3-step horizontal layout (flex row on desktop, vertical stack on mobile)
  • Each step: numbered circle + title + description
  • Animated connecting line:
    • SVG path between steps
    • GSAP DrawSVGPlugin or stroke dashoffset animation
    • Draws left-to-right as section scrolls into view
  • Step data driven from CMS (global or hardcoded — TBD with client)

Feature 17 — Home Page: Blog Preview Section

  • BlogPreviewSection component
  • Section headline + "Visit Our Blog →" link
  • Fetch 3 most recent published posts from Payload
  • BlogCard component (reused on blog index):
    • Cover image (next/image, lazy-loaded)
    • Category tag badge
    • Title (heading)
    • Excerpt (truncated)
    • Author name + date + read time
    • Hover: image subtle zoom, card lift
  • Grid: 3 columns desktop, 1 column mobile

Feature 18 — Home Page: Final CTA Section

  • FinalCTASection component
  • Full-width, deep forest green background (#1A2E1F or #2E7D52)
  • Centred content:
    • Large headline: "Ready to take the stress out of your finances?"
    • Subheadline
    • Large primary CTA button (white on green): "Book a Free Consultation"
    • Trust reassurance: "★ 4.9/5 on Google · ICAEW Certified · No lock-in contracts"
  • Optional: subtle animated background (particle drift or gradient shift)

Feature 19 — Consultation Booking Modal & Form

This is the primary conversion mechanism. Opens from every CTA across the site.

  • BookingModal component (src/components/BookingModal.tsx):
    • Global state: useBookingModal() Zustand store or React Context
    • Triggered by openBookingModal() from any component
    • AnimatePresence + Framer Motion: fade-in backdrop, slide-up modal
    • Close on backdrop click, Escape key, close button
    • Accessible: focus trap, role="dialog", aria-modal
  • Two modes (configurable in CMS Site Settings):
    • Mode A — Calendly: renders <iframe> from calendlyUrl setting
    • Mode B — Custom Form: renders the consultation form
  • Consultation form fields:
    • Full name (text, required)
    • Email address (email, required)
    • Phone number (text, optional)
    • Business type (select: sole trader / limited company / startup / other)
    • What do you need help with? (select: bookkeeping / tax / payroll / VAT / not sure)
    • Message (textarea, optional)
  • Form validation: client-side (React Hook Form + Zod schema)
  • Submit handler (API route POST /api/contact):
    • Save to Payload FormSubmissions collection
    • Send notification email via Resend to admin email (from Site Settings)
    • Trigger webhook if configured (from webhooks registry)
    • Return success/error response
  • Success state: animated checkmark + "We'll be in touch within 1 business day" message
  • Error state: clear error messages per field + general error fallback

Feature 20 — Services Pages

20.1 — Services Overview Page (/services)

  • Grid of all 4 service cards (large format)
  • Each card links to individual service page
  • Intro section: headline + subheadline
  • CTA at bottom

20.2 — Individual Service Pages (/services/[slug])

  • Dynamic route with generateStaticParams (ISR)
  • Fetch service data by slug from Payload at build/revalidate time
  • Hero section: service name, bold tagline, illustration/icon, CTA button
  • What's Included section: bullet list of deliverables (from CMS whatsIncluded)
  • Who It's For section: audience cards filtered to relevant segments
  • How It Works section: 3-step process (service-specific, from CMS)
  • FAQ section: accordion component
    • Fetch FAQs related to this service from Payload
    • Animated expand/collapse (Framer Motion AnimatePresence + height animation)
    • JSON-LD FAQPage schema injected via generateMetadata
  • Testimonials section: filtered by service (from Payload relationship)
  • Final CTA section
  • generateMetadata: SEO title, description, OG image from CMS seo group

Feature 21 — About Page (/about)

  • Fetch team members, site settings from Payload
  • Hero section: large headline + team group photo (from Media)
  • Our Story section: rich text from CMS (Lexical renderer)
  • Team grid section:
    • TeamMemberCard component: photo, name, role, qualifications, LinkedIn link
    • Responsive grid: 3 col desktop, 2 col tablet, 1 col mobile
    • Hover: subtle overlay with LinkedIn button
    • Data from Payload TeamMembers collection (ordered by order field)
  • Core Values section: 4 value blocks (icon + title + description)
  • Certifications section: ICAEW + ACCA logo badges with descriptions
  • Final CTA section

Feature 22 — Blog System

22.1 — Blog Index Page (/blog)

  • Fetch all published posts (ISR, revalidate: 3600s)
  • Search input: client-side filter by title/excerpt
  • Category filter tabs: "All" + each category — filters post grid
  • Blog post card grid (3 columns desktop, 1 mobile) — BlogCard component
  • Pagination (10 posts per page, Payload limit/page query)
  • SEO metadata for blog index

22.2 — Individual Blog Post Page (/blog/[slug])

  • generateStaticParams + ISR (revalidate: 3600s)
  • Fetch post by slug from Payload
  • Lexical rich text renderer (src/lib/lexical-renderer.tsx):
    • Renders all Lexical nodes: headings, paragraphs, lists, blockquotes, images, code blocks
    • Custom component for pull quotes (green left border, large text)
    • Syntax highlighting for code blocks (shiki or prism)
  • Article layout: hero image (full-width), title, author + date + read time + category tag
  • Table of Contents (auto-generated from H2/H3 headings):
    • Sticky sidebar on desktop
    • Active heading highlight on scroll (Intersection Observer)
  • Social share buttons: copy link, Twitter/X, LinkedIn
  • Related posts section: 23 posts from same category
  • generateMetadata: full SEO + Open Graph from CMS seo group

Feature 23 — Contact Page (/contact)

  • Hero: "Get in Touch" + brief description
  • Contact form (renders a Payload Form via form builder):
    • Fields: name, email, phone, subject, message
    • Submission saves to Payload FormSubmissions + email notification
  • Contact info panel: address, phone, email, office hours
  • Google Maps embed (iframe, optional — lazy-loaded)
  • Office hours block

  • Static page routes
  • Content editable via CMS Pages collection (rich text fields)
  • Standard typography layout: table of contents sidebar + main content
  • Last updated date (from CMS)

Feature 25 — Chat Bot Module

  • ChatWidget component (src/components/chat/ChatWidget.tsx):
    • Floating button (bottom-right), "Chat with us" label
    • Slide-up panel animation (Framer Motion)
    • Reads chatBotMode from Site Settings global
  • Mode: disabled — component renders nothing
  • Mode: livechat (Tawk.to or custom):
    • Reads chatBotCustomCode from Site Settings
    • Injects script via useEffect (no SSR)
    • Custom button hidden; Tawk.to button shown instead
  • Mode: ai — AI Chat:
    • Pre-chat form: collect visitor name + email
    • Chat messages UI: user + bot bubbles, loading dots
    • API route POST /api/chat:
      • Sends message to OpenAI/Claude with system prompt
      • System prompt: company info, services, FAQs — fetched from Payload
      • Streams response back (SSE or JSON)
    • Escalation: if bot confidence low → "Let me connect you with our team" → email notification
    • Conversation log saved to Payload (custom ChatLogs collection or email)
  • Mode: leadcapture — Scripted Bot:
    • Step 1: "Hi! What's your name?"
    • Step 2: "Great, {name}! What's your email address?"
    • Step 3: "Are you a sole trader, limited company, or startup?"
    • Step 4: "What's your main concern? (tax / bookkeeping / payroll / other)"
    • Step 5: "Thanks! Our team will be in touch shortly."
    • On completion: POST lead to /api/contact → email + webhook

Feature 26 — SEO & Metadata System

  • generateMetadata function utility (src/lib/metadata.ts):
    • Accepts CMS seo object + fallback to Site Settings defaults
    • Returns Next.js Metadata object
    • Handles: title, description, OG image, canonical URL
  • Open Graph image generation (src/app/og/route.tsx):
    • Dynamic OG images for blog posts using @vercel/og
    • Template: Axil logo + post title + sage green background
  • Structured data helpers (src/lib/structured-data.ts):
    • LocalBusiness schema (name, address, phone, opening hours)
    • AccountingService schema
    • FAQPage schema (for service pages)
    • BlogPosting schema (for blog articles)
    • Injected via <script type="application/ld+json"> in page <head>
  • sitemap.ts (src/app/sitemap.ts):
    • Fetches all published blog posts + service slugs from Payload
    • Returns MetadataRoute.Sitemap array
    • Revalidates on ISR
  • robots.ts (src/app/robots.ts):
    • Allow all crawlers
    • Point to sitemap
    • Block /admin/*
  • Verify all pages have correct <title> tags in browser devtools

  • AnalyticsProvider component (src/components/AnalyticsProvider.tsx):
    • Reads GA ID, GTM ID, FB Pixel ID from CMS Site Settings
    • Conditionally loads scripts only after cookie consent granted
  • Google Tag Manager integration:
    • <Script> in <head> and <noscript> in <body>
    • Only loads after consent
  • Cookie consent banner (src/components/CookieBanner.tsx):
    • GDPR / UK GDPR compliant
    • Framer Motion: slides up from bottom on first visit
    • Buttons: "Accept All" | "Reject Non-Essential" | "Manage Preferences"
    • Stores consent in localStorage
    • Triggers analytics scripts on accept
  • useConsent hook — reads/writes consent state, exposes hasConsent(category)
  • Custom code injection from CMS Site Settings:
    • headerScripts — injected in <head> via Next.js root layout
    • footerScripts — injected before </body>

Feature 28 — Form Builder Frontend Renderer

Allows any Payload-built form to be rendered on the frontend.

  • FormRenderer component (src/components/cms/FormRenderer.tsx):
    • Accepts formId prop (Payload form document ID or slug)
    • Fetches form schema from Payload API
    • Dynamically renders all field types:
      • text, email, phone, textarea<input> / <textarea>
      • select<select> or custom dropdown
      • checkbox → styled checkbox
    • React Hook Form + Zod validation from field config (required, type)
  • FormField component — renders individual field with label, input, error message
  • Submit handler: POST /api/form-submissions
    • Saves to Payload FormSubmissions
    • Triggers email + webhook from form config
  • Success / error UI states
  • Usage: embed <FormRenderer formId="..." /> anywhere on any CMS-managed page

Feature 29 — Performance Optimisation

  • All images use next/image with correct sizes prop and priority for LCP images
  • next/font for Inter + DM Mono (eliminates layout shift from font load)
  • Dynamic imports for heavy components:
    • GlobeScenedynamic(() => import(...), { ssr: false })
    • ChatWidgetdynamic(() => import(...), { ssr: false })
    • Lexical renderer — dynamic import
  • ISR (Incremental Static Regeneration):
    • Service pages: revalidate = 86400 (24h)
    • Blog posts: revalidate = 3600 (1h)
    • Homepage: revalidate = 3600
  • Install @next/bundle-analyzer, run bundle analysis, eliminate large dependencies
  • Lazy-load all sections below fold (Intersection Observer or Next.js loading="lazy")
  • Verify no unused CSS (Tailwind PurgeCSS is automatic)
  • Run Lighthouse on all key pages — target: Performance 95+, SEO 100, Accessibility 95+
  • Fix any Lighthouse findings before delivery

Feature 30 — Accessibility Audit & Fixes

  • Add <a href="#main-content">Skip to content</a> as first focusable element
  • Verify all interactive elements are keyboard-navigable (Tab, Enter, Escape)
  • All images have meaningful alt text (enforced by Payload Media collection)
  • All form fields have associated <label> elements
  • All icon-only buttons have aria-label
  • Modals: focus trap, role="dialog", aria-modal, return focus on close
  • Navigation dropdowns: aria-expanded, aria-haspopup
  • Colour contrast: check all text/background combos meet WCAG AA (4.5:1 body, 3:1 large text)
  • Test with screen reader (VoiceOver / NVDA)
  • Verify prefers-reduced-motion disables all non-essential animations

Feature 31 — Responsive Design QA

  • Test every page at: 320px, 375px, 414px, 768px, 1024px, 1280px, 1440px, 1920px
  • Verify 3D scene: WebGL on desktop, SVG fallback on mobile
  • Verify hamburger menu: opens, nav links work, closes correctly
  • Verify booking modal: fills screen on mobile, scrollable content
  • Verify all form fields usable with touch keyboard (no content hidden behind keyboard)
  • Verify testimonials marquee / carousel: touch-swipeable on mobile
  • Verify blog grid: 1-column on mobile, readable font sizes
  • Verify footer: stacks correctly on mobile

Feature 32 — Error Handling & Monitoring

  • Sentry setup (@sentry/nextjs):
    • Install and configure with SENTRY_DSN
    • Client + server + edge error capture
    • Source maps upload on build
  • Custom 404 page (src/app/not-found.tsx):
    • Brand-styled, helpful message
    • Links back to home + contact
  • Custom 500 page (src/app/error.tsx):
    • Brand-styled error page
    • Reports error to Sentry
  • All API routes return proper HTTP status codes + JSON error bodies
  • Form submission error states: clear per-field errors + general fallback
  • Payload API fetch failures: graceful degradation (show fallback content, not crash)

Feature 33 — Deployment (Ubuntu VPS + Docker)

Stack: Ubuntu server · Docker + Docker Compose · Nginx reverse proxy · Let's Encrypt SSL

33.1 — Server preparation

  • Install Docker + Docker Compose on Ubuntu:
    curl -fsSL https://get.docker.com | sh
    sudo usermod -aG docker $USER
    
  • Install Nginx + Certbot:
    sudo apt install nginx certbot python3-certbot-nginx -y
    
  • Clone repository on server:
    git clone git@github.com:YOUR_ORG/axil-accountants.git /opt/axil
    cd /opt/axil && git checkout main
    
  • Create production .env.local on server (manually — never commit):
    • DATABASE_URI=postgresql://axil:STRONG_PASS@db:5432/axil
    • PAYLOAD_SECRET=STRONG_SECRET_32_CHARS
    • NEXT_PUBLIC_SITE_URL=https://axilaccountants.co.uk

33.2 — Docker Compose production override

  • Create docker-compose.prod.yml (production overrides):
    • App: NODE_ENV=production, restart: always, no port 3000 exposed externally (only via Nginx)
    • DB: named volume for persistence, restart: always
    • Remove dev-only volume mounts

33.3 — Nginx reverse proxy

  • Create /etc/nginx/sites-available/axil config:
    • server_name axilaccountants.co.uk www.axilaccountants.co.uk
    • proxy_pass http://127.0.0.1:3000
    • Gzip, proxy headers, timeouts
  • Enable site: sudo ln -s /etc/nginx/sites-available/axil /etc/nginx/sites-enabled/
  • Obtain SSL certificate: sudo certbot --nginx -d axilaccountants.co.uk -d www.axilaccountants.co.uk
  • Verify auto-renewal: sudo certbot renew --dry-run
  • Configure www → apex redirect in Nginx (301)

33.4 — Deploy script

  • Create scripts/deploy.sh at repo root:
    #!/bin/bash
    set -e
    cd /opt/axil
    git pull origin main
    docker compose -f docker-compose.yml -f docker-compose.prod.yml build app
    docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps app
    docker image prune -f
    echo "Deploy complete: $(date)"
    
  • Make executable: chmod +x scripts/deploy.sh
  • Test deploy: ./scripts/deploy.sh — verify site responds after restart

33.5 — Verification

  • Run production build locally first: docker compose build && docker compose up — no errors
  • Verify HTTPS works: curl -I https://axilaccountants.co.uk
  • Run Lighthouse on production URL — confirm scores meet targets
  • Verify DB volume survives container restart (data not lost)

Feature 34 — Content Seeding & CMS Setup

  • Create seed script (src/payload/seed.ts):
    • Site Settings: company name, logo, contact details, placeholder social URLs
    • 4 Services: Bookkeeping, Tax Returns, Payroll, VAT Returns (full content per service)
    • 3 Sample Testimonials (marked as featured)
    • 3 FAQs per service
    • Blog Categories: "Tax Tips", "Business Advice", "HMRC Updates", "Payroll Guide"
    • Navigation: full nav structure from concept
    • Footer: all columns with links
  • Run seed script against production database
  • Verify all seeded content displays correctly on frontend
  • Create CMS editor user account for client

Feature 35 — Client Handover & Documentation

  • CMS User Guide (docs/cms-guide.md):
    • How to log into the admin panel
    • How to edit page content (services, hero text, etc.)
    • How to write and publish a blog post
    • How to add a testimonial
    • How to add a team member
    • How to create a contact form
    • How to set up a webhook on a form
    • How to change the chat bot mode
    • How to update integration settings (GA, GTM, Calendly URL)
  • Handover checklist:
    • Client has admin login credentials
    • Client has SSH access to server (or handover to sysadmin)
    • Client has Resend account access (for email settings)
    • DNS properly pointing to Vercel
    • Google Analytics connected and receiving data
    • Booking form submissions arriving in CMS + email
    • Mobile tested on real device (iPhone + Android)
    • Lighthouse scores confirmed ≥ 95 Performance

Summary: Feature Dependency Order

Feature 1  (Project Setup)
    └── Feature 2  (Database)
            └── Feature 3  (Payload CMS Core)
                    └── Feature 4  (CMS Collections Schema)
                            ├── Feature 5  (Design System)          ← parallel from here
                            ├── Feature 6  (Animation Infrastructure)
                            └── Feature 7 + 8  (Header + Footer)
                                    └── Feature 9  (3D Scene)
                                            └── Feature 10  (Hero Section)
                                                    └── Features 1118  (Home Page Sections)
                                                            └── Feature 19  (Booking Modal) ← needed by all CTAs
                                                                    ├── Feature 20  (Services Pages)
                                                                    ├── Feature 21  (About Page)
                                                                    ├── Feature 22  (Blog)
                                                                    ├── Feature 23  (Contact Page)
                                                                    └── Feature 24  (Legal Pages)
                                                                            ├── Feature 25  (Chat Bot)
                                                                            ├── Feature 26  (SEO)
                                                                            ├── Feature 27  (Analytics)
                                                                            ├── Feature 28  (Form Renderer)
                                                                            ├── Feature 29  (Performance)
                                                                            ├── Feature 30  (Accessibility)
                                                                            ├── Feature 31  (Responsive QA)
                                                                            ├── Feature 32  (Error Handling)
                                                                            └── Feature 33  (Deployment)
                                                                                    ├── Feature 34  (Content Seed)
                                                                                    └── Feature 35  (Handover)

Total features: 35 | Estimated tasks: ~220 Last updated: February 2026