Adding live documentation to YOUR REST API with Swagger and Nest.js
Tags: javascript, tutorial, showdev, nest
Published: 2019-07-01 12:04:19

---
title: Adding live documentation to YOUR REST API with Swagger and Nest.js
published: true
description: APIS should be documented. The challenge is ensuring the docs and the API are in sync. With Swagger that's a reality
tags: javascript, tutorial, showdev, nest
cover_image: https://thepracticaldev.s3.amazonaws.com/i/q22fntcsk2gjj5asrdmu.jpg
---


> We'll want to document our code and our APIs. What's stopping us is usually time or that we know that the documentation and the actual code will drift and that's just worse than no documentation at all. So we need something that changes with us, that something is Swagger, the fact that it enables you to run queries against it is an added bonus.

This is what it can feel like sometimes with documentation. You spend all this time writing documentation and then someone, might be you, might be your colleague does a change and suddenly, you are out of sync, feels like a struggle, no?

![](https://thepracticaldev.s3.amazonaws.com/i/fj8sdvl2b2mcw6exavkm.gif)

Swagger is live documentation though, it changes as the code changes. So hopefully you will give it a shot after reading this article.


In this article, we will show how easy it is to set up Swagger in your Nest.js app. It's just one config place and a few DTOs that needs documenting. 

We will show the following:

- **Scaffolding** a Nest.js app and some needed artifacts like modules, services, DTOs
- **Setting up** Swagger and see how easy it is to get your endpoints documented
- **Exploring** Swaggers features like executing queries and inspect results
- **Improving** our documentation even more by adding decorators to our DTOs.

## Resources

- [The Swagger specification](https://swagger.io/specification/)
- [Tutorial on Swagger + Nest.js](https://docs.nestjs.com/recipes/swagger)
- [My first Nest.js API](https://dev.to/softchris/nest-creating-a-rest-api-has-never-felt-so-good-4i1)
- [Nest.js + GraphQL](https://dev.to/azure/how-you-can-use-nest-to-build-a-graphql-api-24ii)

## Scaffolding our Nest.js project

Let's create a new Nest.js project by using the excellent Nest CLI. If you haven't got it installed go and do so by running the following command in the terminal:

```
npm i -g @nestjs/cli
```

> Done?

Ok, good. Let's continue.  

To create a nest project we just have to call `nest new [project name]` so lets do just that:

```
nest new swagger-demo
```

It should look like this:

![](https://thepracticaldev.s3.amazonaws.com/i/8kc6o2sr5tjsq8tkykjk.png)

Next step is to set up a route. Let's do this in a modular way and create a module, service and a DTO. Lots of typing you say? No not really as we are using the CLI. Let's check what the CLI can do with:

```
nest --help
```

![](https://thepracticaldev.s3.amazonaws.com/i/wzvav90m32ubo0byp81x.png)

It's telling us to type pretty much:

```
nest generate|g [options] <schematic> [name] [path]
```

Sounds a bit cryptic but to create a module we would need to type:

```
nest g mo cats
```

![](https://thepracticaldev.s3.amazonaws.com/i/uccd0brl3bmo56k00ll7.png)

We need a controller as well that will respond to our requests. So that would be:

```
nest g co cats
```

![](https://thepracticaldev.s3.amazonaws.com/i/vxtkbnvfiuhjqcoc6zgj.png)

For a service we would type:

```
nest g s cats
```

![](https://thepracticaldev.s3.amazonaws.com/i/42rw2e2g9fgjdy0kpeyw.png)

Note two things about the controller + service creation. They are created under the `cats` directory, they come with tests :) and they have both registered themselves with the module, look at the `UPDATE` row at the bottom row.

Lastly, we want to create a DTO, a data transfer object that will hold our properties. We do that by typing the following:

```
nest g cl cat cats
```

Before we run this let's discuss what we are typing. We are saying to create a class `cl`, called `cat` under path `cats`. We do this to ensure that all related things end up in one place.

![](https://thepracticaldev.s3.amazonaws.com/i/ss0lyk0s5m4d696cntdp.png)

## Making the route work

So far we have a bunch of files, but we need the route to work so we need to do the following:

1. Add `id` and `name` to our cat model
2. Ensure the Service has a `getCats()` method that returns a list of cats
3. Make the controller inject the `cats` service and call `getCats()`
4. Take our API for a spin and ensure `/cats` work

### Adding `id` and `name` to our Model

Ensure `src/cats/cat.ts` looks like this:

```ts
export class Cat {
  id: number;
  name: string;
}
```

### Update our Service
We need to add two methods `getCats()` and `createCat()`, this will ensure once we add Swagger on this that we have a `GET` and a `POST` request.

```ts
import { Injectable } from '@nestjs/common';
import { Cat } from './cat';

@Injectable()
export class CatsService {
  cats: Array<Cat> = [{ id: 1, name: 'Cat'}];

  getCats() {
    return this.cats;
  }

  createCat(cat: Cat) {
    this.cats = [ ...this.cats, {...cat}];
  }
}
```

### Make Controller use the Service

Our controller should look like this:

```ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './cat';


@Controller('cats')
export class CatsController {
  constructor(private srv: CatsService) {}

  @Get()
  getCats() {
    return this.srv.getCats();
  }

  @Post()
  createCat(@Body() cat: Cat) {
    this.srv.createCat(cat);
  }
}
```

The above simply ensure we are using our `CatsService` for either getting a list of cats or for adding a cat.

### Take it for a Spin

We need to ensure our route works before we start showing Swagger. So run:

```
npm start
```

and head to the browser on `http://localhost:3000/cats`. It should look like so:

![](https://thepracticaldev.s3.amazonaws.com/i/yj0gp7z63mjslhdctf4t.png)

## Adding Swagger

Now we will add Swagger. To get Swagger to work we need to do the following:

1. **Install** the needed dependencies
2. **Configure** our bootstrap to start using Swagger
3. **Ensure** Swagger is rendering in the browser

### Installing Swagger

We need to install through the NPM with the following command:

```
npm install --save @nestjs/swagger swagger-ui-express
```

That should set us up nicely, now to our next step, configuring it.

### Configuration

Head to `main.ts` our bootstrap file. In our `bootstrap()` method it currently looks like so:

```ts
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  await app.listen(3000);
```

We need to add the following between us declaring `app` and calling `listen()` on it, namely:

```ts
  const options = new DocumentBuilder()
    .setTitle('My API')
    .setDescription('API description')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('api', app, document);
```

First, we create an `options` object that gets a `title`, `description`, `version` and finally we call `build()` which ends up creating an options object. Thereafter we create a document instance by calling `createDocument()` on a `SwaggerModule`. It takes our `app` instance and the `options` object we just created. The last thing we do is calling `setup()` on the SwaggerModule. The first argument is a path, which means we will found our API docs under `http://localhost:3000/api`. The next argument is our `app` and the last argument is the document instance. Our `main.ts` should now look like this in its entirety:

```ts
// main.ts

import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const options = new DocumentBuilder()
    .setTitle('My API')
    .setDescription('API description')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, options);
  SwaggerModule.setup('api', app, document);

  await app.listen(3000);
}
bootstrap();
```

### Trying out the docs
Lets first start up our app 

```
npm start
```

Thereafter head to `http://localhost:3000/api`. Then you should see the following:

![](https://thepracticaldev.s3.amazonaws.com/i/9ivv70nih6qmmoim24kh.png)

This is as expected. We have the default route `/` set up in the `app.controller` file. We also have a `GET` for `/cats` and a `POST` also for `/cats`. So far so good.

The million dollar question then, does it work? Well, let's start with `GET ` and `/cats`

![](https://thepracticaldev.s3.amazonaws.com/i/ajxumo1mfkxwi3x73tpb.png)

Click the `Try it out` button. At this point, it will show the `Execute` button, click that as well. It should give you the below

![](https://thepracticaldev.s3.amazonaws.com/i/rixc3e6m5ha0q8cukprp.png)

It answers with our list of cats. We also get a nice `cURL` version, if we want to use that instead. We can also see the exact response headers we get back, should we want to verify that.

What about our POST request? Well, let's click that instead and our `Try it out `. 

![](https://thepracticaldev.s3.amazonaws.com/i/d6d2srnzim2mulf0us6a.png)

We get a big edit window in which we type some JSON that corresponds to a new cat we want to create so:

```json
{
  "id": "2",
  "name": "cat2"
}
```

Hitting our `Execute` button gives the below response:

![](https://thepracticaldev.s3.amazonaws.com/i/fqvej4ffjc1xtz3o4rtl.png)

As you can see we get a `201`, which means we have a new cat. Lets ensure that is the case by hitting our  `GET` `/cats` in Swagger: 
 
![](https://thepracticaldev.s3.amazonaws.com/i/fc1waiyhsh3ttkx6quht.png)

Success, there are now two cats. Let's look at how we can improve next.


## Improve our docs

If we scroll to the bottom of our Swagger docs page we have a category `Models`. It contains `Cat` our DTO class. It's completely empty though and that makes for sad reading. We can easily fix this though.

![](https://thepracticaldev.s3.amazonaws.com/i/a3mvfay2bc5vcmt7v6ac.png)

What we need to do is to use the decorator `@ApiModelProperty()` and apply those to every property of `Cat`, like so:

Your `cats/cat.ts` should now look like this:

```ts
import { ApiModelProperty } from "@nestjs/swagger";

export class Cat {
  @ApiModelProperty()
  id: number;

  @ApiModelProperty()
  name: string;
}
```

Let's our app again:

```
npm start
```

and go to `http://localhost:3000/api` and scroll to the bottom:

![](https://thepracticaldev.s3.amazonaws.com/i/md95mt3s0vrlajomdcwq.png)

There we are, now our class properties are included in the docs as well

## Summary

That's it. We got a chance to use lovely Nest again. This time we used a few more commands to learn to scaffold all the files we needed. Most of all we learned how to document our API with Swagger. Documentation that changes as the code changes are worth keeping around. So gift your API some docs as well.