Boisson SolutionX

Back to portfolio

Web development

The client needed a site they could update on their own (hero, product cards, retailer and distributor calls to action) without the speed and theme limits of a classic WordPress build.

I built a headless setup. WordPress + ACF stays the editing tool, and a React/TypeScript single-page app pulls page content through WPGraphQL. The contact form uses a custom GraphQL mutation (createContactMessage, registered in functions.php) that cleans each input with sanitize_text_field and saves the message as a WordPress post.

Architecture: a layered client. Components call custom hooks (useHomePageData, useContactFormQuery), hooks call a service layer (homePageService) that uses one shared Axios instance, and GraphQL queries live in their own module. TanStack Query (useQuery/useMutation) manages server state, with a retry rule that never retries validation errors and retries network errors up to 3 times.

Best practices: strict TypeScript models for the GraphQL responses; typed error classes (GraphQLServiceError, NetworkError, ValidationError) that turn transport failures into clear outcomes; client-side form validation before sending, with loading and success/error states; ESLint with typescript-eslint, and Tailwind v4 through the Vite plugin.

Stack

  • React
  • TypeScript
  • Vite
  • Tailwind CSS
  • TanStack Query
  • Headless WordPress
  • WPGraphQL
  • ACF

Gallery