Skip to the content
Software Made Clear Diagrams that show the mechanism About

An Angular software factory, one feature at a time

Follow one Angular booking feature from agreed behaviour to reusable components, server checks and tests, then reuse the parts that should stay consistent.

8 min read Last verified September 24, 2026
ANSWER

Build one Angular feature all the way through, including the screen, server interaction and checks for the agreed behaviour. Reuse its shared components, setup and tests as a starting point, and give an AI agent a clear implementation task rather than asking it to invent the rules.

IN PLAIN TERMS

Suppose a screen lets you cancel a room booking. The button must cancel the booking you chose, wait for confirmation and explain a refusal. Once that interaction works, the next screen can reuse the dialog and test setup without copying the booking rules.

The difficult case is a click followed by a lost connection. The dialog cannot tell whether the server cancelled the booking. Before repeating this feature across screens, decide what the user sees and how the application checks the result. A component library cannot decide that policy for you.

This applies the broader software factory idea to one Angular feature. The room-booking scenario is an illustrative example. Its policy and project structure are choices for this walkthrough, not a production case or a universal Angular architecture.

Agree on what Cancel means#

Suppose a signed-in user can cancel their own room booking before it starts. For this example, the server first checks ownership. An already-cancelled booking returns its current state without performing the cancellation again. Otherwise, a booking that has started cannot be cancelled.

These rules settle the cases the screen must handle. A request to “add a cancellation dialog” leaves them undecided.

Situation Required behaviour in this example
Waiting for confirmation Name the selected booking and its time. Make keeping the booking a clear alternative.
Request in progress Show that cancellation is being sent and prevent another submission from this dialog.
Server refuses Explain the refusal without showing the booking as cancelled.
Connection is lost Say the result is unknown. Check the server state or retry using the agreed repeat-safe operation.
Cancellation is confirmed Update the booking, announce the result and return focus to the retained booking row.

A lost response is not proof that nothing happened. The server may have completed the change before the connection failed; HTTP semantics explicitly accounts for retrying an operation whose original request may have succeeded. The repeat-cancellation rule above is a deliberate part of this example’s API contract, not something a disabled button can guarantee.

Try it: choose the state after Cancel

Follow one illustrative cancellation. The screen must report the observed result, even when it cannot yet tell what the server did.

The research–plan–implement guide covers how to settle such decisions before implementation. Keep this feature brief small enough that a reviewer can compare it with the actual interaction.

Keep booking rules out of reusable components#

Angular’s style guide recommends organising code by feature area. Keep the cancellation screen, its tests and its feature-specific state near one another, rather than spreading them across application-wide folders for every file type.

Within that feature, decide which part does each job:

Part Responsibility
Application shell Start the application and connect routes to features.
Booking feature Track the selected booking, coordinate cancellation and choose which UI state to show.
Booking API adapter Send requests and translate responses into results the feature understands.
Reusable UI Provide dialogs, buttons and feedback patterns without knowing the booking policy.

These are responsibilities, not a demand for four new packages. A small application can start with feature folders. Separate libraries become useful when you need a clear public interface, independent ownership or tooling that checks imports between them.

Reusable UI does not mean “no state and no logic”. A dialog can manage focus; a menu can track whether it is open. Neither needs to fetch bookings or decide who may cancel one. Keep the cancellation screen feature-specific until another use case genuinely shares its behaviour, not merely its appearance.

In an Nx workspace, module-boundary rules can reject disallowed dependencies between projects. For example, this illustrative entry in the rule’s depConstraints array limits a project tagged layer:ui:

{
  "sourceTag": "layer:ui",
  "onlyDependOnLibsWithTags": ["layer:ui", "layer:util"]
}

A booking API project tagged only layer:data-access is outside that allowed set. With the rule enabled for the relevant files, importing it from the UI project fails lint. This is a constraint fragment, not a complete ESLint configuration. Assign the project tags and configure the remaining boundaries.

Run lint automatically for each proposed code change as part of continuous integration, or CI: the process that builds and checks changes as they are made. Check the boundary rule with a deliberately forbidden import before relying on it.

Make the difficult UI states easy to inspect#

Do not make reviewers disconnect their network or modify a database to see an error message. Give each important state a small, repeatable example with invented test data.

A Storybook story renders a component in a supplied state. For this feature, create examples for confirmation, sending, refusal, unknown outcome and confirmed cancellation. Use the same dialog and design tokens as the rest of the application. Design tokens are named values for shared choices such as spacing and colours; a new feature should not invent a second set.

Interaction tests can perform actions and check the result. Here, a test could confirm that clicking once emits the selected booking ID, and that the sending state does not emit another cancellation. Those assertions check the component contract, not the backend.

Also inspect the dialog at a narrow viewport, with a long booking name and using only the keyboard. Check where focus enters and where it returns when the dialog closes; the WAI-ARIA dialog pattern describes those expectations. A screenshot alone cannot show whether a user can operate the control.

Connect the screen to a defined API#

The reusable dialog reports an intention: cancel booking 42. The booking feature sends that intention through its API adapter. The server checks the request and changes stored state. The adapter then gives the feature a defined result, which determines what the screen shows.

Keep those steps distinct. A click is not a confirmed cancellation. A response that the feature cannot interpret is not a reason to quietly assume success.

An API description can remove some repetitive work. OpenAPI Generator’s Angular client generator produces client code from an API description. Record the schema revision, generator version and options so another developer can reproduce it. Keep application-specific response mapping outside generated files.

Generated types are not proof of a valid server response. In particular, Angular’s HttpClient documentation states that the generic response type is an assertion: the client does not check that the returned data matches it. Check fields the feature relies on at the API boundary when no other runtime validation provides that guarantee, and handle unexpected values explicitly.

Authorisation remains a server responsibility. Hiding the Cancel button or blocking a route cannot enforce ownership. Angular’s route-guard guidance makes that distinction explicit. Test the server with another user’s booking ID, not just the visibility of the button.

Give AI one clearly defined task#

Once the behaviour and boundaries are agreed, an AI agent has a concrete implementation job. It does not need to choose a new component library or reorganise the application to finish a dialog.

For a repository that already has the shared UI and API pattern, an illustrative task brief could be:

Outcome: cancel the selected booking under the agreed policy.
Start from: the existing confirmation dialog and booking API adapter.
Change: the booking feature, its adapter and their tests.
Keep: shared UI public interfaces and repository dependency rules.
Add examples: sending, refusal, lost response, confirmed cancellation.
Check: types, boundary lint, component behaviour and API integration.
Stop and ask: a policy is missing or a shared interface must change.
Report as blocked: the required test backend is unavailable.
Return: the diff, actual check results and any unverified behaviour.

Replace the descriptions with the actual file references and commands in your repository. Angular’s AI setup guidance provides framework-specific instructions, but those do not replace your installed versions, local conventions or the feature decision.

A brief is not an access-control mechanism. The environment must enforce the worker’s actual permissions. Keep consequential changes to dependencies, shared components and verification rules visible for review. A failed test is not permission to delete the assertion that exposed the failure.

Use generators for agreed, mechanical structure, such as a feature skeleton and its test files. Use AI where interpretation is still useful. The guide to deterministic steps and AI steps explains that division without making a model repeat work a script can perform directly.

Check one complete path, not just its pieces#

A component test can show that the dialog emits booking 42. An adapter test can show that a refusal becomes the expected UI result. Neither proves the running application connected those pieces correctly.

Add an integration check against a real test backend with synthetic bookings. Check ownership rejection, the time boundary and repeated cancellation. Confirm that the stored booking has the expected state. Keep those checks separate from tests that replace network responses with fixtures.

Then exercise a small browser flow: open a booking, cancel it, observe confirmation and reload to verify the displayed state. Also check a refusal through the connected application. Playwright’s guidance favours isolated tests and assertions on user-visible behaviour. Prefer finding the button by its role and accessible name over depending on a CSS class used only for layout.

For the feature to be reviewable, CI should report the relevant type checks, boundary lint, tests and application build for the proposed revision. Record failed, blocked and not-run checks as such. Review the changed shared components and the rendered feature too; a passing suite does not settle whether the wording or interaction makes sense.

Turn the working feature into a starting point#

After the feature works through the real test system, extract what the next feature should inherit: the folder pattern, component examples, API adapter shape and check commands. Keep the booking policy in the booking feature.

Automate the repeated setup when another feature needs it. A useful generator creates the expected files and registers the right checks. It should not create empty layers just to match an architecture picture. Test changes to that generator, and remember that scaffolding a new feature does not update existing ones; changes to established features need their own migration and review.

Start with the existing build and release pipeline. A monorepo, a separate deployment for every feature or several cooperating agents are not prerequisites for this workflow. Add machinery when a concrete problem justifies maintaining it.

For the next screen, reuse the checked structure and decide its business behaviour deliberately. When implementation fails a check, the builder and its repair loop explains how to return the failure to a limited repair attempt instead of restarting the whole design.

Questions people also ask

3 QUESTIONS
Does an Angular software factory require Nx?

No. Feature folders, shared components and an existing build-and-test pipeline can be enough for a small application. Nx becomes useful when separately defined projects need enforced dependency rules or coordinated tasks. Installing it does not decide the architecture for you.

Should every reusable UI component be stateless?

No. A dialog can manage focus, and a menu can track whether it is open. Keep that interaction state separate from booking policy, application-wide data and direct calls to feature-specific endpoints.

Do Storybook tests replace backend or end-to-end tests?

No. They can check rendering and interaction in the supplied scenario. A mocked successful response does not prove that a server authorises the request or stores the change. Check those behaviours against a real test backend too.

The library Browse all articles