Eating our own dog food: How we redesigned Sulu.io with Headless Sulu and Remix
Sulu has supported headless projects for years, but our own website was built traditionally with Symfony and Twig. We recently redesigned the site and took the opportunity to put our headless capabilities to the test!
Rebuilding sulu.io with headless Sulu and Remix helped us understand when the headless approach makes most sense, what the trade-offs are, and how we can improve the developer experience for those who use Sulu in headless mode.
Building for modern performance
In addition to a fresh design and great UX, we had clear technical requirements: excellent SEO performance with proper server-side rendering, millisecond response times across all device types, and a development workflow that could scale with our growing team.
We could have met these requirements with traditional Symfony and Twig—that’s what our old site used, after all. But we wanted to test our headless capabilities in a real production environment. If we’re recommending headless Sulu to clients, we should understand exactly what they’ll experience.
Here’s the tech stack we used:
- Backend: Sulu CMS handling content management and API delivery.
- Frontend: Remix, a full-stack web framework built on top of React, providing server-side rendering with selective client-side hydration.
Why React feels right for interface development
React was built for this kind of work. Its component-based architecture feels incredibly natural when building web interfaces. Twig templates can sometimes feel like you’re pushing against the grain, but React components just flow.
Frontend engineers immediately feel at home with React/Remix because they can:
- Think in reusable components from day one
- Leverage the entire JavaScript ecosystem
- Use familiar tooling and development patterns
- Build interactive interfaces without mental context switching
This component-based approach fundamentally changes how you build the frontend. Need a hero section? Create a <Hero>
component. Complex navigation? Build a <Navigation>
component. Each piece is self-contained, testable, and reusable.
Design systems and atomic design patterns also come more naturally. Building from atoms (buttons, inputs) to molecules (search bars, cards) to organisms (headers, content sections) feels intuitive when each level represents an actual React component. This systematic approach to interface development is exactly what React was designed for.
Knowledge that benefits our whole community
This redesign gave us a real education. By using our own product in a new way, we gained insights into performance optimization in headless setups, developer experience when working with Sulu’s APIs, and the challenges our users face when going headless.
Every bug we fixed, every performance bottleneck we hit, every “aha!” moment we had—all of it feeds back into making Sulu better for everyone and helping our entire community tackle headless challenges more effectively.
The headless performance myth
There’s a widespread belief that going headless automatically delivers better performance. We need to be precise here: Which performance are we talking about? Response times? Development velocity? User experience?
Let’s examine response times first. Headless setups introduce more moving parts: separate backend and frontend services, API calls, multi-layer caching, and complex deployment pipelines. Each request travels through more layers than traditional setups, and every additional hop introduces latency.
We experienced this reality firsthand. Without proper HTTP caching strategies, our headless architecture wasn’t viable at scale. Our performance only improved through deliberate implementation of API response caching, HTML caching, and CDN strategies working together. The same optimization principles apply to traditional server-rendered websites.
What about development velocity? This depends entirely on your team’s expertise and how you structure your workflow.
User experience improvements? Possibly, but modern approaches like Symfony UX with Turbo can deliver similar interactive experiences through traditional server-rendered architecture.
Ultimately, we should admit that headless doesn’t automatically mean better performance. Your choice should be based on your specific requirements, not assumptions.
The reality of headless complexity
Going headless introduced complexity that traditional Symfony deployments simply don’t have. We’d like to share the challenges we encountered with our community:
Deployment complexity
This was our first reality check. What used to be a straightforward Symfony deployment now meant coordinating multiple services: managing Symfony/PHP backend deployments alongside Node.js frontend runtimes, juggling environment variables across services, handling API calls, configuring the reverse proxy properly, defining x-forwarded and trusted proxy headers correctly, and ensuring that both PHP and Node applications stayed perfectly synchronized.
Caching becomes trickier
Caching strategy also required more thought. Where traditional Sulu offered straightforward caching through the framework or a simple Varnish setup, our headless architecture now demands careful orchestration of API response caching, HTML caching for the frontend, and cache invalidation across both levels.
Form handling gets complex
Form handling wasn’t simple anymore. Remember those straightforward Symfony forms that just worked? Now every form submission needs to call the backend API, handle loading states gracefully on the frontend, manage error responses with finesse, and maintain validation synchronization between client and server.
The traditional Symfony/Twig alternative
Don’t worry—the traditional approach isn’t going anywhere! If you want to see how productive and organized Twig templating can be, check out Alex’s upcoming talk “A Productive Frontend Stack with Symfony UX” at SymfonyCon 2025 in Amsterdam.
Recent projects using Symfony UX with well-structured Twig components demonstrate that the traditional approach often provides exactly what projects need. Symfony UX has evolved dramatically, bringing Stimulus, Turbo, and Live Components that make server-side rendering more dynamic and interactive than ever.
Why this matters for Sulu users
Thanks to our journey from traditional to headless, we feel we’re in a good position to help our users choose hte best architecture for them.
Go headless when you have:
- Frontend teams experienced in JS frameworks
- Complex interactivity that benefits from React/Vue/Angular
- Independent frontend/backend deployment needs
Stick with traditional Symfony/Twig when you have:
- Teams comfortable with server-side rendering patterns
- Projects that benefit from simpler deployment and caching
- Straightforward content websites without heavy interactivity
- Tight timelines where reduced complexity is a must
You can also use a hybrid approach within a single application: Render most content traditionally with Twig while using Sulu’s API for specific interactive components that need client-side updates.
The bottom line
Would we choose headless again for our own website? Most likely not. There are no specific requirements pushing us in this direction for a content-focused site like ours. But this was an incredibly valuable learning experience that deepened our understanding of when headless truly makes sense.
Both traditional and headless approaches have earned their place in modern web development. Sulu supports your decision either way, and our own experience proves that the right tool for the job always beats the trendy one. Choose based on requirements, not headlines.