Original cover photo by Janko Ferlič on Unsplash.
The role of documentation
Documentation tends to receive little attention from software developers. While well-known open source libraries often ship with comprehensive doc sites, demos, and even interactive sandboxes, many other projects — particularly enterprise applications — frequently end up with no documentation at all. Let's consider the consequences of this oversight:
- Slower onboarding: For new hires, having existing docs on hand can dramatically cut down the time spent explaining what each module does and how the system fits together.
- Friction for experienced developers: It is common to inherit code written by someone else. When that code is accompanied by clear examples and guidance, development moves faster. Without such context, misunderstandings can lead to delays or even defects.
- Challenges with stakeholders: When managers or product owners request changes, they often ask how current features behave, or they want to know how certain edge cases or permissions are handled. Maintaining written reference material makes answering these questions straightforward.
With that context, let's first establish what good documentation looks like in any project — not just Angular — and then look at specific tooling and practices for documenting Angular apps.
Guidelines for writing documentation
Based on my experience, documentation is its own discipline and works best when it follows clear principles. Here are several rules worth following:
- Document unusual behavior and quirks: when a part of your application behaves unexpectedly, or when the code is structured in a non-obvious way due to a business constraint, make sure that is recorded in the docs.
- Keep documentation adjacent to the code it describes: in Angular projects, JSDoc comments placed above components or pages keep explanations right where they are needed.
-
Resist overdocumentation: there is no need to describe every class property, especially when the name already makes it obvious. A field like
isDialogVisible: booleanspeaks for itself — focus instead on the parts that could be misread. - Use generators for documentation sites: for larger codebases, a dedicated documentation portal is a good practice and speeds up onboarding considerably.
- Choose precise, straightforward wording: avoid artistic language; aim for short, clear explanations of what a code block actually accomplishes.
- If you use pull requests or peer review, include documentation review in your process; ensure that someone unfamiliar with the work can follow the written explanation.
- Show examples! They are invaluable for reusable functions or components, offering a quick starting point for other developers.
With these principles in mind, let's move on to documenting Angular projects.
Documentation for Angular applications
What to document?
Before anything else, it's worth clarifying what actually warrants documentation. Let's set aside the elements that are generally self-explanatory and don't require extra commentary:
- Modules in general, especially feature modules. Names like
UsersModuleorDocumentsModuleare typically self-explanatory, so there's no need to invest time describing them in detail. - API calls in service methods. These sections of code are usually very explicit. Consider the following example; the purpose of each method is immediately clear, and you'll likely have dozens or hundreds of similar cases across your codebase:
@Injectable()
export class UsersService {
constructor(private readonly http: HttpClient) {}
getUserById(id: number) {
return this.http.get<User>(`api.ourprojectapi.com/users/${id}`);
}
}
- Business logic related models and classes: once again, these tend to be fairly readable on their own. There's little need to elaborate on what a
UserModelrepresents, unless there's some particular subtlety involved. - Enums, unless the names are ambiguous (in which case it's worth first checking whether the naming itself could be improved).
- When using third-party state management libraries (such as NgRx or NgXs), documenting standard boilerplate like reducers or actions is unnecessary. However, certain elements, like Effects in NgRx, may benefit from some clarification in specific contexts.
Now, let's look at the parts that genuinely deserve documentation:
- Business logic (often called container) components, which handle data retrieval, form creation, DOM updates, and so on. Describe what these components are responsible for and where they're used. For page components backed by routes, it's helpful to note which route points to them, what parameters they consume, and whether any resolved data is involved.
- Reusable components: these deserve extensive documentation, since other developers will rely on them without necessarily understanding their internal workings. Document the emitted events and include usage examples. Take a look at this case; the component's function should be obvious at a glance:
/**
* This component displays a loading spinner over a block of content,
* in a dimmed overlay. Content inside the component is projected,
* and a boolean Input `loading` displays the spinner at will.
* Projected content is blocked from interaction when `loading`
* is set to `true`
*
* Usage example:
* @example
* <app-loader [loading]="loading">
* <div>
* Content goes here
* </div>
* <button (click)="loading = true; getContent()">
* Get new content
* </button>
* </app-loader>
*/
@Component({
selector: 'app-loader',
template: `
<div #wrapper [class.loading]="loading">
<ng-content></ng-content>
<div class="blocker" *ngIf="loading">
<loader-icon></loader-icon>
</div>
</div>
`
})
export class Loader {
@Input() loading = false;
}
- Business logic related pipes. For instance, here's a pipe that checks whether an item is pinned to the top of the screen when it matches another specific item:
/**
* This pipe takes a look at a list of items
* (Orders, Shipments or Products)
* and determines if it contains items that match with
* those in an AssignmentList,
* so that it can be displayed
* as pinned at the top of the page
*
* @example
* <!-- in Order List page, for example -->
* <div>{{ products | isPinned : currentAssignment }}</div>
*/
@Pipe({
name: 'isPinned',
})
export class IsPinnedPipe implements PipeTransform {
transform<T>(
items: { propertyName: T; id: number }[],
item: T,
): boolean {
return items.some(i => i.propertyName === item);
}
}
- Custom services and their methods. A utility service with generic methods, or wrappers around native functionality, deserve thorough documentation. For example, if you have a
LocalStorageService, make sure it's well covered. - Error cases whenever relevant. If a method makes an API call that could fail in multiple ways, be sure to note that in the method's description.
Naturally, this list isn't meant to be exhaustive, but covering at least these points can save a lot of time and frustration.
Next, let's consider how the documentation should be written.
How to document
Writing documentation shares many similarities with writing an essay or article, although here the goal is to be even more concise and precise. Here are some guidelines that tend to help:
- Keep it brief: if there's too much text, developers will start glossing over details that might be crucial.
- Use straightforward language: this isn't about impressing anyone, documentation is a practical guide, not a literary piece.
- Leverage JSDoc annotations such as
@descriptionand@example. - Incorporate links where they add value. For instance, when working with a third-party component, linking to its official documentation can be immensely helpful.
- Always include examples when applicable. Show how something works in practice rather than just describing it.
The first important step is creating a README page. This serves as both the entry point for new developers and as an onboarding guide. Outline what the project does, which tools are used, installation and run instructions, the app's main building blocks, and any other essential details developers should know from the start.
If you're documenting a project for the first time, it's a smart idea to browse the documentation of popular frameworks and libraries to see how they approach it. For example, the documentation sites for RxJS, NgRx, and Angular itself are excellent references for improving your own documentation skills.
Take, for instance, the documentation page for the map operator in RxJS. It opens with a short description, then lists parameter and return types (which can be automated, more on that later), provides a detailed explanation with an illustration, and wraps up with an example and references to related concepts. While you usually don't need this level of sophistication, especially in enterprise settings, it's a solid structure to model your own documentation after.
What tools to use
Eventually, you'll likely want to turn your JSDoc annotations into a full-fledged documentation website. This is something you can share with new team members instead of handing over lengthy Word documents, and it gives your team a searchable resource for explanations and guidance during development. Fortunately, there are excellent tools that make building such sites a matter of running a single console command. Today, we'll explore Compodoc, a documentation generator built specifically for Angular projects (it also supports Nest and Stencil, but our focus here is Angular).
Let's give it a try and generate a documentation site from an Angular project. If you have an Angular app handy on your machine (maybe a side project), just follow these steps:
Note: even if your app has zero documentation, Compodoc will still generate a website that lists all components, directives, services, pipes, and so on, along with their inputs, outputs, method parameter names, and types. What's missing are the detailed descriptions, which we'd need to provide ourselves via JSDoc annotations.
- Install Compodoc globally with
npm install -g @compodoc/compodoc - Create a file called
tsconfig.doc.json, with an include key that points to thesrcfolder. - Optionally, you can add a script to your
package.jsonfile that builds the documentation website:
"scripts": {
"compodoc": "npx compodoc -p tsconfig.doc.json"
}
- Now run it with
npm run compodoc
This command produces a documentation folder in your app's root directory — that's your documentation website. It should also open automatically in your browser, so you can see what was generated.
There are several demo documentation sites created with Compodoc that you can browse, like this Angular app Documentation Demo.
You can further tailor your documentation experience by:
- Excluding certain files or types of files from the docs if they're not needed
- Enriching content with descriptions and examples via JSDoc annotations
- Checking the documentation coverage page to gauge how much of your project is documented
- Perhaps choosing a theme and style for your documentation site
- Adding extra external documentation files
- Enabling syntax highlighting for code examples
- And plenty more
In Conclusion
Documenting software is as old a practice as writing software itself. Some teams skip it altogether, but more often than not, that decision leads to complications down the road, particularly as teams expand. Hopefully, this article has given you some insight into how to start documenting your projects, improving your overall development experience.
