← Back to work
Private client project 2026·Full-stack Engineer

Solid

Corporate site with a custom headless CMS — and a multi-client store platform.

Overview

The project

Solid is the studio's own corporate site: a marketing front end driven by a bespoke admin CMS for blog, portfolio, services, and careers. Alongside it sits a reusable WordPress + WooCommerce platform that spins up branded multi-client stores from a shared codebase.

Screens

Screenshots

Tap any image to enlarge. Use arrow keys to navigate.

Stack

What I built it with

Laravel 12Inertia v2React 19TypeScriptTailwind v4WordPressWooCommerceMySQL

My role

What I owned

  • Built the corporate marketing site (home, work, services, blog, careers) on Inertia + React.
  • Built the admin CMS: blog with translations, portfolio, services, jobs, and newsletter campaigns.
  • Implemented 2FA, email verification, and role-based access with Fortify + spatie/permission.
  • Engineered a multi-client WordPress/WooCommerce platform with a shared plugin and vendor theme.
  • Added bilingual storefronts, seeded catalogs, and Wompi/Tilopay payment gateways.

Architecture

How it's wired

  • 01Laravel 12 monolith serving an Inertia v2 + React 19 front end, no separate API layer.
  • 02Headless-style admin CMS with translation tables driving public content.
  • 03Separate WordPress + WooCommerce platform split across plugin, theme, and per-client repos.
  • 04Dockerized store deploys that auto-install WP, seed a catalog, and wire commerce config from env.

Hard parts

What was challenging

The decisions worth talking about in an interview.

One store codebase, many branded clients

The WooCommerce platform had to stay reusable while every client looks bespoke. A shared platform plugin plus an isolated vendor theme and a per-client repo kept client-specific code from leaking into the shared base, with hooks as the only extension surface.

Bilingual CMS without a translation plugin

Rather than pull in WPML/Polylang, the storefront does EN/ES through a gettext filter map plus a cookie — which means every new string has to be registered in both the gettext and ngettext maps to stay translated.