Case study / Flowable
Keeping a live
site moving.
I’m the sole engineer and technical owner of Flowable’s marketing website, from architecture and implementation through testing and releases. I partner with design and marketing, and scope features end to end with them.
- Role
- Sole engineer and technical owner
- Stack
- Next.js, TypeScript, Contentful, Tailwind, Radix UI, Storybook
- Scope
- Architecture, delivery, quality, and technical health
The brief
A live site,
not a blank slate.
Flowable’s website supports an active marketing team. Every improvement has to land without getting in the way of campaigns, content updates, or visitors.
The work runs under four constraints:
- Always publishing. Marketing publishes continuously, so no change can depend on a content freeze.
- CMS-driven. Editors assemble pages in Contentful, so components have to hold up in any combination they are given.
- Search matters. Rankings, redirects, and metadata can’t regress.
- One engineer. Every change has to be safe to ship without a team to catch it.
Decisions
Four calls
that kept it moving.
One change at a time
Instead of
Rewriting routing and caching together in one big release.
Chose: Migrate from Pages Router to App Router route by route, and leave the publishing model alone.
Why: Editors kept their exact workflow, and SEO stayed protected while both routers ran side by side.
EvidenceMetadata driven by CMS SEO fields, redirects and canonical URLs kept identical, and Search Console checked after each move.
Composition over variants
Instead of
A separate block, or a growing set of variant props, for every arrangement.
Chose: Compound components: editors pick a design and attach child entries in Contentful.
Why: Different entries needed different arrangements of the same parts. Composition covers them with one component.
Evidence35 CMS-driven components on Radix UI primitives, with variants and states documented in Storybook.
Refresh without a freeze
Instead of
A big-bang relaunch behind a content freeze.
Chose: Switch fonts and the type scale centrally in the Tailwind theme, then redesign page type by page type.
Why: Marketing kept publishing the whole time, and each page type shipped on its own.
EvidenceMore than 100 published pages refreshed from Figma designs, with no content freeze.
Server by default
Instead of
Shipping client JavaScript for every section.
Chose: Render on the server and add client code only where interaction needs it.
Why: Every kilobyte of client JavaScript costs mobile visitors loading and interaction time.
EvidenceHeavy client libraries removed, images and fonts tuned. On the Agentic Case Platform launch page, an animated SVG replaced a video and the dashboards use no chart library.
The migration
Route
by route.
Both routers ran side by side until the last route moved, so the live site kept working at every step.
Illustrative: progress by step, not a measure of traffic.
- GroundworkRemoved patterns that only work in the Pages Router, so routes could move independently.
- API routesMoved the API endpoints to App Router route handlers.
- Shared layoutRebuilt the root layout and providers.
- Static pagesMoved the simple, fixed pages.
- BlogMoved the blog overview and category pages.
- CMS pagesMoved the Contentful-driven pages, then retired the Pages Router.
- CleanupRemoved what the old router no longer needed.
The result
Mobile score,
nearly doubled.
Server rendering by default, less client JavaScript, and tuned images and fonts took the lab score from the edge of poor to just short of good.
Next
What I'd
do next.
- Measure real-user performance (Core Web Vitals) alongside the lab scores.
- Move from a full rebuild on every publish to on-demand revalidation, so content goes live faster.