DEV Community

Tim Bendt
Tim Bendt

Posted on

Develop Front-end Code With a Real Rest API, Without Slowing Down to Ask for Back-end Development.

Do you ever find yourself in this situation? You're gathering requirements for a user story, you're reviewing wireframes and designs, it looks like you understand everything you need to implement a feature in the frontend code... but the API dev team isn't ready to start on the feature at the same time?

You could just delay the task for another sprint.

You could develop against a static data payload inside your project.

You could write a test api endpoint in express just for your local development. (This could be really handy for local tests too.)

In general the third option is probably the best, but what if you don't really want to deal with backend code? I suggest running a Strapi app next to your frontend project. Strapi lets you set up a new API server with almost zero configuration, and it has a very user-friendly admin visual interface for managing all the details of the API.

What is Strapi? I think of it as a cross between an MVC framework like Rails, Laravel, or ASP.Net Core – and a headless CMS like Contentful. It lets you build database schemas in a visual editor, and then you can hit rest endpoints to to do all basic CRUD as well as sorting, filtering, and pagination for those new schemas. It has support for advanced relationships between models. It also has a user account management and auth system built in. It also has email and file upload plugins that need minimal configuration to get up and running.

The speed and flexibility of a visual api editor could be perfect for rapid prototyping, and when the back-end developers need to see what the final API should look like you can point them to the schema that you built in Strapi, or share the TypeScript definitions that you exported from this Strapi project. (More on that later.)

Getting Started

First I would clone this repo https://github.com/strapi/strapi-docker and use it either as a starting point for your own project or copy the relevant pieces inside of your other front-end project.

You will need docker running locally already, I highly recommend this because it makes your dev environments portable and easily reproducible. Every other developer who downloads your repo will be able to get up to the current local dev environment with just a couple commands.

Once you've gotten that repo you can just run this command from inside the directory.

docker-compose up

It will create your new strapi app inside ./strapi-app and it will store your mongodb data inside of ./data.

You can access the admin UI at http://localhost:1337/admin.

I would recommend opening up the docker-compose.yml file and reading through it if you want to customize the names of your containers or the names of the directories they get installed into. I moved 'db' into 'data/mongodb/' and I moved 'strapi-app/' into 'cms/'.

I add these two folders into my .gitignore file.

data/*
cms/*

When you create new schemas and endpoints in the Strapi admin it actually creates new files and folders that you will need to check into Git. So add this line next in your .gitignore file.

!cms/api

Data Seeding

One other thing you may ask is how do I get my service configuration and data out of the local mongodb and let other developers import it all?

You can create scripts that export data from mongodb into json and them import it back after docker creates the containers.

I'll mount an additional filesystem point inside the mongodb config.

volumes:
      - ./data/mongodb:/data/db
      - ./seed:/data/seed

Here's my export.sh script

#!/bin/sh
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoexport -d strapi -c users-permissions_permission -o /data/seed/permission.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoexport -d strapi -c users-permissions_role -o /data/seed/role.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoexport -d strapi -c users-permissions_user -o /data/seed/user.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoexport -d strapi -c panel -o /data/seed/panels.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoexport -d strapi -c panelitem -o /data/seed/panelItems.json"

Run that and then check in the changes to any /seed/*.json files with Git so others can share your data.

When you set up the project or need to sync data you can run a script like this import.sh script.

#!/bin/sh
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoimport -d strapi -c users-permissions_permission /data/seed/permission.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoimport -d strapi -c users-permissions_role /data/seed/role.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoimport -d strapi -c users-permissions_user /data/seed/user.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoimport -d strapi -c panel /data/seed/panels.json"
docker exec project-dev-cms_mongodb_1 /bin/sh -c "mongoimport -d strapi -c panelitem /data/seed/panelItems.json"

Even if you don't rely on other teams to develop your APIs, maybe it's good to know how to do this, just so you can be your own back-end developer for smaller projects that don't require large-scale back-end development.

Getting TypeScript definitions for you Strapi Schemas

I always recommend using TypeScript. If you want to quickly get all that schema meatadata into your frontend code you can extract definitions right out of the api models.

This project – strapi-to-typescript – will scan your strapi project for the settings.json files and create .ts files with Interfaces that match, wherever you want.

It turns this:

{
  "connection": "default",
  "collectionName": "panel",
  "info": {
    "name": "panel",
    "description": ""
  },
  "options": {
    "timestamps": true
  },
  "attributes": {
    "Title": {
      "default": "",
      "type": "string"
    },
    "Instructions": {
      "default": "",
      "type": "string"
    },
    "Minifiable": {
      "default": false,
      "type": "boolean"
    }
  }
}

Into this:


/**
 * Model definition for panel
 */
export interface IPanel {
  id: string;
  Title?: string;
  Instructions?: string;
  Minifiable?: boolean;
}

Viola! 🎉


Any issues? Let me know how it goes in a comment here.

Top comments (0)