DEV Community

Paul Chin Jr.
Paul Chin Jr.

Posted on

Serverless Static Site Generation with Eleventy and Begin

Today, we're going to build a serverless blog using Eleventy, storing the site's source code and static content on GitHub, then deploy for free on Begin. No credit card or AWS account needed.

Try out Eleventy with Begin right now!

Hit this button to deploy an Eleventy blog to begin (no credit card required!) in 15 seconds:

Deploy to Begin

Create a new Architect project

Architect is an open-source serverless framework hosted by the OpenJS Foundation. Architect provisions AWS resources like S3 and API Gateway using infrastructure as code. Architect will also grant least privileged IAM roles for those resources enabling better security by default.

We'll start by installing our dependencies.

npm i -g @architect/architect
mkdir eleventy-blog
cd eleventy-blog
npm init -y
npm install @11ty/eleventy @architect/sandbox 
Enter fullscreen mode Exit fullscreen mode

Create an app.arc file in the project root. This file defines the app structure and cloud resources. Working this way gives developers deterministic deployments with declarative infrastructure that can be committed to GitHub alongside the source code.

# eleventy-blog/app.arc
@app
eleventy-blog

@static
folder _site
spa false

@http

@tables 
data
  scopeID *String
  dataID **String
  ttl TTL 
Enter fullscreen mode Exit fullscreen mode

Using Eleventy and AWS S3

Eleventy is a lightweight static site generator that uses templating and markdown to render HTML. AWS S3 is an object storage service that can be configured to serve static assets to the public internet. This avoids the need for a dedicated web server.

We can now create a layout template, an index page, a posts page, and some markdown files. In this example, we will use Shopify's Liquid templating language. Templates wrap your content with markup and let you iterate over data collections like individual posts. Start by creating _includes/layout.liquid:

<!doctype html>
<html lang="en">
  <head>
    <title>The Logs of the Web</title> 
    <meta charset="utf-8">
  </head>
  <body>
    <nav>
      | <a href="/">World Wide Web Log</a> |
      <a href="/posts" title="Posts">Posts</a> |
    </nav>
    <section>
     <p> {{ content }}</p>
    </section>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Create an index.html file in the root of our app

---
layout: layout.liquid
pageTitle: The Index Page
---
<section>
  <h2>Cool Blog</h2>
  <article>
    <h1 >{{ pageTitle }}</h1>
    <p><em>"I think I jump around more when I'm alone."</em></p>
  </article>
</section>
Enter fullscreen mode Exit fullscreen mode

Modify the scripts in package.json

# package.json
"scripts": {
    "build": "eleventy",
    "watch": "eleventy --serve",
    "start": "run-p watch sandbox",
    "sandbox": "ARC_STATIC_SPA=false npx sandbox"
  }
Enter fullscreen mode Exit fullscreen mode

Now you can use npm start and Eleventy will build your HTML into a /_site folder and @architect/sandbox will start a local development server.

Take a look at your shiny site by visiting localhost.

Creating posts

We can organize our markdown files in a folder named /posts. Eleventy turns these markdown files into HTML. A posts.json will allow Eleventy to expose the posts as a collection to feed the template data at build time. Our first file will be /posts/hello-world.md

--------
pageTitle: The First Post
imgURL: "https://www.placecage.com/g/400/300"
--------
# Hello World
- Nicolas Cage owned a pet octopus who helped him with his acting.
Enter fullscreen mode Exit fullscreen mode

Create a /posts/post.json file.

{ "layout": "layout.liquid", "tags": ["posts"] }
Enter fullscreen mode Exit fullscreen mode

Let's create a /eleventy-blog/posts.html that will display all of our posts.

--------
layout: layout.liquid
pageTitle: Caged Logs
--------
{% for post in collections.posts %}
<section>
  <article>
  <h1><a href="{{ post.url }}">{{ post.data.pageTitle }}</a></h1>
  <p> {{ post.templateContent }}
  <em>{{ post.date | date: "%Y-%m-%d" }}</em>
  </p>
  <img src="{{ post.data.imgURL }}" class="db" alt="Grey Photo of Cage.">
  </article>
</section>
{% endfor %}
Enter fullscreen mode Exit fullscreen mode

Try it out now by running npm start and try styling it however you like.

Discussion (0)