Short answer: How this Hugo blog uses Aamu.app as a headless CMS with database rows, Docs content, GraphQL, generated Markdown, and static publishing.

This blog uses Aamu.app as a headless CMS: post metadata lives in a Database, article text is written in Docs, and a build script fetches both to generate a Hugo site.

Writers edit Docs, editors manage publication status and metadata in the Database, and a static host serves the generated HTML.

What we are building

The basic flow looks like this:

Aamu Docs
  -> BlogPost row in Aamu Database
  -> GraphQL API + Docs API
  -> Hugo content files
  -> static blog

The Database row is used for the structured parts of the post: title, slug, author, publish date, status, tags, hero image, and the linked Doc. The Doc is the source of truth for the article body. Hugo is used only at build time to create the public site.

You can see the source code for this blog at https://github.com/AamuApp/aamu-blog.

Why use Aamu.app as a headless CMS?

A traditional CMS can be useful, but it also becomes another product to maintain. If your team already works in Aamu, using Aamu as the CMS keeps writing, metadata, project work, and internal knowledge close together.

This approach is useful when you want:

  • a familiar writing experience through Aamu Docs,

  • structured blog metadata in an Aamu Database,

  • a public site that is static, fast, and easy to host,

  • a build pipeline that can run on your own server, CI, or a static hosting service,

  • GraphQL access to the database rows, and

  • Docs API access to the actual article HTML.

The ingredients

For a setup like this blog, you need:

  • an Aamu Database created from the aamu-blog template,

  • Aamu Docs for writing the post bodies,

  • a BlogPost table where each row stores post metadata and links to a Doc,

  • a Person table for authors,

  • an API key that can read the database and the linked Docs,

  • Hugo for generating the static site, and

  • some deployment target such as Netlify, Cloudflare Pages, Vercel, or your own server.

Create the blog database

Create a database in Aamu.app with the provided aamu-blog template. The template gives you the basic shape for a blog: a BlogPost table and a Person table.

The BlogPost table is for posts. It stores fields such as title, slug, description, publish date, status, tags, author, hero image, and the Doc reference. The Person table is for post authors.

Write the article in Aamu Docs and link it through the BlogPost row’s Doc field.

Write posts in Aamu Docs

Create a new Doc for the article and write the post there. This gives you the normal Aamu Docs writing experience: rich text, headings, lists, links, images, collaboration, snapshots, and source views.

When the post is ready, create or update the matching BlogPost row in the database. Set the title, slug, author, publish date, tags, hero image, and status. Then select the Doc in the row's Doc field.

That Doc is the article source. The build script reads the BlogPost rows through GraphQL and then fetches the linked Doc through the Docs API. If the Doc has HTML content, that HTML becomes the Hugo post body.

What about the Body field?

The Body field is only for manually written or copy-pasted HTML. It is useful as a fallback, or if you really want to manage the post body as raw HTML in the database row.

Do not use the Body field as the normal Doc workflow. In the current Aamu.app UI, you cannot attach a Doc to the Body field. If you want the post to be written in Docs, link the Doc through the row's Doc field instead.

Configure the API key

The build script needs to read published BlogPost rows and fetch the linked Docs. This is done with an API key stored as an environment variable on the machine or CI job that builds the site.

For this blog repository, the useful environment variables are:

API_KEY=your_api_key
AAMU_DB_ID=your_database_id
AAMU_API_BASE_URL=https://your-aamu-host.example

# Optional, depending on your setup:
DOCS_API_KEY=your_docs_api_key
AAMU_PROJECT_ID=your_project_id
GRAPHQL_ENDPOINT=https://api.aamu.app/api/v1/graphql/

Keep API keys on the server side. Do not commit them to Git, do not publish them in frontend JavaScript, and do not paste them into public examples. The static site can be public, but the build credentials should stay private.

Build the Hugo site

The blog repository contains a build script that does the content sync before Hugo runs. The basic command is:

node build-with-graphql.js
hugo --minify

Or as one command:

node build-with-graphql.js && hugo --minify

The script does a few things:

  • queries the BlogPost rows through the GraphQL API,

  • filters for published posts,

  • detects the Doc field in the BlogPost schema,

  • fetches the linked Doc through the Docs API,

  • uses the Doc HTML as the post body,

  • downloads images into the Hugo post folder,

  • writes Hugo-compatible content/posts/.../index.md files, and

  • lets Hugo create the final static site.

The generated Hugo content files are build artifacts. The source of truth is the Aamu Database row plus the linked Doc.

Deployment options

There are several reasonable ways to publish the generated static site.

Static hosting service

You can use a service such as Netlify, Cloudflare Pages, Vercel, or another static host. In that setup, configure the environment variables in the hosting service and use the build command above. A build hook can trigger a new build when content changes.

Your own server

You can also build on your own machine or server and serve the generated files with Nginx or another web server. The official Aamu blog has used a Git-based deployment flow with a bare repository and a post-receive hook. That works well if you like controlling the server yourself, but it is only one option.

CI pipeline

A third option is a CI job. The job checks out the blog repository, sets the Aamu API environment variables, runs the build, and uploads the generated public/ directory to your hosting target.

Next steps

If you want to build a blog like this:

  1. Fork or clone AamuApp/aamu-blog.

  2. Create an Aamu Database from the aamu-blog template.

  3. Create a Person row for the author.

  4. Create a Doc for your first post.

  5. Create a BlogPost row and link the Doc in the row's Doc field.

  6. Add the API environment variables to your build environment.

  7. Run node build-with-graphql.js && hugo --minify.

  8. Deploy the generated public/ directory.

After editing a Doc or its post metadata, rebuild the site to publish the changes.

Related articles