Commit graph

21 commits

Author SHA1 Message Date
Vadym Samoilenko
7b6cfaa5c2 fix: wrap generateStaticParams in try/catch to survive build without DB
Some checks failed
Deploy to production / SSH deploy to VPS (push) Has been cancelled
During Docker build the `db` host doesn't exist in the build network,
so any attempt to query Postgres in generateStaticParams fails. With the
try/catch, blog pages fall back to [] (rendered on demand) and service
pages fall back to hardcoded SERVICES_FALLBACK slugs so static pages
are still pre-generated even without a live DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 22:01:00 +00:00
Vadym Samoilenko
dc1b1efbab fix: use minimal Payload config in migrator to prevent OOM SIGKILL
The migrator was importing the full payload.config.ts which loads lexical
editor + form-builder plugin — very heavy modules that caused the process
to be SIGKILL'd (exit 9) on the VPS.

The new migrate.ts builds an inline minimal config: only the postgres
adapter + explicit migrationDir. No editor, no plugins, no
collections/globals needed to run raw SQL migrations. This should fit
comfortably within VPS memory limits.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 21:46:29 +00:00
Vadym Samoilenko
1ba1349607 fix: use programmatic migrate script instead of pnpm payload migrate
pnpm payload migrate exits 1 in the migrator container likely due to TLA
issues with Lexical packages (same issue seen with migrate:create).

Replace with a small src/scripts/migrate.ts that calls payload.db.migrate()
programmatically, using the same NODE_OPTIONS approach that works for seed.ts:
  NODE_OPTIONS="--experimental-strip-types --no-require-module"

Also add migrator log output to the CD workflow for easier debugging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 21:37:29 +00:00
Vadym Samoilenko
96ab1c5da6 fix: run DB migrations via migrator service, not standalone app
In Next.js standalone output (output: 'standalone') the src/migrations/
directory is not present on the filesystem, so payload.db.migrate()
could not discover migration files → home_page table was never created
→ getHomePage() threw a DB error → Server Components render failed.

Fix:
- Add `migrator` service to docker-compose.prod.yml (builds from the
  `migrator` Dockerfile stage which has the full src/ tree)
- migrator runs `pnpm payload migrate` before app starts
- app depends_on migrator: service_completed_successfully
- Remove payload.db.migrate() from instrumentation.ts (migrator handles it)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 21:31:52 +00:00
Vadym Samoilenko
3f6dfe36b1 feat: full CMS integration — connect all content to Payload admin panel
- Connect homepage, blog, services, header, footer to Payload CMS via local API
- Add HomePage global with 7 editorial sections (hero, painPoints, solution, whyAxil, audience, process, finalCta)
- Add ServerHeader/ServerFooter async wrappers with unstable_cache + tag-based ISR revalidation
- Rewrite blog/[slug] and services/[slug] pages to fetch from CMS with fallbacks
- Add seed script (src/lib/seed.ts) to populate all collections and globals from hardcoded defaults
- Restructure app into (site)/ route group to fix Payload admin hydration conflicts
- Make root layout a passthrough; (site)/layout.tsx owns html/body/fonts
- Restrict user creation/update/delete to admin role only
- Fix migration imports: type MigrateUpArgs/Down from @payloadcms/db-postgres
- Wrap revalidateTag dynamic imports in try/catch for seed/CLI compatibility
- Skip migrations in dev mode (Payload handles schema push automatically)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 21:19:44 +00:00
Vadym Samoilenko
190581c80b feat: replace logo with official Axil Accountants brand mark
Swaps logo-axil.png for logo-axil.jpg (official logo with blue A
lettermark, green bar chart icon and AXIL ACCOUNTANTS wordmark).
Updates Header and Footer references accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 18:20:14 +00:00
Vadym Samoilenko
4ef45a311d fix: change contact form sender to info@ai-impress.com
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 15:46:32 +00:00
Vadym Samoilenko
338b47d4c1 feat: wire contact form to Resend email notifications
- Add Server Action (actions.ts) sending to info@ and anastasia@axilaccountants.co.uk
- Add ContactForm client component with useActionState, loading and success states
- Replace static HTML form (action="#") with live ContactForm component
- Add @eslint/eslintrc as direct devDependency (fix ESLint resolution on Node.js 25)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 15:45:11 +00:00
Vadym Samoilenko
2b19626b68 feat: add initial DB migrations and sharp dependency
- Generate initial Payload CMS migration (all collections + globals)
- Add sharp for image resizing support
- Add .ts extensions to payload.config.ts imports (required for migrate:create with --disable-transpile)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 15:28:24 +00:00
Vadym Samoilenko
4e23350bfc fix: run migrations via Next.js instrumentation.ts at startup
tsx v4 + Node.js 22 ESM does not handle extensionless .ts imports.
instrumentation.ts uses compiled/bundled code — no resolution issues.
Migrations run automatically before first request on every app start.
Removes external migrator container approach entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 14:14:18 +00:00
Vadym Samoilenko
2c115bab99 fix: resolve all TypeScript build errors
- InteractiveMenu: block body on textRefs callback (void return)
- TextHoverEffect: remove stale @ts-expect-error (now unused)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 13:55:57 +00:00
Vadym Samoilenko
dcd6eb487e fix: ref callback return type in InteractiveMenu
Block body prevents implicit return of HTMLButtonElement | null,
fixing TS error in stricter React ref type checking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 13:53:24 +00:00
Vadym Samoilenko
7bb25f9c59 feat: add courses page, real contact details, Courses to navigation
- New /courses page with 5 course cards (Interview Ready, Self
  Assessment, Payroll, QuickBooks, Xero) with thumbnail images,
  pricing, includes checklists, and enrol CTAs
- Added course images to public/courses/ and Assets/
- Contact page: updated email, phone (07440 594192), address
  (Suite 29 Beaufort Court E14 9XL), hours, and added Courses
  option to the "I'm interested in" select field
- Header: added Courses to desktop nav and mobile dock
  (GraduationCap icon) between Services and Blog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 13:25:16 +00:00
Vadym Samoilenko
9d4bb7ad34 fix: add missing href to all broken buttons across site
- services/page.tsx: 'Book Free Consultation' bottom CTA → /contact
- services/[slug]/page.tsx: hero + final CTA 'Book Free Consultation' → /contact;
  fix nested <Link> inside secondary Button (invalid HTML) → href prop
- blog/page.tsx: 'Subscribe to newsletter' → /contact (no newsletter service yet)
- blog/[slug]/page.tsx: inline 'Book Free Consultation' CTA → /contact

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 13:03:32 +00:00
Vadym Samoilenko
e4fcc5b9c8 fix: add missing href to 'Get your quote' button on services page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 13:00:40 +00:00
Vadym Samoilenko
946c6a44ab fix: remove duplicate CTAs and calendar reference
- services/page.tsx: remove duplicate 'Talk to us' (both went to /contact);
  fix 'Book Free Consultation' missing href; swap to BeamButton for consistency
- about/page.tsx: remove 'Contact Us' button duplicating BeamButton on same page;
  remove now-unused Button import
- contact/page.tsx: replace "directly in our calendar" with call-back copy
  since no calendar integration exists yet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 12:55:29 +00:00
Vadym Samoilenko
28b999b1ae fix: align all CTAs with concept — every CTA leads to contact form
- ProcessSection: 'Get started' href /services → /contact
- BlogPreviewSection: fix invalid <Link> nested inside <Button> (was <button><a>)
- ContactPage: 'Book free consultation' sidebar button now href="#contact-form"
  with matching id on the form element (was unclickable — no href)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 12:51:57 +00:00
Vadym Samoilenko
7cd698d6d6 feat: UI polish — SolutionSection stacked cards, BeamButton CTA, Footer redesign
- SolutionSection: replace flat cards with interactive stacked card layout
  (skew, grayscale, hover lift, click-to-expand with z-50 + skew reset)
- BeamButton: new component with framer-motion SVG beam animation along
  pill border (emerald→blue gradient); variants dark/light
- HeroSection + FinalCTASection: primary CTA switched to BeamButton
- Footer: replace programmatic SVG logo with logo-axil.png via next/image;
  add AImpress LTD credit link; increase hero text height
- TextHoverEffect: fix viewBox (920×100), use SVG-unit fontSize, split
  AXIL (blue #1B9AD6) / ACCOUNTANTS (emerald #3CC68A) via tspan

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 12:30:50 +00:00
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
Vadym Samoilenko
8db56af042 refactor: replace hardcoded hex colors with design system tokens
Replace all hardcoded hex color values in components with Tailwind CSS
classes or CSS custom properties matching the design system tokens.
Affected files: Footer, TestimonialsColumn, HeroSection, StarIcon,
TextHoverEffect, and all page-level radial-gradient backgrounds.

Also fix eslint.config.mjs to use FlatCompat for eslint-config-next
legacy config compatibility with ESLint 9 flat config format, and
resolve pre-existing react/no-unescaped-entities errors in JSX files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 20:36:50 +00:00
Vadym Samoilenko
e373c2b46c feat: project setup & repository (Feature 1)
- Next.js 16.1.6 with App Router, TypeScript strict, Tailwind CSS v4
- ESLint 9, Prettier with Tailwind class sorting plugin
- Husky + lint-staged pre-commit hooks
- Multi-stage Dockerfile (dev/build/production) with pnpm + Node 20
- docker-compose.yml with hot reload + PostgreSQL 17
- src/ directory structure (components, lib, hooks, types, payload)
- .env.example template with all required variables
- standalone output mode for production Docker builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:43:53 +00:00