Hex.pm Documentation

Static site generation for Elixir. Astral gives you Astro-class site features — pages, Markdown, layouts, content collections, pagination, feeds, sitemaps, and component templates — while Volt handles TypeScript, CSS, assets, dev serving, and HMR.

mix igniter.install astral
mix astral.dev
mix astral.build

Build docs, blogs, marketing pages, and content sites with Elixir config and templates. No JavaScript site config, no separate bundler process, no Node.js requirement for the default toolchain.

Why Astral

Most static site generators put your content model, routing, and build configuration in JavaScript. Astral keeps the site layer in Elixir and delegates frontend assets to Volt.

You get the pieces expected from a modern static site framework:

  • File-based static pages from Markdown, HTML, and .astral templates.
  • HEEx-first .astral pages, layouts, and local components.
  • Schema-backed content collections with JSONSpec-style typespec maps or Zoi.
  • Static pagination and generated routes for blogs, docs, and indexes.
  • Built-in feed and sitemap plugins.
  • Stable Markdown heading anchors for table-of-contents layouts.
  • Public files copied as-is.
  • TypeScript, CSS, imported assets, dev serving, and HMR through Volt.
  • Plug/Bandit dev server with full reloads for pages, layouts, components, and public files.
  • Igniter-powered starter scaffolding.

Astral is early but usable for small static sites, documentation prototypes, and blogs. See the roadmap for planned work.

Elixir site config

astral.config.exs is ordinary Elixir:

import Astral.Config

site do
  pages "pages"
  public "public"
  components "components"

  layouts "layouts" do
    default "site.astral"
  end

  assets "assets" do
    entry "app.ts"
    url_prefix "/assets"
  end
end

See the Getting Started guide and Configuration cheatsheet.

HEEx-first static templates

.astral templates use Phoenix HEEx syntax but render static HTML:

---
assigns = assign(assigns, :title, "Home")
---

<h1>{@title}</h1>
<.pill :for={feature <- @features}>{feature}</.pill>

Local components and slots use HEEx conventions:

<!-- components/card.astral -->
<article class="card">
  {render_slot(@inner_block)}
</article>

Browser assets inside .astral templates are extracted into Volt's asset graph:

<style>.hero { padding: 4rem; }</style>
<script lang="ts">console.log("ready")</script>

See the .astral Templates guide.

Content collections

Define typed content collections in Elixir:

collections do
  collection :posts, "content/posts" do
    permalink "/blog/:slug/"
    layout "post.html"

    schema %{
      required(:title) => String.t(),
      required(:date) => String.t(),
      optional(:draft) => boolean(),
      optional(:tags) => [String.t()]
    }
  end
end

Use validated data from layouts and templates:

<%= for post <- @collections.posts do %>
  <a href={post.route_path}><%= post.data.title %></a>
<% end %>

See the Content Collections guide.

Pagination, feeds, and sitemaps

Build common site routes with plugins:

plugins [
  {Astral.Plugin.CollectionPages,
   collection: :posts,
   pattern: "/blog/*page",
   page_size: 10,
   layout: "blog.html"},
  {Astral.Plugin.Feed,
   site_url: "https://example.com",
   title: "My Blog",
   author: "Me",
   collection: :posts},
  {Astral.Plugin.Sitemap,
   site_url: "https://example.com"}
]

See Pagination and Generated Routes and Feeds and Sitemaps.

Volt-powered assets

Reference source assets from layouts:

<script type="module" src="<%= Astral.asset_path(@site, "app.ts") %>"></script>

In development this points to Volt's dev server. In static builds it resolves through Volt's manifest to content-hashed output files.

See the Assets guide and the Volt documentation for frontend tooling details.

Development and builds

mix astral.dev --open
mix astral.build

mix astral.dev serves routes, public files, Volt assets, HMR, and useful HTML error pages. mix astral.build writes static files to dist/ for any static host or CDN.

See the Development Server guide and Static Builds guide.

Example site

A runnable example lives in examples/basic:

cd examples/basic
mix deps.get
mix astral.dev
mix astral.build
mix check

It demonstrates Markdown, HTML pages, .astral pages/layouts/components, public files, Volt TypeScript/CSS assets, feeds, sitemaps, and Volt JS/TS formatting/linting.

Documentation

Full documentation, guides, and cheatsheets are available on HexDocs.

Development

mix deps.get
mix ci

License

MIT © 2026 Danila Poyarkov