3.8 KiB
3.8 KiB
narlblog
A minimalist, filesystem-backed portfolio and blog engine. Rust/Axum API for the backend and Astro/React for the frontend.
backend/ Rust + Axum API (filesystem-backed)
frontend/ Astro + React, SSRs pages and proxies /api/*
data/ Runtime data — posts, uploads, config.json (host volume)
Quick start
-
Environment Setup:
cp .env.example .env # Generate a strong admin token: echo "ADMIN_TOKEN=$(openssl rand -hex 32)" >> .env -
Using Just: This project uses
justto simplify common tasks.just setup # Install backend and frontend dependencies just dev # Run both backend and frontend locally in parallel just docker # Start the full stack using Docker Compose -
Permissions: Ensure the
data/host directory is owned by UID 1000:sudo chown -R 1000:1000 data/
Site Modes
The engine supports two distinct modes via the SITE_MODE environment variable:
atelier(Default): Optimized for art portfolios. Requires at least one image per post; the first image serves as the cover plate in the gallery view.blog: A traditional text-focused blog layout. Images are optional, and the index prioritizes titles and excerpts.
Commands
| Command | Description |
|---|---|
just setup |
Installs dependencies for backend and frontend. |
just build |
Builds production binaries and assets. |
just dev |
Runs both services locally for development. |
just docker |
Starts the stack using docker compose. |
just test |
Runs the test suite for both services. |
Environment
| Variable | Required | Default | Notes |
|---|---|---|---|
ADMIN_TOKEN |
yes | — | Long random string. Stored as an HttpOnly cookie after login. |
SITE_MODE |
no | atelier |
atelier (art portfolio) or blog (traditional blog). |
PORT |
no | 3000 |
Backend port. |
DATA_DIR |
no | /app/data |
Where posts/uploads/config live. |
COOKIE_SECURE |
no | true |
Set false only for local HTTP development. |
FRONTEND_ORIGIN |
no | empty | Set to your frontend's URL only if you expose the backend directly. |
PUBLIC_API_URL |
no | http://backend:3000 |
Backend URL the Astro proxy hits server-to-server. |
Authoring
Posts are stored as markdown files in data/posts/<slug>.md with YAML frontmatter.
---
date: 2026-05-09
title: My First Post
summary: Optional short caption or excerpt.
tags:
- general
- 2026
draft: false
---
# Content Title
Post content goes here. In `atelier` mode, include at least one image:

draft: truehides a post from the public index.- Access the web editor at
/admin/editorafter logging in at/admin/login.
Uploads
Supported: jpg, jpeg, png, webp, gif, avif, pdf, txt, md, mp3, wav, ogg, mp4, webm, mov. Max size: 50 MB.
Backups
The data/ directory contains all state (posts, uploads, configuration). Backup this folder regularly.
Stack
- Backend: Rust 2024, Axum 0.8
- Frontend: Astro 6, React 19, Tailwind 4
- Editor: CodeMirror 6 with Vim mode