How to build a NestJS MVC application with YugabyteDB
Tags: technology, tutorial, programming, productivity
Published: 2022-02-23 21:25:32

The article is the second in a series of posts investigating ways to build applications with [NestJS](https://docs.nestjs.com/). In Part 1, we built a two-factor authentication app with NestJS.

{% link https://dev.to/arctype/building-two-factor-authentication-with-nestjs-and-postgres-5f7k %}

In this article, we’ll learn more about the model view controller (MVC) architecture by building a NestJS MVC application with [YugabyteDB](https://arctype.com/postgres/connect/yugabyte-postgres). We will code an eBook store demo project. The code for this tutorial is available on my [Github repository](https://github.com/icode247/NestMVCApp). Feel free to clone it as you follow the steps. Let's begin!

## Model View Controller Design

MVC is an architectural paradigm that divides an application into three basic logical components - model, view, and controller. Each of these components is designed to handle particular parts of an application's development. MVC is a popular industry-standard web development framework for creating scalable and flexible projects. 

The three logical components of MVC are as follows:

- **Model**: Compared to the View and Controller, this level is regarded as the lowest. It represents the data that is transferred between the View and Controller components and determines the storage of all data items in the application.
- **View**: This component is in charge of the application's user interface. It also manages the end-display user's data as well as communication between the user and the controller.
- **Controller**: The controller completes the loop by receiving user input, transforming it into appropriate messages, passing them on to the views, and managing request handlers.

The MVC pattern has the following benefits:

- It allows for easy organization of large web applications
- It makes it easy to modify any part of the application without necessarily affecting other parts of the application
- It simplifies the code testing process
- It allows for easy collaboration between teams of developers
- It helps developers create easily maintained code
- It allows developers to create and use their preferred view engines

## Prerequisites

This tutorial is a hands-on demonstration. To follow along, ensure you have installed the following:

- [Arctype](https://arctype.com/)
- [NodeJS](https://nodejs.org/)
- [Yugabyte Database](https://docs.yugabyte.com/latest/quick-start/install/macos/)
- [Postman](https://www.postman.com/downloads/)

The code for this tutorial is available on my Github [repository](https://github.com/icode247/NestMVCApp). Feel free to clone it as you follow the steps.

## What is NestJS?

[NestJS](https://nestjs.com/) is a Node.js framework for creating fast, testable, scalable, loosely coupled server-side applications that use TypeScript. It takes advantage of powerful HTTP server frameworks such as Express or Fastify. Nest adds a layer of abstraction to Node.js frameworks and exposes their APIs to developers. It supports database management systems like PostgreSQL, MySQL, and in this tutorial - [yugabyteDB](https://docs.arctype.com/connect/yugabytedb). NestJS also offers dependency injections out of the box.

### Why use NestJS?

NestJS has been one of the most popular Node.JS frameworks since its release in 2017. Some of the reasons why developers use Nestjs are as follows:

- It is highly scalable and easy to maintain
- It has a large developer community and support system
- Nest has found a unique intersection of [front-end and middleware](https://stackoverflow.com/questions/636689/difference-between-frontend-backend-and-middleware-in-web-development) programming that many languages have struggled to discover
- NestJS's TypeScript support ensures that it will remain relevant in the continuously evolving JavaScript world and provides developers with fewer context shifts.
- It has comprehensive documentation
- Easy unit testing
- It is built for large-scale enterprise applications
- Nest provides an out-of-the-box application architecture that allows developers and teams to create highly testable, scalable, loosely coupled, and easily maintainable applications

## Project setup

Before we dive into coding, let’s set up our NestJS project and set up our project structure. We’ll start by creating the project folder. Open your terminal and run the following command:

```
mkdir nestmvcapp && cd nestmvcapp
```

Then install the NestJS CLI with the command below:

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

When the installation is complete, run the command below to scaffold a NestJS project.

```
nest new bookapi
```

Choose your preferred npm package manager. For this tutorial, we’ll use **npm** and wait for the necessary packages to be installed. Once the installation is completed, let's proceed by creating our database table with **Arctype**.

## Set up a YugabyteDB database

To start using the Yugabyte database in our application, we need to have it installed on our machine. Let’s see how to do this, step-by-step. First, verify you have Python.

```
# Ubuntu 20.04
sudo apt install python-is-python3
```

Then, verify you have [wget](https://www.gnu.org/software/wget/) installed. You can do this with the command below.

```
sudo apt install wget
```

Next, download and extract the Yugabyte Database:

```
# download
wget https://downloads.yugabyte.com/releases/2.11.2.0/yugabyte-2.11.2.0-b89-linux-x86_64.tar.gz

# extract
tar xvfz yugabyte-2.11.2.0-b89-linux-x86_64.tar.gz && cd yugabyte-2.11.2.0/
```

Then, configure YugabyteDB with the command below.


```
./bin/post_install.sh
```

Lastly, start your Yugabyte database.

```
./bin/yugabyted start
```

Now, we’ll connect Arctype to Yugabyte. Open **Arctype** click on the **YugabyteDB** tab, and connect to the Yugabyte database by completing the information as shown in the screenshot below:
![Screenshot of Arctype](https://arctype.com/blog/content/images/2022/02/image-40.png)

Notice that in the above screenshot, we left the database input empty. This is because we don’t have any created yet. So, let’s create one. Click on the **New Query** button and run the SQL command below:

```
CREATE DATABASE books_db;
```

![Screenshot of Arctype](https://lh5.googleusercontent.com/knkETXDwnX7_MtQpSbAOIeZtb3hjtd5Czin2q47Gl9-kGHgLOsd6smMEuP6zBrolOkPN0ON-_ZfTDiLzOYA_WxQArC_IPKFGBOwIiqGZWoU0L49LTmJRR0ZrpIds2GOBD1KOmrT2)

## Install Dependencies

With our Yugabyte database setup, let’s install the dependencies for our application. Install [typeorm,](https://www.npmjs.com/package/@nestjs/typeorm)[pg](https://www.npmjs.com/package/pg), and [ejs](https://www.npmjs.com/package/ejs) with the command below:

```
npm install --save @nestjs/typeorm typeorm pg ejs
```

This will take a little bit of time to install, so wait for it to finish. Then, we can proceed with creating our application.

## Create Books Module

A module is a class that has been annotated with the **@Module()** decorator. Nest uses the metadata provided by the **@Module()** decorator to arrange the application structure. We’ll create a **books** module with the command below:

```
nest generate module books
```

The above command will create a **books** folder in the **src** folder with a **books.module.ts** file, and register it in the root app module (app.module.ts) file.

## Create a Books Model Class

With our books module created, let’s make a model to create and read data from our database.

Create a book model class with the command below:

```
nest generate class /books/model/book --flat
```

The above command will create **model/book.ts** file in the books module directory. The --flat flag ensures the Nest will not generate a folder for the books model.

Next, let’s define our database model using **Typeorm.** We need an **id**, **title**, **author,** **quantity**, **description,** and **createdAt** fields for our books model. We’ll use the **typeorm Entity** decorator, to define our model class, **Column** decorator to define our fields, **PrimaryGeneratedColumn** to create randomly generated IDs for our books using [uuid](https://www.npmjs.com/package/uuid),and the **CreatedDateColumn decorator** to save the current date-time when a book was created. Open the **model/book.ts** file, and add the code snippet below:

```
import { Entity, Column, PrimaryGeneratedColumn, PrimaryColumn, CreateDateColumn } from 'typeorm';

@Entity()
export class Book {

   @PrimaryGeneratedColumn("uuid")
   id: number;

   @Column()
   title: string;

   @Column()
   author: string;

   @Column()
   quantity: number

   @Column()
   description: String

   @CreateDateColumn()
   createdAt: Date;
}
```

When we run our application, **Typeorm** will generate the SQL equivalent of the model, to create a book table in our Yugabyte database.

Next, we’ll connect our application to our Yugabyte database in the **src/app.module.ts** file. First, import the Nest **TypeOrmModule** module, and the **Books** model class with the code snippet below:

```
import { TypeOrmModule } from '@nestjs/typeorm'
import { Book } from './movie/model/book';
```

Then, connect to the database using the **forRoot** method with our database credentials with the code snippet below:

```
imports: [
   …
   TypeOrmModule.forRoot({
     type: 'postgres',
     host: 'localhost',
     username: 'yugabyte',
     port: 5433,
     password: '',
     database: 'books_db',
     entities: [Book],
     synchronize: true,
   }),
 ],
```

We also need to export our Books model class in our books.module.ts file, to make it accessible. First, we’ll import the **TypeOrmModule** module, and the **Books** model class.

```
import { TypeOrmModule } from '@nestjs/typeorm';
import { Book } from './model/book';
```

Then we’ll make the Book model class available using the TypeOrmModule `forFeature` method.

```
…
@Module({
 imports: [TypeOrmModule.forFeature([Book])],
 …
```

## Create Views

With our books model defined, let’s create the view for our application. Create a **Views** folder in the books module directory. We’ll create the view templates for our application, and we’ll use **ejs,** which we have installed in a previous section, as our [template engine](https://expressjs.com/en/guide/using-template-engines.html). To get started, let’s delta the boilerplate code in our **main.ts** file and the code below to configure our template engine and static files directory.

```
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
 const app = await NestFactory.create<NestExpressApplication>(
   AppModule,
 );
 app.useStaticAssets(join(__dirname, '..', '/src/public'));
 app.setBaseViewsDir(join(__dirname, '..', '/src/books/views'));
 app.setViewEngine('ejs');

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

Now, we can create our template files. We’ll start with the **header.ejs** and the **footer.ejs**, which will be created in the **books/views/partials** folder. Then will create the **books.ejs,** and **book-detail.ejs** file in the **books/views** folder. Open the **header.ejs** template and add the code snippet below:

```
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <!-- Bootstrap CSS -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
    <title>Hello, world!</title>
  </head>
  <body>
    <nav class="navbar navbar-light bg-light">
      <div class="container-fluid">
        <a class="navbar-brand">Book Store</a>
        <% if (page ==="book"){ %>
        <form class="d-flex">
          <input
            class="form-control me-2"
            type="search"
            placeholder="Search"
            aria-label="Search"
          />
          <button class="btn btn-outline-success" type="submit">Search</button>
        </form>
        <button
          type="button"
          class="btn btn-primary"
          data-bs-toggle="modal"
          data-bs-target="#staticBackdrop"
        >
          Add New
        </button>
        <% } %>
      </div>
    </nav>
  </body>
</html>
```

Our headers template will look the the screenshot below:

![Screenshot of rendered header template](https://lh5.googleusercontent.com/9_hohtOI8Jukc6y6N9CupBjTsmQ-njAn1dtnbx6x8puk0uoGm9hG8Ipemgz3Fkf7JGPSxFlYEYSoZSvcci1DoqWqVBRgCBEQeGQvqQ6GexSCiqDXc0LOhhRSOW52jlGvsWPYfCmi)

Then, open the **footer.ejs** template and reference our javascript file, and the bootstrap CDN with the code snippet below:

```
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"
></script>
<script src="/js/app.js"></script>
</body>
</html>
```

The views we created in the **header.ejs** and **footer.ejs** templates will be included in our **books.ejs** and **book-detail.ejs** templates.

Next, our **books** will have an HTML form modal to add new books to the database, and the list of all the books in our database. In the **books** template, we’ll have an input form to send a request to our backend to save a book to the database.  We’ll also include the **header** and **footer** templates in our books template. Open the **books.ejs** template and add the code snippet below. 

```
<%- include('partials/header.ejs') %>

<div class="container-fluid mt-3">
 <h4>Book Store</h4>
 <ol class="list-group list-group-numbered">
   <% books.forEach(data=>{ %>

   <li
     class="list-group-item d-flex justify-content-between align-items-start"
   >
     <div class="ms-2 me-auto">
       <div class="fw-bold">
         <a href="book/<%= data.id %>"><%= data.title %></a>
       </div>
     </div>
     <span class="badge bg-primary rounded-pill"><%= data.quantity %></span>
   </li>
   <% }) %>
 </ol>
</div>
<!-- Modal -->
<div
 class="modal fade"
 id="staticBackdrop"
 data-bs-backdrop="static"
 data-bs-keyboard="false"
 tabindex="-1"
 aria-labelledby="staticBackdropLabel"
 aria-hidden="true"
>
 <div class="modal-dialog">
   <div class="modal-content">
     <div class="modal-header">
       <h5 class="modal-title" id="staticBackdropLabel">Add Book</h5>
       <button
         type="button"
         class="btn-close"
         data-bs-dismiss="modal"
         aria-label="Close"
       ></button>
     </div>
     <div class="modal-body">
       <form action="" id="createForm" method="post" action="/movie">
         <div class="mb-3">
           <label for="title" class="form-label">Title</label>
           <input
             required
             type="text"
             class="form-control"
             id="title"
             placeholder="Javascript Cookbook"
             name="title"
           />
         </div>
         <div class="mb-3">
           <label for="author" class="form-label">Author</label>
           <input
             required
             type="text"
             class="form-control"
             id="author"
             name="author"
             placeholder="Nelson Doe"
           />
         </div>
         <div class="mb-3">
           <label for="quantity" class="form-label">Quantity</label>
           <input
             required
             type="number"
             class="form-control"
             id="quantity"
             name="quantity"
             placeholder="40"
           />
         </div>
         <div class="mb-3">
           <label for="description" class="form-label">Description</label>
           <textarea
             class="form-control"
             id="description"
             name="description"
             required
             rows="3"
           ></textarea>
         </div>
         <button type="submit" class="btn btn-primary">Add</button>
       </form>
     </div>
   </div>
 </div>
</div>
<%- include('partials/footer.ejs') %>
```

The books template will look like the screenshot below: 

![Screenshot of books template](https://lh6.googleusercontent.com/3F4-PI4wPCaFg7m6u4KiQKOD70s37OYyuv0Qtv9GHr-D0S5KtrqH273nBAr_OTDVQw6iRadjYFHfrtrkbYmPV2Vhlh-k1MgeblCtG7itRhZTqOuPPfttKGD2ZdUBXd5FOPzuW2hb)

Next, our **book-detail** template will also have a html form modal to **update** a book, and a **delete** button to delete a book from the database. We’ll also include the **header**, and the **footer** template in our **book-detail** template. Then we dynamically display the details of each book in our database. 

Add the code snippet below to the **book-detail** template:

```
<%- include('partials/header.ejs') %>
<div class="container-fluid">
 <table class="table">
   <thead>
     <tr>
       <th scope="col">Item</th>
       <th scope="col">Details</th>
       <th scope="col">Action</th>
     </tr>
   </thead>
   <tbody>
     <tr>
       <td>Title</td>
       <td colspan="2"><%= book.title %></td>
     </tr>
     <tr>
       <td>Author</td>
       <td colspan="2"><%= book.author %></td>
     </tr>
     <tr>
       <td>Quantity</td>
       <td colspan="2"><%= book.quantity %></td>
     </tr>
     <tr>
       <td>Description</td>
       <td colspan="2"><%= book.description %></td>
     </tr>
     <tr>
       <td colspan="2"></td>
       <td>
         <button
           type="button"
           class="btn btn-primary"
           data-bs-toggle="modal"
           data-bs-target="#update"
         >
           Update
         </button>
         <button
           type="button"
           class="btn btn-danger"
           onclick="deleteBook('<%= book.id %>')"
         >
           Delete
         </button>
       </td>
     </tr>
   </tbody>
 </table>
 <div
   class="modal fade"
   id="update"
   data-bs-backdrop="static"
   data-bs-keyboard="false"
   tabindex="-1"
   aria-labelledby="staticBackdropLabel"
   aria-hidden="true"
 >
   <div class="modal-dialog">
     <div class="modal-content">
       <div class="modal-header">
         <h5 class="modal-title" id="update">Update Book</h5>
         <button
           type="button"
           class="btn-close"
           data-bs-dismiss="modal"
           aria-label="Close"
         ></button>
       </div>
       <div class="modal-body">
         <div
           class="alert alert-success alert-dismissible fade show"
           role="alert"
           hidden
         >
           <strong>Succcess!</strong> Record Updated!.
           <button
             type="button"
             class="btn-close"
             data-bs-dismiss="alert"
             aria-label="Close"
           ></button>
         </div>
         <form action="" id="form">
           <div class="mb-3">
             <label for="title" class="form-label">Title</label>
             <input
               type="text"
               class="form-control"
               id="title"
               name="title"
               value="<%= book.title %>"
             />
           </div>
           <div class="mb-3">
             <label for="author" class="form-label">Author</label>
             <input
               type="text"
               class="form-control"
               id="author"
               name="author"
               value="<%= book.author %>"
             />
           </div>
           <div class="mb-3">
             <label for="quantity" class="form-label">Quantity</label>
             <input
               type="text"
               class="form-control"
               id="quantity"
               name="quantity"
               value="<%= book.quantity %>"
             />
           </div>
           <div class="mb-3">
             <label for="description" class="form-label">Description</label>
             <textarea
               class="form-control"
               id="description"
               name="description"
               rows="3"
             >
<%= book.description %></textarea
             >
           </div>
           <input type="hidden" class="" name="id" value="<%= book.id %>" />
           <button type="submit" class="btn btn-primary">Add</button>
         </form>
       </div>
     </div>
   </div>
 </div>
</div>

<%- include('partials/footer.ejs') %>
```

Our book-detail template will look like the screenshot below:

![Screenshot of book-detail template](https://lh3.googleusercontent.com/EFyO1WIz_uRrkqTWBYRO3UdhPDmpBxQd4ya1xWhQ28aPkmyHmEGdDTAmQMZeWXL1j_GARbjrMri5xWcMYQesETZRv8di40kFcoa_LmVr_BkPDoNsfQL9AI3FdSiplk2R01PEU2Lb)

Now, let’s create our static files folder to save our static (CSS, JS, and image) files. For this tutorial, we’ll only create a JS folder for our javascript code. So, create a **public** folder in the src directory, and create **js/app.js** file in the public folder. Then add the code snippet below to the **app.js** file.

```
function updateBook() {
 const createForm = document.getElementById('form');
 createForm.addEventListener('submit', async (e) => {
   e.preventDefault();
   const id = createForm['id'].value;
   await fetch(`http://localhost:3000/book/${id}`, {
     method: 'Put',
     headers: {
       'Content-Type': 'application/json',
     },
     body: JSON.stringify({
       title: createForm['title'].value,
       author: createForm['author'].value,
       quantity: createForm['quantity'].value,
       description: createForm['description'].value,
     }),
   })
     .then((data) => data.json())
     .then((res) => {
       if (res) {
         document.querySelector('.alert').removeAttribute('hidden');
         setTimeout(() => {
           window.location.reload();
         }, 3000);
       }
     });
 });
}

async function deleteBook(id) {
 console.log(id);
 await fetch(`http://localhost:3000/book/${id}`, {
   method: 'DELETE',
 }).then(() => (window.location.href = '/book'));
}

updateBook();
```

In the above code snippet, we created two functions to **update** and **delete** a book from our database. In these functions, we’ll use the Fetch API to send a request to our backend endpoint, which we’ll create later.

## Create Controller

Let's proceed with our controllers. Generate a Nest controller with the command below:

```
nest generate controller /books/controller/book --flat
```

The above command will create a **controller/book.controller.ts** file in the books module folder with some boilerplate code. Open the **controller/book.controller.ts**  file and import the necessary Nest decorators needed for our routes, import our **Book** model class, and the **BookService** class, which we’ll be creating later. Then create our **BookController** constructor method and bind our **BookService** class to make it accessible in other methods.

```
import { Controller, Render, Get, Post, Put, Delete, Param, Body, Res } from '@nestjs/common';
import { Book } from '../model/book';
import { BookService } from '../service/book.service'

@Controller('book')
export class BookController {
   constructor(private readonly bookService: BookService) {}
...
```

Next, we’ll create our **allBook** route which will listen to GET request, to render our book template using the **@Render** decorator with our books list from the database with code snippet below:

```
…
@Get()
   @Render('book')
   async allBook(): Promise<object> {
       const books = await this.bookService.getAllBook();
       return { books, page: "book" }
   }
…
```

Next, we’ll create our **createBook** route. We’ll use the **@Body** decorator to get the user's input from the request body, and the data from the request body must match the schema of the book. Then, we’ll redirect the user to the same page using the **@Res** redirect method.

```
…
@Post()
   async createBook(@Body() book: Book, @Res() res): Promise<any> {
       await this.bookService.createBook(book);
       return res.redirect('/book')
   }
…
```

Next, we’ll create the **getBook**, **updateBook**, and **deleteBook** routes. We’ll get the book’s id from the request parameters using the **@Param** decorator, and **fetch**, **update,** or **delete** the record using the id. On the **updateBook** route, we’ll also use the **@Body** decorator to get the new book details from the request body.

```
…
@Get(':id')
   @Render('book-detail')
   async getBook(@Param() params): Promise<object> {
       const book = await this.bookService.getBook(params.id)
       return { book, page: "detail" }
   }
   @Put(':id')
   async updateBook(@Param() params, @Body() book: Book): Promise<Book> {
       return this.bookService.updateBook(params.id, book);
   }

   @Delete(':id')
   async deleteBook(@Param() params): Promise<Book> {
       return this.bookService.deleteBook(params.id)
   }
}
```

## Create Service

At this point, our controller is set. Let’s set up our app service by running the command below:

```
nest generate service /books/service/book --flat
```

The above command will create a **service/book.service.ts** file in our books module folder. Now let’s create our route handler functions in the service file. First, we’ll import the following dependencies:

- Injectable: To make our **BookService** available in other files in our project.
- HttpException: To create custom HTTP Errors
- HttpStatus: To send custom status code
- InjectRepository: To inject our **Book** model class to our **BookService.**

We'll also import our book model class. Do this with the code snippet below:

```
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'
import { Repository } from 'typeorm'
import { Book } from '../model/book';
```

Next, we’ll add a constructor method to our **BookService** class. Inject our Book model with code snippet below:

```
...
constructor(@InjectRepository(Book) private readonly bookRepository: Repository<Book>) { }
...
```

Then, we’ll create the **getAllBooks**, and **createBooks** handler functions. The getAllBooks handler will query the database for all the books in the database and return them in descending order to our controller. While the **createBook** handler will create a new with the data in the book object using the **save** method.

```
…
async getAllBook(): Promise<Book[]> {
       return await this.bookRepository.find({ order: { createdAt: "DESC" } })
   }

   async createBook(book: Book): Promise<Book> {
       return await this.bookRepository.save(book)
   }
…
```

Last, we’ll create the **getBook**, **updateBook**, and **deleteBook** handlers with code snippet below. These handlers will use the id of the book to get, update or delete a book from our database.

```
…
async getBook(id: string): Promise<Book> {
       return await this.bookRepository.findOne(id);
   }
   async updateBook(id: string, book: Book): Promise<Book> {
       const updateBook = await this.bookRepository.update(id, book)
       if (!updateBook) {
           throw new HttpException('Book id not found', HttpStatus.NOT_FOUND)
       }
       return await this.bookRepository.findOne(id);
   }
   async deleteBook(id: string): Promise<any> {
       if (await this.bookRepository.delete(id)) {
           return null
       }
       throw new HttpException('Book not found', HttpStatus.NOT_FOUND)
   }
```

## Conclusion

Through this tutorial, you've learned how to structure a NestJS MVC application with a Yugabyte database by building a book store demo project. You've learned what the MVC architecture is, how to set up a NestJS application, and how to set up and create a Yugabyte database.  For further reading, you can also read more about[ NestJS](https://docs.nestjs.com/) and [YugabyteDB](https://arctype.com/postgres/connect/yugabyte-postgres). For an extra challenge, you can extend the application by protecting the delete and update routes. What will you build next?