16 November 2023
Our Guide to Seamless Project Documentation

DOCS

At the heart of every successful project lies robust documentation that not only serves as a roadmap for the project, but also eases the learning curve for newcomers. The essence of good documentation is about providing a clear pathway through the configurations and conventions that shape the project. Today, we're giving you an insight into how our internal tech documentation serves as the backbone of our developmental process.
Bartłomiej Stefański
Bartłomiej Stefański
Head of Engineering
Our Guide to Seamless Project Documentation

Readme Documentation

The README is a crucial part of any project. It should be succinct yet loaded with all the frequently needed information, acting as the gateway to understanding our projects.

Each README within our ecosystem should consistently feature these important sections:

Setup and Installation

In this section, provide comprehensive instructions on how to install and run the project locally. It should cover the process of cloning the repository, installing the necessary dependencies, and any command line instructions for executing the project.

Configuration

Elaborate on how to configure the project. Include any information necessary for:

  • configs,
  • environment variables,
  • and database dumps.

If there's an .env file or a config directory, make sure to mention it here and include instructions on how to get it.

Resources

Highlight useful links that directly pertain to the project, such as:

  • The project's documentation tool (e.g., Confluence).
  • The project's Kanban board (e.g., JIRA) for tracking progress and tasks.
  • CI/CD badges and links (like Jenkins, GitHub Actions, Gitlab Pipelines) to quickly navigate to the CI/CD pipelines.
Docs

Troubleshooting & Known Issues

The Blazity team began with a comprehensive audit of the current solution's functionality and the entire content creation process through workshops and interviews with key stakeholders. They decided to redesign the data architecture and develop a new front end using a new technology stack. The team recommended migrating to a headless architecture with Next.js for the front end and Builder.io as the content management system (CMS).

Git Convention

Detail the Git conventions followed in the project. This could include information on whether conventional commits are being used, the tense to be used in commit messages, and the rationale behind the chosen approach (if necessary).

Testing

Outline the testing methodologies adopted in the project. Information about the types of tests, expected coverage, and methodologies such as GWT (Given When Then) or AAA (Arrange Act Assert) should be covered. In cases where tests are not applicable to the project (like purely visual projects), explicitly state this.

File Structure and Infrastructure Overview

Give a basic description of the file structure, focusing on what a new developer needs to know to start working. If the project uses cloud or third-party services and the infrastructure is different than a usual standard project, provide a simple graph showing how components connect to each other.


Tools like the ones listed below can be used to create these graphs:

External Documentation

There are aspects of the project that require a more detailed form of documentation. These include elements that discuss in-depth architectural choices, extensive coding style guides, or major project decisions. For these, an external documentation platform such as Confluence is more suitable. This platform allows for better organization of complex information, collaborative editing, and structured layout, which are essential for navigating larger projects

ADRs

ADRs, or Architecture Decision Records, serve as documentation of important architectural choices made during a project. They provide an understanding of the context, decision, and consequences of choosing one solution over another. While not frequently referenced in day-to-day development, they become crucial when troubleshooting issues or making further architectural decisions. Given the fact that they are not referenced often, it's practical to host ADRs on an external platform like Confluence.

Architecture Specs

When a project is large, the basic information in the README might not be enough. You may need to create more detailed architectural diagrams and specs. These documents could provide a deeper look into the system, show how different parts interact, and give complete technical details. These documents are often too detailed for a README. It's better to put them on a platform like Confluence. This way, the README stays easy to understand, while more detailed information is available for those who need it

In-Code Documentation

Backend API Docs

When it comes to documenting backend APIs, OpenAPI is a reliable tool. We typically utilize an implementation like Swagger (+ UI) for REST and GraphQL APIs. It provides a UI to interact with the API and understand its functionalities. This form of in-code documentation is essential when we have a dedicated backend team and the APIs are complex enough to warrant such documentation.


However, if we are creating a simple pseudo-backend with Next.js API routes, such detailed documentation may not be required. The focus should be on making the code as readable and easy to understand as possible.


When working with other types of APIs like gRPC or tRPC, other forms of documentation may be necessary. Since OpenAPI is limited to REST and GraphQL, additional tools or methodologies may be required to adequately document these systems.

Utility and Type Docs

To maintain clarity and readability in our codebase, we employ JSDoc format to document utility/helper functions and global TypeScript types. This form of documentation is key to understanding how these utilities work and how to use them.

You may wonder why we need JSDocs when we already have TypeScript. The answer lies in the self-documenting nature of code.

Global functions or types often have short names, which is expected and good practice. However, these concise names can sometimes affect the self-documenting aspect of the code. By using JSDoc format, we can provide detailed descriptions, parameter explanations, and return value information that TypeScript alone may not convey.

Additionally, JSDoc comments can serve as the foundation for generating web-based documentation. Tools like TypeDoc can extract JSDoc annotations from our code and generate interactive documentation that helps developers understand the utilities and types we've defined.


  1. For example, consider a global TypeScript type .d.ts file:

Code

1declare global { /** * Defines the Optional type which allows properties of T to be optional. * * @template T - The type for which properties are made optional. * @template K - The set of keys within T that should be optional. * * @typedef {Object} Optional * @property {Partial<T
2  >} Pick<Partial<T
3    >, K> - A new object with all properties of T being partially optional. * @property {Omit<T, K
4      >} Omit<T, K>
5        - A new object with all properties of T except those in K. */ type Optional<T, K extends keyof T>
6          = Pick<Partial<T>, K> & Omit<T, K> }</T,></Partial<T></T,
7        ></T,
8      ></T,
9    ></Partial<T
10  ></T
11>
12

And a utility function:TypeScriptCopy

Code

1/**
2 * Approximates the integral of a function using Simpson's rule.
3 * Simpson's rule is a numerical integration technique that approximates the integral of a function by
4 * dividing the area under the curve into a series of trapezoids and using a quadratic polynomial to
5 * approximate the shape of each segment. It provides a more accurate approximation compared to simpler
6 * integration techniques like the trapezoidal rule.
7 *
8 * @param {Function} f - The function to integrate.
9 * @param {number} a - The lower limit of integration.
10 * @param {number} b - The upper limit of integration.
11 * @param {number} n - The number of intervals for integration.
12 * @returns {number} The approximate value of the integral.
13 */
14function approximateIntegral(f, a, b, n) {
15   const h = (b - a) / n;
16  let sum = f(a) + f(b);
17 
18  for (let i = 1; i < n; i += 2) {
19    const x = a + i * h;
20    sum += 4 * f(x);
21  }
22 
23  for (let i = 2; i < n - 1; i += 2) {
24    const x = a + i * h;
25    sum += 2 * f(x);
26  }
27 
28  return (h / 3) * sum;
29}
30 
31// Rest of the code...

By providing detailed JSDoc comments like this, we enhance the readability and maintainability of our codebase. The documentation also serves as a reference point for developers who interact with these utilities and types.


Remember that proper in-code documentation, in the form of JSDoc comments, makes our codebase more self-explanatory and enables the generation of user-friendly documentation when needed.


Keep in mind, going overboard with it can backfire, since after all, they're just comments with their own set of downsides.


That's the long and short of how we dodge project chaos with our doc guidelines. It’s like having a friendly chat with every new project and getting to know each other before things get serious. Hopefully, our approach sparks some fresh ideas for handling your own project documentation.

blazity comet
Get a quote
Empower your vision with us today
The contact information is only used to process your request. By clicking send, you agree to allow us to store information in order to process your request.