This is the overview of the free series Frontend system design for enterprise applications, first published on tt-tech.io.
An enterprise frontend outlives its framework, its first team and usually its first architect. That changes which concepts matter. The concepts were never the hard part. Knowing which ones to ignore was.
Most frontend system design content prepares you for an interview: design a news feed in 45 minutes, on a whiteboard, for nobody. Enterprise frontends fail in a different way. They do not fail on day one. They fail in year seven, when the decision nobody made on purpose is now in four hundred files.
I have spent more than twenty years in software, building enterprise applications. This series is what I would tell a team starting one, or inheriting one.
What makes a frontend "enterprise"
It is not the size of the bundle. It is five things that small apps rarely have at the same time.
Time. The code lives longer than the framework. AngularJS support ended in January 2022.[1] The apps built on it did not end with it. I have been part of several migrations from AngularJS to Angular, in different teams and roles. The lesson every time: the boundaries you draw in year one decide what you can delete in year ten.
Teams. Many teams in one codebase, often one monorepo. The lines between their code are the architecture, whether anyone drew them or not.
Rules. Banking and healthcare come with rules the frontend cannot wave away. Access control is "only effective when implemented in trusted server-side code or serverless APIs", and broken access control keeps the top spot in the OWASP Top 10:2025.[2] In the EU, the European Accessibility Act covers consumer banking services provided to consumers after 28 June 2025.[3] For banks in scope, accessibility is a requirement there, not a nice-to-have.
Roles. The same screen looks different for a customer, an advisor and an auditor. Somebody has to decide where that logic lives.
Languages. For Morocco and the Gulf, Arabic is right to left, French text often runs longer than English, and Moroccan money is MAD with its own format. A layout built with left and right breaks the day Arabic arrives. CSS logical properties describe directions "relative to the content's writing direction, rather than a physical direction",[4] and that one choice decides whether RTL is a small task or a rewrite.
In enterprise, the decision outlives the people who made it. Design for the next team.
The eight parts
Eight areas, and in each only the five to seven concepts that change a decision.
- Architecture. Layers, enforced boundaries, monorepo or not, micro-frontends mostly not, and the legacy corner you keep deletable.
- State. Who owns each piece of state and how long it lives. Server data, UI, forms, the URL.
- Networking and caching. One question, so one part: where does this data live, and when is it wrong?
- Rendering. Many logged-in enterprise apps do not need server rendering. When they do, and what it costs.
- Performance. Budgets that fail the build, measured on the devices your users really have.
- Security. The frontend is the untrusted part. What the client can protect, and what it only shows.
- Accessibility. A legal requirement, and the design system is where it is won or lost.
- Languages, RTL and money. Arabic, French and MAD from the first component, not as a later project.
Caching sits with networking because a cache without an owner is a bug with a delay. RTL gets its own part because for readers in Morocco and the Gulf it is not a sub-bullet of accessibility.
How each part works
Every part has the same shape:
- The few concepts that matter, each with one line on why.
- When to choose what. Signals or RxJS, CSR or SSR, monorepo or polyrepo. The trade-off in plain words, Angular first, React next to it where the choice differs.
- What I left out, and why. A concept that sounds important but rarely changes a decision in an enterprise app.
-
An example on Atlas Bank, the open demo app of the AI with Angular series: an imaginary Moroccan bank, built as an Nx monorepo, with module boundaries that
npm run lint:archenforces and two legacy corners (anNgModuletransfer screen and an AngularJS beneficiaries screen). The repo is public. Never client code.
A glossary tells you what a word means. Production tells you which words you can ignore.
On Monday
- Take the oldest screen in your app. For each of the eight areas, ask: was this decided on purpose, or did it happen by default?
- Write down the one you cannot answer. That is your first architecture decision record.
- Start with Atlas Bank's architecture page: it shows the dependency contract the first part builds on.
For your coding agent
The rules of all eight parts in one file, written for an agent. Paste them into your AGENTS.md, save them as a skill, or point your agent at the file. Each part also has its own file at the end of the article.
The file: https://tt-tech.io/agents/frontend-system-design.md
Sources
- AngularJS, Version Support Status, docs
- OWASP, A01 Broken Access Control - OWASP Top 10:2025, 2025
- EUR-Lex, Directive (EU) 2019/882 on the accessibility requirements for products and services, 2019
- MDN, CSS logical properties and values
The overview of the free series Frontend system design for enterprise applications on tt-tech.io, also in French and Arabic.
Top comments (3)
Spot on regarding architectural decisions at scale. Decoupling state early saves massive refactoring pain down the road when enterprise apps scale. Great breakdown!
Thanks Ali. Agreed, and the cheapest way to decouple it is to name an owner for each piece of state: server data in one cache, UI state in the component, filters in the URL. The state part of the series is built around exactly that question: tt-tech.io/blog/enterprise-fronten...
The 'year seven, four hundred files' framing is the right lens: enterprise rot comes from decisions nobody made explicitly, so the year-one boundaries you draw are what make code deletable and migratable later, rather than an implicit coupling that compounds across handoffs. Access control is a good line to keep repeating: it has to be enforced in trusted server-side code, with the frontend only hiding UI, because anything trusted client-side can be bypassed — same as keeping authorization out of a desktop renderer. With many teams in one repo, those cross-team contracts (types, API surfaces) should be explicit and guarded by the build, not left as unspoken conventions that only the original team remembers.