Full-stack apps
Full-stack applications are the bread and butter of Architect. Our component framework has been designed specifically to make it as easy as possible to package up modern applications into portable, deployable units.
In this guide, you'll learn how to create and deploy an Architect Component that includes a database, a dockerized API service, and a static frontend web app.
Databases
The first building block of a full-stack web application is its database. Our full-stack app needs
to persist user data, so we'll need a reliable place to store it. Let's start by adding a database
to our architect.yml file:
databases:
main:
type: postgres:13
description: Stores user data
The above will ensure that a new database is created for your component that uses postgres version
13. It also includes a small description of what the database is used for so that production
engineering teams have some visibility into what the cloud resources in the environment are used
for.
The backend
Next up, we'll want to add our dockerized backend API. Let's start by running architect init to
bootstrap a new project using one of our favorite languages and frameworks.
$ architect init backend
This new project includes its own architect.yml, but you can delete it. This guide creates one
macro component that includes both the frontend and backend resources.
Now that you have a new backend folder with the project code, let's create the service in our root
architect.yml file. This should be the same file we added the database to.
services:
backend:
build:
context: ./backend
interfaces:
main:
port: 8080
ingress:
subdomain: api
environment:
DATABASE_ADDR: ${{ databases.main.url }}
As you can see, we also included a reference to the database inside the DATABASE_ADDR environment
variable. This uses Architect's
expression syntax to
automatically fill the value with our database address every time we deploy.
The frontend
Finally, we're ready to create our frontend. Let's run the architect init command again to create
our frontend project:
$ architect init frontend
Now that you have a new frontend folder with the project code, let's create the service for our
frontend app:
services:
frontend:
build:
context: ./frontend
interfaces:
main:
port: 3000
ingress:
subdomain: app
environment:
BACKEND_ADDR: ${{ services.backend.interfaces.main.ingress.url }}
Just like with the backend service connecting to the database, the frontend service has injected the
public URL of the backend service into itself as the BACKEND_ADDR variable.
Putting it all together
Now that we've seen the parts, let's put it all together.
name: my-component
databases:
main:
type: postgres:13
services:
backend:
build:
context: ./backend
interfaces:
main:
port: 8080
ingress:
subdomain: api
environment:
DATABASE_ADDR: ${{ databases.main.url }}
CORS_ORIGIN: ${{ services.frontend.interfaces.main.ingress.url }}
frontend:
build:
context: ./frontend
interfaces:
main:
port: 3000
ingress:
subdomain: app
environment:
BACKEND_ADDR: ${{ services.backend.interfaces.main.ingress.url }}
Did you catch the CORS_ORIGIN address in the backend service this time? Check out our guide on
configuring CORS to learn more.