I buildfrontendsfor enterprise,at production scale.
8 yearsshipping React & TypeScript to Mercedes-Benz, Sonova, Thalia, and TBO Clothing — multi-tenant architecture, Core Web Vitals under 2s, cache invalidation that works the first time. When the product demands it, I reach into NestJS and LLM orchestration to close the loop.
Products that ship. Metrics that move.
Hired once, re-hired often.
Faisal rebuilt the frontend of our white-label platform while we kept shipping to enterprise clients. Zero regressions, zero production incidents in the quarter after launch. The kind of senior engineer you let own the architecture and then stop worrying about it.
Klaire was the single biggest operational shift we've had. Client onboarding went from a week of back-and-forth with our team to twenty minutes the client does themselves. Faisal architected the whole thing — orchestration, frontend, the reliability layer — and it ran in production for enterprise clients across Europe.
Faisal's templates on ThemeForest set the bar for the team. Clean markup, pixel-accurate, genuinely responsive when 'responsive' was still a buzzword — and every one of them sold in the hundreds to low thousands. He makes frontend look easy.
Senior means decisions, not just code.
Core Web Vitals by design
I engineer for performance from day one — not as an afterthought. SSR/SSG strategy, route-based code splitting, lazy-loading below-the-fold, preloaded critical assets, eliminated render-blocking resources. Sub-2s mobile on enterprise deployments.
State with intentionality
Server state via RTK Query — auto-caching, tag-based invalidation, background refetch, optimistic updates. Local UI state close to the component with useState and useReducer. Redux Toolkit where cross-cutting concerns genuinely demand it. Lean bundles, predictable components.
Resilient data layers
Typed API clients with Axios interceptors for auth injection and error normalisation. Request deduplication, retry with exponential backoff, response caching that prevents redundant network calls. GraphQL where clients shape data; REST where simplicity wins.
Architecture for teams, not just today
Feature-based folder structure, strict component boundaries, shared design tokens, Storybook-driven development across multiple enterprise teams. Code a new engineer can navigate on day one — and ship to on day two.
Frontend-embedded AI that ships
I ship AI features the way I ship UI — with the same rigor. LLM orchestration (Claude, GPT-4o, Gemini) through tool calling and multi-step agent loops. Streaming into real interfaces, not chat widgets. The hard part isn't connecting the APIs — it's making the output reliable enough that a non-technical user trusts it without reviewing every result. That's where I operate.
8 years of shipping — and rewriting it better.
Lead the frontend of a white-label B2B SaaS community platform shipped to enterprise clients across Europe — Mercedes-Benz, Sonova, Thalia, TBO Clothing. Built the multi-tenant design system: tokenised brand config per tenant, a Storybook-driven component library, and a theming engine that lets a new brand ship in hours. Architected the Next.js frontend with per-tenant × per-campaign server caching, feed/shop/rewards flows at sub-2s cold load, and the white-labelling layer. Built the operator UI for the AI Page Builder (Claude/GPT-4o), the authoring surface for Visual Micro-Apps, and the dashboards for the outbound AI-call automation. Reached into NestJS, BullMQ, and the cache invalidation layer whenever the frontend needed the backend to move with it. Cut content production time by 87%; drove production incidents from 9/quarter to zero.
The code, live.
// server state as a first-class citizen
export const usersApi = createApi({
reducerPath: 'usersApi',
baseQuery: authedBaseQuery('/api'),
tagTypes: ['Users'],
endpoints: (build) => ({
listUsers: build.query<User[], void>({
query: () => '/users',
providesTags: ['Users'],
keepUnusedDataFor: 8,
}),
}),
});
const { data, isFetching, refetch } = useListUsersQuery();
// auto cache · tag invalidation · typed errors- 01Refetch network
Forces a round-trip. 700ms of simulated latency, then the cache is refreshed with the new payload and the timestamp resets.
- 02Use cache instant · 0 ms
If the cache is fresh (< 8s old), we return the cached payload synchronously — no loading state, no network. This is the whole point.
- 03Simulate error retry · 800ms backoff
60% chance of a failed request. The UI enters
errorstate, then a retry fires with backoff — exactly the pattern production APIs need. - 04Invalidate tag-based
Manually blows the cache — the moment the data you trusted is no longer true (a write, a mutation, a session change). In RTK Query this is a tag invalidation; here it's a ref reset.
tenant:campaign granularity — reads are O(1), the write path is the only source of staleness. More on that in Notes.How I think about the work.
Cache invalidation is a product decision, not a technical one
Notes from three years of multi-tenant platforms
Every multi-tenant platform I've shipped comes back to the same question: how fine-grained does your cache need to be? Get it wrong in either direction and the product tells on you.
Too coarse — `cache per tenant` — and one admin editing a single campaign nukes the cached pages for every other campaign they own. The editor sees an instant update. Every other editor on the tenant sees a cold render they did not cause.
Too granular — `cache per page per tenant per user` — and you haven't really cached anything. You've just paid for Redis.
The answer is almost never technical. It is: what is the smallest unit of content an editor actually edits? For SPEAR, it was the tenant design config. For Growth Engine, it was the `tenant:campaign` tuple. That tuple becomes the cache key, and the only path that invalidates it is the save endpoint in the admin.
Two properties fall out of this: writes are the only source of staleness (reads are pure), and reads stay O(1) on a warm cache. Editors see their own changes instantly. Everyone else sees the cached page until the moment an edit they care about lands.
That's the whole trick. Pick the right key, put the invalidation on the write path, and stop touching it.
The hard part of AI automation isn't connecting the tools
Notes from a B2B outbound pipeline running 6,316 executions a week
A few months ago I built a fully automated B2B outbound pipeline in n8n. Input: a company name in a Google Sheet. Output: a personalised email draft sitting in Gmail, ready for a human to glance at and send. Zero manual work in between.
The pipeline runs six connected workflows. Apollo finds the right contact. Claude scores the matches and picks the target. PhantomBuster scrapes LinkedIn activity. Google Custom Search pulls public signals. Claude builds an intelligence profile, drafts a cold email, and writes the Gmail draft. A second workflow handles follow-ups — day two tries a Vapi AI phone call first and only falls back to email if unanswered, day five sends a concise second touch. A third polls Gmail every minute, classifies replies, updates the sheet. A fourth deduplicates so no lead ever gets emailed twice.
None of that is the hard part. Connecting APIs is plumbing. n8n makes plumbing trivial.
The hard part is making AI decisions reliable enough to trust without checking every single output. A classifier that's 92% accurate sounds great until you realise that 8% failure rate means dozens of bad labels a week on a pipeline doing thousands of runs. An LLM-written email that's good 19 times out of 20 still embarrasses you on the twentieth if nobody reads it.
The answer isn't one trick, it's a layered one. Strict schemas on every LLM output so bad data fails loud instead of silent. Tool calling for anything that touches a database, so the model proposes and the code disposes. Validation gates between stages that refuse to move forward on malformed input. And one human-in-the-loop checkpoint at the point of irreversibility — the Gmail send button — because that's the exact place where a human's skim costs you seconds and catches the 5% the model got wrong.
Self-hosted on GCP, because cloud n8n hits limits fast on a pipeline moving this much volume. 6,316 executions in a week. Instead of a rep reaching five qualified leads a day, the system reaches a hundred.
That's the real engineering problem in AI automation: not whether the model can do the task, but how you build a system that catches the model when it can't.
Send me the hardest
frontend problem your team is facing.
I'll reply within a day with how I'd approach it — paid engagement or not. If it's a fit for both of us, we go deeper. If it's not, you'll still have a second opinion on a hard problem.
- Senior / Staff Frontend roles
- React · Next.js · TypeScript at production scale
- Design system & multi-tenant architecture
- AI-frontend — LLMs embedded in real UI, not chat widgets
- Performance rescues — Core Web Vitals under 2s
- Remote · async · European time overlap
- Junior or mid-level roles
- WordPress / pure templating work
- Crypto, web3, gambling, adtech
- Unpaid trials or spec work
- On-site only · no remote option
- Agency-style body-shopping contracts






