The World of SPA Applications: A Technical Director’s Conversation with a Junior Developer
Senior, the last article helped me understand SPAs much better. But now I want to go deeper. Not just “React, Angular and Blazor build UI”, but the professional world of SPA applications. How does a technical director or international frontend expert think about SPAs?
Good. That is the right question. At junior level, people ask, “Which framework should I learn?” At senior level, people ask, “How do we build a reliable frontend architecture that survives real users, changing requirements, security rules, production incidents, and team growth?”
A SPA is not just a frontend framework. It is a client-side application architecture. React, Angular and Blazor are implementation technologies. The bigger subject is how modern interactive web applications are designed, delivered, secured, tested, monitored and evolved.
Let’s start with a clean definition.
A Single Page Application, or SPA, is a web application that loads an initial application shell into the browser and then updates the user interface dynamically as the user interacts with the system. Instead of the server returning a full HTML page for every click, the client-side application handles navigation, state, rendering and API communication.
The basic journey looks like this:
Initial request
↓
Server returns index.html
↓
Browser downloads JavaScript/CSS/assets
↓
SPA framework boots
↓
Frontend router displays a view
↓
Components render UI
↓
APIs provide data
↓
State changes
↓
UI updates without full page reload
That is the foundation. But the professional world starts after that.
1. SPA versus traditional server-rendered web applications
So is SPA always better than server-rendered applications?
No. That is the first serious lesson. SPA is not automatically better. It is a trade-off.
Traditional server-rendered applications generate most HTML on the server. ASP.NET MVC, Razor Pages, PHP, Django, Rails and classic web frameworks work this way. The browser requests a page, the server builds HTML, and the browser displays it.
A SPA shifts much more responsibility to the browser. The browser becomes a small application runtime. It handles routing, state, rendering, validation, API calls and user interaction.
The advantage is a smoother, richer user experience. The cost is more frontend complexity.
A SPA is usually suitable when the application has rich interaction: dashboards, admin portals, customer portals, trading screens, workflow systems, healthcare platforms, SaaS products, CRM systems, project management systems, booking systems, finance screens, document-heavy systems, and anything where users stay inside the app and perform many actions.
A server-rendered approach may still be better for content-heavy websites, SEO-first marketing pages, simple public sites, or applications where initial page load speed and search engine visibility matter more than rich interaction.
So the technical director does not say “React everything”?
Exactly. A technical director asks: what is the product? who are the users? what are the performance expectations? how important is SEO? what is the team skillset? what is the release model? what is the security model? what devices do users use? what is the expected lifetime of the system?
Technology follows context.
2. The application shell
You mentioned “application shell”. What is that?
The application shell is the basic frame of the SPA. It is the part that loads first and remains around while different screens come and go.
It may include:
Top navigation
Left menu
User profile area
Layout container
Theme
Global loading indicator
Toast notifications
Router outlet
Global error boundary
Authentication state
In Angular, the shell may contain a router outlet:
<app-main-layout>
<router-outlet></router-outlet>
</app-main-layout>
In React, it may contain a layout route:
function AppLayout() {
return (
<>
<Header />
<SideMenu />
<main>
<Outlet />
</main>
</>
);
}
In Blazor:
<MainLayout>
@Body
</MainLayout>
The shell is important because it defines the user’s sense of being “inside the application”. In enterprise apps, the shell also handles global concerns: permissions, navigation visibility, tenant selection, notifications, and sometimes real-time updates.
3. Components: not just UI blocks, but architectural units
I understand components are reusable UI pieces, but what does an expert look for?
An expert looks at responsibility, boundaries and composition.
A component should answer one clear question: “What am I responsible for?”
For example:
CustomerDetailsPage
CustomerSummaryCard
OrdersTable
OrderStatusBadge
CurrencyAmount
DateRangePicker
ConfirmDialog
Each component should have a reason to exist. A good component has clear inputs and outputs. It should not secretly reach everywhere in the application unless it is intentionally a smart/container component.
There is a useful distinction: container components and presentational components.
A container component knows about data loading, state, routing, API calls or store interaction.
A presentational component receives data and displays it.
Example:
CustomerOrdersPage = container
OrdersTable = presentational
OrderStatusBadge = presentational
In Angular, the page component may select state from NgRx and pass data to child components.
In React, the page may use React Query, Redux or hooks, then pass props.
In Blazor, the page may inject services and pass parameters.
The pattern is the same.
Why does this matter?
Because if every component loads its own data, knows about global state, calls APIs and manages business rules, your frontend becomes a bowl of noodles. It may work for three screens. It fails at fifty.
Good frontend architecture is controlled composition.
4. Props, Inputs, Parameters and component contracts
In the previous article we said React has props, Angular has inputs, Blazor has parameters. Is there more to it?
Yes. Props, inputs and parameters are not just syntax. They are component contracts.
A component contract says:
“What data do I need?” “What events can I raise?” “What assumptions do I make?” “What can the parent control?” “What is internal to me?”
React:
<OrderStatusBadge status="Pending" />
Angular:
<app-order-status-badge [status]="order.status"></app-order-status-badge>
Blazor:
<OrderStatusBadge Status="@order.Status" />
This component should not need to know the whole order object if all it displays is status. Passing too much data creates coupling.
Bad:
<OrderStatusBadge order={order} />
Better:
<OrderStatusBadge status={order.status} />
That looks small, but at scale it matters. Precise component contracts reduce accidental dependencies.
5. State management: the heart of SPA complexity
State management still feels like the biggest topic.
It is. Most SPA complexity is state complexity wearing different clothes.
State is any data that affects the UI or behaviour of the application. In a serious SPA, state has categories.
Local UI state belongs to one component. Example: is a dropdown open? is a modal visible? which tab is selected?
Server state comes from APIs. Example: customers, orders, invoices, permissions, reports.
Global application state is shared widely. Example: authenticated user, tenant, theme, feature flags, language, global notifications.
URL state lives in the route. Example: selected customer ID, page number, search filters.
Form state is the current state of user input, validation, dirty fields, touched fields and submit status.
Derived state is calculated from other state. Example: total basket amount, filtered list, canSubmit flag.
A beginner stores state wherever it is convenient. A senior decides state ownership deliberately.
What is the rule?
Keep state as close as possible to where it is used, but no closer. If only one component needs it, keep it local. If several related components need it, lift it to their nearest shared parent. If the whole app needs it, use a shared service or store. If the URL should represent it, put it in the route/query string.
Do not put everything into a global store. That is a classic overengineering mistake.
6. React state, Angular state and Blazor state
How does this map to React, Angular and Blazor?
React has built-in local state with useState, lifecycle-style effects with useEffect, memoisation with useMemo and useCallback, Context for shared values, and ecosystem libraries such as Redux Toolkit, Zustand, Jotai, MobX, TanStack Query and others.
Angular has component fields, services, RxJS streams, signals in modern Angular, and NgRx for Redux-style architecture.
Blazor has component fields, cascading parameters, scoped services, state containers, Fluxor, and normal C# events or observable patterns.
But forget the names for a moment. The question is always:
“How does data change, and who reacts to that change?”
In NgRx:
Action → Reducer → Store → Selector → Component
↘ Effect → API → Success/Failure Action
In Redux-style React:
Dispatch action → Reducer updates store → Components select state
In a service-based Angular app:
Service holds BehaviorSubject/Signal → Component subscribes/reads → UI updates
In Blazor:
Service state changes → Component notified → StateHasChanged triggers render
Different machines, same purpose.
7. Server state is not the same as client state
What do you mean by server state?
Server state is data owned by the backend. The frontend only has a copy of it.
Examples:
Order list
Customer details
Invoice status
User permissions
Product prices
Leaderboard
Notifications
The frontend does not truly own this data. It caches it, displays it and sends commands to change it.
This matters because server state has problems local state does not:
Is it loading?
Did it fail?
Is it stale?
Should we refetch?
Can we cache it?
Can multiple users change it?
How do we handle optimistic updates?
Libraries like TanStack Query in React are popular because they treat server state as a first-class problem: caching, invalidation, refetching, loading states, retries, stale time.
Angular teams may implement similar behaviour with NgRx effects, NgRx Entity, RxJS services or newer resource/signal patterns. Blazor teams often build service-based caching or use Fluxor-like patterns.
The expert point: do not confuse “state management” with only Redux or NgRx. Server state management is its own discipline.
8. Lifecycle and rendering behaviour
Why do lifecycle methods matter so much?
Because lifecycle controls when work happens.
React uses hooks. useEffect runs after render depending on dependencies.
useEffect(() => {
loadOrders(customerId);
}, [customerId]);
Angular uses hooks such as ngOnInit, ngOnChanges, ngAfterViewInit, ngOnDestroy.
ngOnInit(): void {
this.loadOrders();
}
Blazor uses methods such as OnInitializedAsync, OnParametersSetAsync, OnAfterRenderAsync.
protected override async Task OnParametersSetAsync()
{
Orders = await OrderService.GetOrdersAsync(CustomerId);
}
The problem is not knowing the method name. The problem is understanding consequences.
If you load data in the wrong lifecycle stage, you may call APIs twice. If you forget cleanup, you may leak subscriptions. If you mutate state during rendering, you may trigger loops. If you perform expensive calculations on every render, the UI becomes slow.
What is a render?
Rendering is the process of taking application state and producing UI.
In React, state changes cause component functions to run again and produce a virtual representation of UI. React reconciles changes with the real DOM.
In Angular, change detection checks component state and updates bindings in the DOM.
In Blazor, rendering produces a render tree diff, which is applied to the browser DOM.
The vocabulary differs, but the principle is the same:
State changes → Framework recalculates UI → DOM updates
The DOM is expensive. Updating thousands of DOM nodes is slow. That is why virtualisation, pagination, memoisation and careful rendering matter.
9. Routing and navigation architecture
Routing seems simple: URL maps to page.
That is the beginner view. In enterprise SPAs, routing is architecture.
Routes define product structure, permissions, deep linking, lazy loading, breadcrumbs, navigation, analytics and sometimes feature boundaries.
A good route structure might look like:
/login
/dashboard
/customers
/customers/:customerId
/customers/:customerId/orders
/customers/:customerId/documents
/admin/users
/admin/roles
Routes should be meaningful. A user should be able to bookmark or share a useful URL. The URL should preserve important state.
For example, this is useful:
/orders?page=2&status=pending&sort=orderDate_desc
Because refresh does not lose the user’s filter.
This is weak:
/orders
where the filters live only in memory and disappear on refresh.
What about route guards?
Route guards protect user experience, not true system security. They prevent a user from navigating to screens they should not see. But backend APIs must enforce authorization.
Angular has route guards. React has protected route components or router loaders. Blazor has authorization views and route-level authorization patterns.
Senior rule:
“Never trust the SPA as the security boundary.”
10. API design for SPAs
How should APIs be designed for SPAs?
Around user journeys, not around database tables.
A beginner creates:
GET /customers
GET /orders
GET /payments
GET /documents
Then the frontend makes many calls and stitches everything together.
Sometimes that is fine. But for a dashboard, you may need a use-case endpoint:
GET /api/customers/123/dashboard
Returning:
{
"summary": {},
"latestOrders": [],
"recentPayments": [],
"alerts": []
}
This avoids chatty API behaviour.
The design choice is between fine-grained APIs and use-case APIs. Fine-grained endpoints are reusable but can create many calls. Use-case endpoints are efficient but more specific.
Technical directors think about backend-for-frontend, often called BFF.
A BFF, or Backend for Frontend, is a backend layer tailored to a particular frontend experience. A mobile app, web SPA and admin portal may have different data needs. A BFF shapes the API to the client.
For enterprise SPAs, a BFF can improve security, reduce frontend complexity, hide backend service topology, and provide screen-shaped DTOs.
11. Authentication, authorization and tokens
SPAs and authentication confuse me.
They confuse many people because there are several moving parts.
Authentication answers: “Who are you?”
Authorization answers: “What are you allowed to do?”
In SPAs, common identity technologies include OpenID Connect, OAuth 2.0, Microsoft Entra ID, Auth0, IdentityServer-style systems, cookies, JWTs, access tokens and refresh tokens.
A token is not magic. It is a security credential. If you store it badly, you create risk.
Important concepts:
Access token: used to call APIs.
ID token: tells the client who the user is.
Refresh token: used to obtain new access tokens.
Claims: facts about the user, such as user ID, role, tenant, permissions.
Scopes: permissions granted to a client/API.
CORS: browser security policy controlling cross-origin HTTP calls.
CSRF: attack where authenticated browser sessions are abused.
XSS: script injection attack that can steal data or perform actions.
Should we store JWTs in localStorage?
Carefully. Many security architects dislike storing sensitive tokens in localStorage because JavaScript can access it, and XSS can steal it. Cookie-based approaches with HttpOnly, Secure and SameSite flags can reduce some risks, but introduce CSRF considerations. There is no one-line answer. The right approach depends on architecture, identity provider, threat model, hosting and API design.
But the senior principle is clear:
“Authentication design is security architecture, not just frontend plumbing.”
12. Error handling and user experience
What about errors?
Professional SPAs treat errors as first-class UX.
Types of errors:
Validation errors
Authentication errors
Authorization errors
Network errors
Timeouts
Server errors
Concurrency conflicts
Not found errors
Unexpected client errors
A beginner shows “Something went wrong” everywhere. A senior creates an error strategy.
For example:
400 validation error → show field messages
401 unauthenticated → redirect to login
403 forbidden → show no access message
404 not found → show friendly not found screen
409 conflict → explain data changed and ask user to refresh
500 server error → show generic safe message and log details
Frontend errors should be logged. React has error boundaries. Angular has global error handlers and HTTP interceptors. Blazor has error boundaries and logging options.
HTTP interceptors/middleware-style client logic are very useful.
Angular interceptor example concept:
Add auth token
Handle 401
Log errors
Show global loader
Attach correlation ID
React apps often implement similar behaviour using Axios interceptors or fetch wrappers.
Blazor can use custom HttpClient handlers.
13. Loading states, empty states and skeletons
This sounds small, but loading states matter, don’t they?
They matter hugely. A SPA is asynchronous by nature. Data is not immediately available. So every screen needs to handle:
Loading
Loaded with data
Loaded with no data
Failed
Retrying
Partially loaded
Refreshing in background
Bad UI:
Blank page while loading
Better UI:
Skeleton loading
Clear empty state
Retry button on failure
Disable submit while saving
Optimistic feedback where safe
A professional frontend makes waiting understandable. Users tolerate delay better when the interface communicates clearly.
14. Forms: the battlefield of frontend quality
Why do forms become so hard?
Because forms combine UI, validation, business rules, state, server communication, error handling, accessibility and user psychology.
A serious form must handle:
Initial values
Dirty state
Touched state
Client validation
Server validation
Conditional fields
Async validation
Saving state
Disabled state
Reset/cancel
Unsaved changes warning
Error summary
Accessibility
Angular Reactive Forms are strong for complex enterprise forms. React often uses React Hook Form for performance and ergonomics. Blazor uses EditForm, validation components and model binding.
But framework aside, the expert rule is:
“Do not let business validation live only in the browser.”
Frontend validation helps the user. Backend validation protects the system.
15. Performance: what experts actually measure
Earlier we talked about performance. What does an expert measure?
Several things.
Initial load performance: how long before the app becomes usable?
Bundle size: how much JavaScript/CSS must be downloaded?
Time to interactive: when can the user actually interact?
API latency: how long backend calls take.
Payload size: how much JSON is transferred.
Rendering cost: how long the browser takes to paint/update UI.
Memory usage: whether the app leaks memory during long sessions.
Interaction latency: how quickly the UI responds to clicks, typing, filtering.
Common SPA performance techniques:
Lazy loading routes
Code splitting
Tree shaking
Compression
Caching
Pagination
Virtual scrolling
Debouncing
Throttling
Memoisation
OnPush change detection
Avoiding unnecessary rerenders
Optimised selectors
Image optimisation
CDN delivery
Server-side rendering where needed
Explain debouncing and throttling.
Debouncing means waiting until the user stops doing something before acting.
Example: search box. Do not call API on every keystroke. Wait 300ms after the user stops typing.
Throttling means allowing an action at most once per time interval.
Example: window resize or scroll event. Handle it once every 200ms, not 500 times per second.
And memoisation?
Memoisation means caching calculated results so expensive calculations are not repeated unnecessarily. React uses useMemo; NgRx selectors are memoised; Angular pure pipes can help; Blazor developers can reduce recalculation through careful component design.
16. Accessibility and international quality
Many developers ignore accessibility.
Then they are not senior frontend engineers.
Accessibility means people using screen readers, keyboard navigation, high contrast modes, zoom, voice control or assistive devices can use the app.
Important terms:
Semantic HTML
ARIA
Focus management
Keyboard navigation
Color contrast
Form labels
Error announcements
Accessible modals
Skip links
Screen reader support
International-level frontend engineering includes accessibility from the start. It is not polish at the end.
Also consider localisation: dates, times, currency, number formats, right-to-left languages, translation length, pluralisation.
A UI built only for one language and one screen size may fail internationally.
17. Testing strategy
How do experts test SPAs?
With layers.
Unit tests for pure functions, reducers, selectors, services and utility logic.
Component tests for UI behaviour.
Integration tests for components with services/store.
End-to-end tests for real user journeys.
Accessibility tests.
Visual regression tests where needed.
Contract tests between frontend and backend.
For React: Jest/Vitest, React Testing Library, Playwright/Cypress.
For Angular: Jasmine/Jest, Angular Testing Library, Cypress/Playwright.
For Blazor: bUnit, Playwright for end-to-end.
The expert principle:
“Test behaviour, not implementation details.”
Do not test that a private variable changed. Test that when the user clicks Save, the correct API is called, loading state appears, and success message displays.
18. Build, deployment and hosting
What happens when a SPA is deployed?
The SPA is usually built into static assets: HTML, CSS, JavaScript, images, fonts. These can be hosted on Azure Static Web Apps, Azure App Service, Nginx, CDN, S3-style storage, or served by an ASP.NET Core host.
Important deployment topics:
Environment configuration
API base URLs
Cache busting
CDN
Compression
Deep link fallback
Versioning
Source maps
Security headers
Content Security Policy
Deep link fallback is important. If the user opens:
/customers/123
the server must return the SPA index.html, and the frontend router takes over.
Without fallback, refresh gives 404.
19. Micro frontends and module federation
What about micro frontends?
Micro frontends are the frontend version of microservices thinking. Different teams own different parts of the frontend, and the app is composed from separately built/deployed frontend modules.
Useful when:
Large organisation
Multiple teams
Independent deployment needed
Clear domain boundaries
Long-lived platform
Dangerous when used too early. Micro frontends add complexity: versioning, shared dependencies, design consistency, routing integration, authentication, performance, testing, and operational coordination.
A technical director asks whether the organisation needs micro frontends, not whether the architecture diagram looks impressive.
For many systems, a modular monolith frontend is better: one SPA with clear feature modules.
20. React, Angular and Blazor: expert comparison
Give me the expert comparison.
React is flexible and ecosystem-driven. It gives you a powerful component model, but architecture depends heavily on the team’s choices. Great for teams comfortable making decisions around routing, state, data fetching, forms and build tooling.
Angular is opinionated and structured. It gives you routing, DI, forms, HTTP, RxJS and CLI conventions. It suits enterprise teams that value consistency, large-scale structure and strong TypeScript patterns.
Blazor is attractive for .NET teams because it uses C#, Razor components and .NET patterns. Blazor Server can be productive for internal apps but depends on persistent server connection behaviour. Blazor WebAssembly gives client-side execution but has payload and runtime considerations. Modern Blazor is evolving strongly, but the team must understand hosting modes and trade-offs.
Do not ask “which is best?” Ask:
Which fits the product?
Which fits the team?
Which fits the hiring market?
Which fits our backend?
Which fits our performance needs?
Which fits our security model?
Which fits our long-term maintenance plan?
That is technical director thinking.
21. Interview-level questions and expert answers
Give me serious interview-style answers.
Good.
“What is a SPA?”
A SPA is a client-side application loaded through an initial HTML shell where routing, rendering, state management and API communication are handled mostly in the browser, allowing dynamic screen updates without full page reloads.
“What are the main challenges of SPAs?”
Initial load cost, state complexity, routing, authentication, API design, performance, accessibility, SEO where relevant, error handling, bundle size, security and long-term maintainability.
“What is state management?”
It is the discipline of owning, updating, sharing and deriving data that controls UI and behaviour. It includes local state, server state, global state, URL state, form state and derived state.
“How do React, Angular and Blazor differ?”
React is a flexible UI library; Angular is a full opinionated TypeScript framework; Blazor is a .NET/Razor component framework for building interactive web UI with C#. They differ in ecosystem, rendering model, state patterns, tooling and team fit, but share SPA concepts such as components, routing, state, lifecycle and API communication.
“When should you use a global store?”
When state is shared across distant components, long-lived, complex, needs predictable transitions, debugging, caching, undo/redo, or consistent side-effect handling. Do not use it for simple local UI state.
“What is the role of a BFF?”
A Backend for Frontend shapes backend data and workflows for a specific frontend experience. It reduces chatty calls, hides backend complexity, improves security and gives the frontend screen-specific APIs.
“How do you optimise a SPA?”
Measure first. Reduce bundle size, lazy-load routes, optimise API payloads, paginate large datasets, virtualise long lists, avoid unnecessary rerenders, use memoised selectors, cache carefully, compress assets, use CDN, handle loading states, and monitor real user performance.
“How do you secure a SPA?”
Use a proper identity flow, protect API endpoints server-side, handle tokens/cookies carefully, implement route guards for UX, mitigate XSS/CSRF risks, apply CORS correctly, use security headers, and never rely on frontend-only authorization.
22. Becoming a real full stack developer
So how does this make me full stack?
Full stack is not “I know Angular and Web API.” Full stack means you understand the complete transaction from user intent to persistent data and back.
When the user clicks Save, you understand:
Button click
Form validation
Component state
Action/event
API request
Authentication token
HTTP status
Backend endpoint
CQRS command
Validation
Business rules
Database transaction
Response DTO
State update
UI feedback
Error handling
Telemetry
That is full stack.
A framework developer knows syntax.
A full stack engineer understands flow.
A technical director understands flow, trade-offs, team impact, delivery risk, security, scalability and maintainability.
Conversation summary
Let me try to summarise. A SPA is not just React, Angular or Blazor. It is a client-side application architecture where the browser runs a rich app after loading an initial shell.
Correct.
Components are not just visual blocks. They are contracts, boundaries and composition units.
Yes.
State management is the centre of SPA complexity. We have local state, server state, global state, URL state, form state and derived state.
Very good.
Routing is not just navigation. It affects deep links, permissions, lazy loading, breadcrumbs, analytics and user workflow.
Exactly.
API design must support the frontend experience. Sometimes use-case APIs or BFFs are better than making the browser stitch everything together.
Strong point.
Security belongs mainly on the backend. Frontend route guards are useful, but not enough.
Correct.
Performance means bundle size, API payload, rendering, state updates, caching, pagination and real user monitoring.
That is a senior view.
React, Angular and Blazor are different tools, but they solve similar SPA problems with different trade-offs.
Exactly. Once you understand the concepts, the frameworks become less mysterious.
So to become a true full stack developer, I need to understand the user journey end to end, from browser interaction to API, database, response, state update and UI feedback.
That is the heart of it.
The world of SPA applications is not only about building screens. It is about designing reliable, secure, fast, accessible and maintainable user experiences on top of strong backend systems.
That is why frontend engineering is now serious software engineering. Not decoration. Not just HTML. Not just JavaScript. It is architecture, product thinking, performance engineering, security awareness and human experience combined.
And when you understand that, you stop being “a backend developer who can touch Angular” and become a genuine full stack engineer.
Applying SPA Architecture in Production with Angular, React and Blazor
1. Choosing whether an SPA is appropriate
Choosing whether an SPA is appropriate matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Begin with one representative user or system scenario. Architecture becomes useful when it explains real decisions rather than presenting a catalogue of patterns.
Junior developer asks: “When is the decision to use an SPA ready for production?”
Practical exercise
Select one existing feature and create a one-page review for choosing whether an SPA is appropriate. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
2. Defining application boundaries
Defining application boundaries matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Make ownership explicit before selecting a library. Many production defects arise because two components both assume the other owns state, validation or recovery.
Junior developer asks: “When is defining application boundaries ready for production?”
Practical exercise
Select one existing feature and create a one-page review for defining application boundaries. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
3. Designing feature-oriented structure
Designing feature-oriented structure matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Prefer an observable thin slice over speculative infrastructure. Real behaviour gives the team evidence with which to refine the design.
Junior developer asks: “When is designing feature-oriented structure ready for production?”
Practical exercise
Select one existing feature and create a one-page review for designing feature-oriented structure. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
4. Planning navigation and routing
Planning navigation and routing matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Optimise for change and diagnosis. A solution is durable when another engineer can locate the rule, verify it and recover safely from failure.
Junior developer asks: “When is planning navigation and routing ready for production?”
Practical exercise
Select one existing feature and create a one-page review for planning navigation and routing. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
5. Modelling server and client state
Modelling server and client state matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Begin with one representative user or system scenario. Architecture becomes useful when it explains real decisions rather than presenting a catalogue of patterns.
Junior developer asks: “When is modelling server and client state ready for production?”
Practical exercise
Select one existing feature and create a one-page review for modelling server and client state. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
6. Handling loading and failure states
Handling loading and failure states matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Make ownership explicit before selecting a library. Many production defects arise because two components both assume the other owns state, validation or recovery.
Junior developer asks: “When is handling loading and failure states ready for production?”
Practical exercise
Select one existing feature and create a one-page review for handling loading and failure states. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
7. Designing API contracts
Designing API contracts matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Prefer an observable thin slice over speculative infrastructure. Real behaviour gives the team evidence with which to refine the design.
Junior developer asks: “When is designing api contracts ready for production?”
Practical exercise
Select one existing feature and create a one-page review for designing api contracts. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
8. Applying authentication safely
Applying authentication safely matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Optimise for change and diagnosis. A solution is durable when another engineer can locate the rule, verify it and recover safely from failure.
Junior developer asks: “When is applying authentication safely ready for production?”
Practical exercise
Select one existing feature and create a one-page review for applying authentication safely. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
9. Applying authorization in UI and API
Applying authorization in UI and API matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Begin with one representative user or system scenario. Architecture becomes useful when it explains real decisions rather than presenting a catalogue of patterns.
Junior developer asks: “When is applying authorization in ui and api ready for production?”
Practical exercise
Select one existing feature and create a one-page review for applying authorization in ui and api. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
10. Managing forms and validation
Managing forms and validation matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Make ownership explicit before selecting a library. Many production defects arise because two components both assume the other owns state, validation or recovery.
Junior developer asks: “When is managing forms and validation ready for production?”
Practical exercise
Select one existing feature and create a one-page review for managing forms and validation. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
11. Building accessible interaction
Building accessible interaction matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Prefer an observable thin slice over speculative infrastructure. Real behaviour gives the team evidence with which to refine the design.
Junior developer asks: “When is building accessible interaction ready for production?”
Practical exercise
Select one existing feature and create a one-page review for building accessible interaction. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
12. Choosing rendering strategies
Choosing rendering strategies matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Optimise for change and diagnosis. A solution is durable when another engineer can locate the rule, verify it and recover safely from failure.
Junior developer asks: “When is choosing rendering strategies ready for production?”
Practical exercise
Select one existing feature and create a one-page review for choosing rendering strategies. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
13. Controlling bundle size
Controlling bundle size matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Begin with one representative user or system scenario. Architecture becomes useful when it explains real decisions rather than presenting a catalogue of patterns.
Junior developer asks: “When is controlling bundle size ready for production?”
Practical exercise
Select one existing feature and create a one-page review for controlling bundle size. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
14. Caching and invalidation
Caching and invalidation matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Make ownership explicit before selecting a library. Many production defects arise because two components both assume the other owns state, validation or recovery.
Junior developer asks: “When is caching and invalidation ready for production?”
Practical exercise
Select one existing feature and create a one-page review for caching and invalidation. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
15. Handling optimistic updates
Handling optimistic updates matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Prefer an observable thin slice over speculative infrastructure. Real behaviour gives the team evidence with which to refine the design.
Junior developer asks: “When is handling optimistic updates ready for production?”
Practical exercise
Select one existing feature and create a one-page review for handling optimistic updates. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
16. Testing complete user journeys
Testing complete user journeys matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Optimise for change and diagnosis. A solution is durable when another engineer can locate the rule, verify it and recover safely from failure.
Junior developer asks: “When is testing complete user journeys ready for production?”
Practical exercise
Select one existing feature and create a one-page review for testing complete user journeys. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
17. Observing browser failures
Observing browser failures matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Begin with one representative user or system scenario. Architecture becomes useful when it explains real decisions rather than presenting a catalogue of patterns.
Junior developer asks: “When is observing browser failures ready for production?”
Practical exercise
Select one existing feature and create a one-page review for observing browser failures. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
18. Deploying backward-compatible releases
Deploying backward-compatible releases matters in a browser application that must coordinate navigation, identity, remote data and rich interaction over time. The objective is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows. Make ownership explicit before selecting a library. Many production defects arise because two components both assume the other owns state, validation or recovery.
Junior developer asks: “When is deploying backward-compatible releases ready for production?”
Practical exercise
Select one existing feature and create a one-page review for deploying backward-compatible releases. Include the scenario, invariant, dependency diagram, failure matrix, tests, performance evidence, security boundary, telemetry and rollback. Ask a teammate unfamiliar with the implementation to trace the behaviour. Confusion in that review is valuable evidence that the model or documentation needs improvement.
Final Perspective
The practices in this guide form a feedback loop: understand the outcome, model ownership and boundaries, deliver a narrow path, test important failure, observe the real system and refine the design. Apply the relevant chapters according to risk. The goal throughout is a maintainable user experience whose state, boundaries and failure behaviour remain understandable as the product grows.
