A First Look at Architect
Tags: aws, cloudformation, architect, lambda
Published: 2021-05-15 04:19:22

---
canonical_url: "https://ajcwebdev.com/first-look-architect/"
description: "Architect is an Infrastructure as Code framework for provisioning build artifacts."
---

## Outline

- [Introduction](#introduction)
- [Setup](#setup)
  - [Install Architect CLI and AWS SDK](#install-architect-cli-and-aws-sdk)
  - [Initialize Project](#initialize-project)
  - [Start Development Server](#start-development-server)
- [Project Structure](#project-structure)
  - [Arc App Entry Point](#arc-app-entry-point)
  - [Arc Configuration](#arc-configuration)
  - [Lambda Handler](#lambda-handler)
  - [Create an About Page](#create-an-about-page)
- [Deploy to AWS](#deploy-to-aws)
  - [Deploy to Staging Environment](#deploy-to-staging-environment)
  - [Deploy to Production Environment](#deploy-to-production-environment)

> ___All of this project's code can be found in the [First Look monorepo](https://github.com/ajcwebdev/a-first-look/tree/main/deployment/architect/) on my GitHub.___

## Introduction

[Architect](https://arc.codes/) is an Infrastructure as Code framework for provisioning build artifacts. Architect defines a high level manifest file in multiple open text formats which can be checked into version control. It compiles the manifest code into AWS CloudFormation and then deploys that stack. Supported formats include:
* a native text file format `app.arc`
* `package.json`
* `arc.json`
* `arc.yaml`
* `arc.toml`

## Setup

### Install Architect CLI and AWS SDK

```bash
npm i -g @architect/architect aws-sdk
```

Check `arc` version.

```bash
arc version
```

Output:

```
      Version: Architect 8.5.11
 Installed to: /opt/homebrew/lib/node_modules/@architect/architect
          cwd: /Users/ajcwebdev
```

### Initialize Project

Create a project directory and initialize a project with `arc init`. 

```bash
mkdir ajcwebdev-architect
cd ajcwebdev-architect
arc init
```

Output:

```
     Version ⌁ Architect 8.5.11
         cwd ⌁ /Users/ajcwebdev/ajcwebdev-architect

✓ Create Created Architect project manifest (app.arc)
✓ Create Created new project files in src/http/get-index/
⚬ Create Installing Architect...

added 264 packages, and audited 265 packages in 16s

25 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

✓ Create Your Architect project is ready! Get started with: npx arc sandbox
```

Running `arc init` in an empty directory creates a default `app.arc` manifest file named after that directory with one default function `src/http/get-index`.

### Start Development Server

Architect projects work locally and offline. `arc sandbox` emulates most app resources defined in `app.arc`:

```bash
arc sandbox
```

```
         App ⌁ ajcwebdev-architect
      Region ⌁ us-west-2
     Profile ⌁ default
     Version ⌁ Architect 8.5.11
         cwd ⌁ /Users/ajcwebdev/ajcwebdev-architect

✓ Sandbox Found Architect project manifest: app.arc
✓ Sandbox No testing environment variables found
✓ Sandbox Project files hydrated into functions
✓ Sandbox Loaded routes (HTTP API mode / Lambda proxy v2.0 format)
    get / ................................. src/http/get-index

    http://localhost:3333

✓ Sandbox Started in 8ms
❤︎ Local environment ready!
```

![01-arc-hello-world-nodejs-localhost](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6f38lacrcto5hyrvdwdr.png)

## Project Structure

```
├── src
│   └── http
│       └── get-index
│           ├── config.arc
│           └── index.js
├── app.arc
├── package-lock.json
└── package.json
```

`package.json` contains a single `start` script and the Architect development dependency.

```json
{
  "name": "ajcwebdev-architect",
  "version": "0.0.0",
  "description": "A fresh new Architect project!",
  "scripts": {
    "start": "npx sandbox"
  },
  "devDependencies": {
    "@architect/architect": "^8.5.11"
  }
}
```

### Arc App Entry Point

`@app` declares the application namespace in `app.arc`. `@http` defines HTTP routes in API Gateway with Lambda handler functions.

```arc
@app
ajcwebdev-architect

@http
get /
```

### Arc Configuration

`@aws` defines AWS specific configuration in `config.arc`.

```arc
@aws
runtime nodejs12.x
```

### Lambda Handler

`index.js` contains a Lambda function that returns HTML in the `body`.

```javascript
// src/http/get-index/index.js

exports.handler = async function http (req) {
  return {
    statusCode: 200,
    headers: {
      'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0',
      'content-type': 'text/html; charset=utf8'
    },
    body: `
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">

          <title>Architect</title>

          <style>
            * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
            }
            body {
              font-family: -apple-system, BlinkMacSystemFont, sans-serif;
            }
            .max-width-320 {
              max-width: 20rem;
            }
            .margin-left-8 {
              margin-left: 0.5rem;
            }
            .margin-bottom-16 {
              margin-bottom: 1rem;
            }
            .margin-bottom-8 {
              margin-bottom: 0.5rem;
            }
            .padding-32 {
              padding: 2rem;
            }
            .color-grey {
              color: #333;
            }
            .color-black-link:hover {
              color: black;
            }
          </style>
        </head>

        <body class="padding-32">
          <div class="max-width-320">
            <svg
              xmlns="http://www.w3.org/2000/svg"
              viewBox="0 0 267.07 50.23"
              class="margin-bottom-16"
            >
              <g fill="#000000"><path d="M91.68 41.88L77.47 8.59c-.21-.66-1.06-1.01-1.73-1.01h-.44c-.68 0-1.5.46-1.77 1.08l-14.3 33.27c-.03.07-.05.15-.05.24 0 .32.27.58.59.58h3.97c.3 0 .59-.31.69-.52.03-.07 2.77-6.72 2.77-6.72h16.54l2.77 6.84s.21.6.86.6h3.59c.43 0 .79-.35.79-.78-.01-.11-.07-.29-.07-.29zM68.91 31.15l6.56-15.75 6.51 15.75zM158.14 30.27c0-6.31-4.06-10.47-9.98-10.47-3.38 0-5.82 1.42-7.24 3.28V8.34h-.01a.55.55 0 0 0-.55-.52h-3.73c-.3 0-.55.24-.55.54v33.85c0 .29.24.53.53.53h3.84c.29 0 .53-.24.53-.53v-11.7c.05-3.08 2.2-6.31 6.26-6.31 3.57 0 6.02 2.69 6.02 6.75v11.26c0 .29.24.53.53.53h3.84c.29 0 .53-.24.53-.53zM167 9.33c-1.91.05-3.42 1.32-3.42 3.28s1.52 3.33 3.42 3.33c1.96 0 3.47-1.37 3.47-3.33s-1.52-3.33-3.47-3.28zM217.73 31.15c0-.12 0-.25-.01-.36v-.04c0-.09 0-.18-.01-.27 0-.05-.01-.09-.01-.14-.03-.37-.06-.71-.08-.88-.73-5.75-4.84-9.64-10.69-9.64-6.8 0-11.55 5.09-11.55 11.69 0 6.7 5.14 11.69 12.13 11.69 4.4 0 7.03-1.43 8.64-2.69 0 0 .36-.25.14-.66l-1.62-2.71c-.14-.22-.55-.24-.82-.02-1.24.92-2.97 1.97-5.81 1.97-4.21 0-7.24-2.59-7.88-6.16h17.17c.26 0 .37-.22.37-.48 0 0 .02-.56.02-1.11v-.03c.01-.06.01-.11.01-.16zm-17.51-1.71c.73-3.52 3.33-5.67 6.85-5.67 3.23 0 5.77 2.25 6.02 5.67zM108.97 19.88s-.89-.07-1.36-.07c-4.01 0-6.7 2.2-7.63 4.84l-.17-3.89a.574.574 0 0 0-.57-.51h-3.06a.56.56 0 0 0-.56.56V42.2c0 .3.25.55.55.55h3.78c.3 0 .55-.24.56-.54V30.77c.05-3.18 2.2-6.31 6.41-6.31.66 0 1.65.17 1.65.17.3.04.53-.14.55-.4l.31-3.84c.02-.27-.2-.49-.46-.51zM128.84 37.37c.2-.11.43-.03.53.16l1.64 2.99c.1.19.03.4-.16.52l-.02.01c-1.54.95-3.71 2.13-7.52 2.13-7.24 0-12.23-5.09-12.23-11.64 0-6.65 5.33-11.74 12.23-11.74 3.85 0 6.16 1.18 7.68 2.24.07.05.28.23.11.52l-1.72 2.96c-.11.19-.34.24-.53.13l-.04-.03c-1.19-.74-2.8-1.37-4.96-1.37-4.65 0-7.78 3.08-7.78 7.29 0 4.11 3.13 7.19 7.58 7.19 2.39 0 3.94-.64 5.16-1.35zM168.97 20.24h-3.79c-.29 0-.53.24-.53.53l-.05 21.45c0 .29.24.53.53.53h3.83c.29 0 .53-.24.53-.53V20.77c0-.29-.23-.53-.52-.53zM192.03 37.81c-.06-.12-.45-.13-.88.11-.85.44-1.81.91-3.51.91-2.79 0-4.5-1.22-4.5-4.21V24.3h8.38c.29 0 .53-.24.53-.53v-3c0-.29-.24-.53-.53-.53h-8.38v-7.2c0-.29-.24-.53-.53-.53h-3.69c-.29 0-.53.24-.53.53v7.2h-4.17c-.29 0-.53.24-.53.53v3c0 .29.24.53.53.53h4.07v10.62c0 5.33 3.38 8.27 8.37 8.27 3.54 0 5.59-1.22 6.56-1.91.17-.19.27-.38.17-.59zM238.61 37.45c.2-.11.43-.03.53.16l1.64 2.99c.1.19.03.4-.16.52l-.02.01c-1.54.95-3.71 2.13-7.52 2.13-7.24 0-12.23-5.09-12.23-11.64 0-6.65 5.33-11.74 12.23-11.74 3.85 0 6.16 1.18 7.68 2.24.07.05.28.23.11.52l-1.72 2.96c-.11.19-.34.24-.53.13l-.04-.03c-1.19-.74-2.8-1.37-4.96-1.37-4.65 0-7.78 3.08-7.78 7.29 0 4.11 3.13 7.19 7.58 7.19 2.39 0 3.94-.64 5.16-1.35zM262.91 37.92c-.06-.12-.45-.13-.88.11-.85.44-1.81.91-3.51.91-2.79 0-4.5-1.22-4.5-4.21V24.41h8.38c.29 0 .53-.24.53-.53v-3c0-.29-.24-.53-.53-.53h-8.38v-7.2c0-.29-.24-.53-.53-.53h-3.69c-.29 0-.53.24-.53.53v7.2h-4.17c-.29 0-.53.24-.53.53v3c0 .29.24.53.53.53h4.07v10.62c0 5.33 3.38 8.27 8.37 8.27 3.54 0 5.59-1.22 6.56-1.91.17-.19.27-.38.17-.59zM27.7 1.44c-13.03 0-23.63 10.6-23.63 23.63S14.67 48.7 27.7 48.7s23.63-10.6 23.63-23.63S40.72 1.44 27.7 1.44zm16.22 34.63c-3.68 5.41-9.71 8.62-16.23 8.62-6.49 0-12.52-3.2-16.2-8.57l16.2-15.78zm3.4-11c0 2.52-.48 4.99-1.44 7.34L29.71 16.73c-1.11-1.11-2.92-1.12-4.02-.02L9.53 32.46c-.97-2.37-1.46-4.85-1.46-7.39 0-10.82 8.81-19.63 19.63-19.63s19.62 8.8 19.62 19.63z"/></g>
            </svg>

            <div class="margin-left-8">
              <div class="margin-bottom-16">
                <h1 class="margin-bottom-16">
                  Hello from Node.js!
                </h1>
                <p class="margin-bottom-8">
                  Get started by editing this file at:
                </p>
                <code>
                  src/http/{your function}/index.js
                </code>
              </div>

              <div>
                <p class="margin-bottom-8">
                  View documentation at:
                </p>
                <code>
                  <a class="color-grey color-black-link" href="https://arc.codes">
                    https://arc.codes
                  </a>
                </code>
              </div>
            </div>
          </div>
        </body>
      </html>
    `
  }
}
```

Make some modifications to the HTML.

```javascript
// src/http/get-index/index.js

exports.handler = async function http (req) {
  return {
    statusCode: 200,
    headers: {
      'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0',
      'content-type': 'text/html; charset=utf8'
    },
    body: `
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">

          <title>ajcwebdev</title>

          <style>
            * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
            }
            body {
              font-family: -apple-system, BlinkMacSystemFont, sans-serif;
            }
            .max-width-320 {
              max-width: 20rem;
            }
            .margin-left-8 {
              margin-left: 0.5rem;
            }
            .margin-bottom-16 {
              margin-bottom: 1rem;
            }
            .margin-bottom-8 {
              margin-bottom: 0.5rem;
            }
            .padding-32 {
              padding: 2rem;
            }
            .color-grey {
              color: #333;
            }
            .color-black-link:hover {
              color: black;
            }
          </style>
        </head>

        <body class="padding-32">
          <div class="max-width-320">
            <div class="margin-left-8">
              <div class="margin-bottom-16">
                <h1 class="margin-bottom-16">
                  ajcwebdev
                </h1>
                <p class="margin-bottom-8">
                  shipshape
                </p>
              </div>
            </div>
          </div>
        </body>
      </html>
    `
  }
}
```

![02-arc-hello-world-edit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m53jtk1iekdmdannaaui.png)

### Create an About Page

Add `get /about` to your `app.arc` file and run `arc init` to generate a `get-about` directory with `index.js`

```arc
@app
ajcwebdev-architect

@http
get /
get /about
```

Alternatively you can create the directory and files yourself.

```bash
mkdir src/http/get-about
touch src/http/get-about/index.js src/http/get-about/config.arc
```

```arc
@aws
runtime nodejs12.x
```

```javascript
// src/http/get-about/index.js

exports.handler = async function http (req) {
  return {
    statusCode: 200,
    headers: {
      'cache-control': 'no-cache, no-store, must-revalidate, max-age=0, s-maxage=0',
      'content-type': 'text/html; charset=utf8'
    },
    body: `
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">

          <title>ajcwebdev</title>

          <style>
            * {
              margin: 0;
              padding: 0;
              box-sizing: border-box;
            }
            body {
              font-family: -apple-system, BlinkMacSystemFont, sans-serif;
            }
            .max-width-320 {
              max-width: 20rem;
            }
            .margin-left-8 {
              margin-left: 0.5rem;
            }
            .margin-bottom-16 {
              margin-bottom: 1rem;
            }
            .margin-bottom-8 {
              margin-bottom: 0.5rem;
            }
            .padding-32 {
              padding: 2rem;
            }
            .color-grey {
              color: #333;
            }
            .color-black-link:hover {
              color: black;
            }
          </style>
        </head>
        
        <body class="padding-32">
          <div class="max-width-320">
            <div class="margin-left-8">
              <div class="margin-bottom-16">
                <h1 class="margin-bottom-16">
                  About
                </h1>
                
                <p class="margin-bottom-8">
                  This page tells you about stuff
                </p>
              </div>
            </div>
          </div>
        </body>
      </html>
    `
  }
}
```

![03-arc-about-page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pu7jllcnl99049hox4xh.png)

## Deploy to AWS

We will first deploy to a staging environment and then to a production environment.

### Deploy to Staging Environment

```bash
arc deploy
```

```
         App ⌁ ajcwebdev-architect
      Region ⌁ us-west-2
     Profile ⌁ default
     Version ⌁ Architect 8.5.11
         cwd ⌁ /Users/ajcwebdev/ajcwebdev-architect

⚬ Deploy Initializing deployment
  | Stack ... AjcwebdevArchitectStaging
✓ Hydrate Finished checks, nothing to hydrate
⚬ Deploy Created deployment templates
✓ Deploy Generated CloudFormation deployment
✓ Deploy Deployed & built infrastructure
✓ Success! Deployed app in 107.684 seconds

    https://mi1p1lmaq6.execute-api.us-west-2.amazonaws.com

⚬ Deploy Deploying static assets...
⚬ Deploy @static folder (public/) not found, skipping static asset deployment
```

Visit [the URL](https://mi1p1lmaq6.execute-api.us-west-2.amazonaws.com) to see your site.

![04-arc-deployed-staging-website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3x6b59kbbn0czbwb2fyg.png)

### Deploy to Production Environment

```bash
arc deploy production
```

```
         App ⌁ ajcwebdev-architect
      Region ⌁ us-west-2
     Profile ⌁ default
     Version ⌁ Architect 8.5.11
         cwd ⌁ /Users/ajcwebdev/ajcwebdev-architect

⚬ Deploy Initializing deployment
  | Stack ... AjcwebdevArchitectProduction
✓ Hydrate Finished checks, nothing to hydrate
⚬ Deploy Created deployment templates
✓ Deploy Generated CloudFormation deployment
✓ Deploy Deployed & built infrastructure
✓ Success! Deployed app in 105.266 seconds

    https://5qg90om5c6.execute-api.us-west-2.amazonaws.com

⚬ Deploy Deploying static assets...
⚬ Deploy @static folder (public/) not found, skipping static asset deployment
```

![05-arc-deployed-production-website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljt0tpcnigwhaguhoqrl.png)