The problem
One Mind Agency is a creative agency that needed a bilingual site, in English and Italian, to show its work and win new business. The team wanted to publish case studies from a familiar admin, and every enquiry had to land in a sales pipeline, not in an inbox. The hosting was shared: Node could run builds, but not a permanent server.
What I built
I built three pieces that live side by side on one domain.
- Static front end in Next.js — home, work, single case study, about and contact pages, exported as plain files under /en/ and /it/. Fast to serve, nothing to keep running.
- Headless WordPress under /cms — a custom plugin registers the Case Study post type and its fields (client, year, category, accent colour, summary, credits) and exposes them, with their translations, through the REST API. Public WordPress pages redirect to the real site.
- Automatic rebuilds — when an editor saves content, WordPress raises a flag. A server job picks it up within about 5 minutes, rebuilds the site and swaps the files, with a lock so two builds never overlap.
- Contact form to CRM — a small PHP bridge turns each enquiry into a Lead in EspoCRM, with budget range and language. The CRM key stays on the server and never reaches the browser.
- Spam and abuse protection — a hidden honeypot field, one request every 30 seconds per IP address, an origin allowlist and strict validation of every field.
- No broken images — if a case study points to an image file that no longer exists, the API returns nothing and the page shows a colour placeholder instead.
Built with
Next.js 15 with static export, React 19, Tailwind CSS, Framer Motion and Lenis. WordPress with ACF and Polylang. EspoCRM. PHP 8.2 and MariaDB 10.11 on Hetzner.
Why it was done this way
The server allows Node only for builds, with no long-running processes. So the site is generated at build time and served as static files, while WordPress and the CRM run on the PHP the server already had. Editors keep a normal admin, and visitors get plain HTML.


