Skip to content

Repository files navigation

Macari (from Meridian)

Astro site evolving toward Macari: mostly static public blog and pages, plus an SSR command centre behind auth. See docs/spec.md and docs/deliverables-tracker.md.

Stack highlights: Astro 6, Starlight (/docs), TypeScript, Tailwind 3 (via @astrojs/tailwind; package.json overrides align its astro peer with the app until the integration declares Astro 6), MDX, content collections, RSS, sitemap, @astrojs/node standalone server, filesystem sessions, SQLite (better-sqlite3), bcrypt password hashes.

Local development

Requirements: Node.js 20+ (22 recommended).

npm install
cp .env.example .env

Set in .env at least PUBLIC_SITE_URL. Use http://localhost:4321 for local dev (see .env.example). Production builds still enforce same-origin checks on form POSTs, so the public URL you deploy under should match PUBLIC_SITE_URL (scheme, host, port).

For the command centre, set bootstrap credentials so the first (empty) database creates an admin user:

MACARI_BOOTSTRAP_USERNAME=admin
MACARI_BOOTSTRAP_PASSWORD=your-secure-password

Optional: MACARI_DB_PATH (defaults to ./data/macari.db under the project).

npm run dev

The dev script sets ASTRO_DEV_RELAX_ORIGIN=1 so sign-in forms are not blocked by Astro’s same-origin check when PUBLIC_SITE_URL and the browser URL differ slightly (e.g. localhost vs 127.0.0.1). Production builds keep strict checks.

Open http://localhost:4321.

Sign-in still fails after changing .env?

Bootstrap reads MACARI_BOOTSTRAP_* from your real .env file via dotenv and runtime env lookup (Vite was not reliably exposing those vars to SQLite code in dev). Ensure .env contains MACARI_BOOTSTRAP_USERNAME and MACARI_BOOTSTRAP_PASSWORD, then restart pnpm dev / npm run dev.

If you reset the database, delete SQLite sidecar files too (WAL mode): data/macari.db, data/macari.db-wal, and data/macari.db-shm if present.

pnpm and native modules

pnpm v10+ blocks dependency install scripts unless you allow them. This repo lists better-sqlite3, sharp, and esbuild in pnpm-workspace.yaml (onlyBuiltDependencies).

After cloning or if you see “Could not locate the bindings file”, run a clean install:

rm -rf node_modules
pnpm install

If it still fails, run pnpm rebuild better-sqlite3 (needs a C++ toolchain). As a fallback, npm install also works.

Test the vertical slice (auth + /command)

  1. With bootstrap vars set, run npm run dev.
  2. Open http://localhost:4321/command — you should be redirected to /auth/sign-in.
  3. Sign in with the bootstrap username and password — you should land on the command centre and can Sign out.

Public header/footer do not link to /command (see product spec).

Scripts

Command Description
npm run dev Dev server with hot reload
npm run build astro check + production build (dist/client + dist/server)
npm run preview Preview after build
npm start Run Node standalone: node ./dist/server/entry.mjs (set HOST / PORT if needed)

Authoring

  • Starlight reference: public docs live at /docs (start at /docs/guides/ for quick start, configuration, editorial features, and copy-paste AI prompts).
  • Posts: src/content/posts/ as .md or .mdx.
  • draft: true omits the entry from the production build (no page, no RSS).
  • unlisted: true (non-draft) keeps a shareable URL but omits the entry from the blog/notes indexes, RSS, /search, /tags, and the sitemap; the page is marked noindex for crawlers.
  • Writing kind: posts support writingKind: article | essay | journal (default article); notes support writingKind: note | snippet | log (default note). Shown in cards, detail headers, note index, tag archives, and search.
  • Hero images: src/assets/posts/ (see sample posts).
  • Short notes: src/content/notes/ as .md or .mdx (published at /notes and /notes/{slug}; same draft / unlisted rules). Optional tags: feed /tags and per-tag archives with posts.
  • Wikilinks in Markdown and MDX prose: [[note-or-post-slug]] or [[slug|Display text]] resolves to /notes/... or /blog/... when a matching file exists under src/content/notes or src/content/posts. Unresolved slugs render as a dashed “missing” span. Code blocks are left unchanged.
  • Backlinks: note and blog post detail pages include a Linked from section listing other published notes/posts whose bodies contain a wikilink that resolves to that page (same scope as rendered wikilinks: fenced and inline code are excluded).
  • Public search: /search loads /search-index.json (build-time index) and filters client-side by title, tags, description, and body text (all words must match).
  • Site metadata: src/lib/site.ts.
  • Motion: with prefers-reduced-motion: reduce, decorative CSS transitions/animations are collapsed site-wide; the blog reading-progress bar still tracks scroll without animating the width.

Docker

Build with your real site URL so feeds and metadata resolve correctly:

docker build --build-arg PUBLIC_SITE_URL=https://your-domain.com -t macari .
docker run --rm \
  -e MACARI_BOOTSTRAP_USERNAME=admin \
  -e MACARI_BOOTSTRAP_PASSWORD='use-a-long-secret' \
  -p 4321:4321 \
  -v macari-data:/app/data \
  -v macari-sessions:/app/.astro \
  macari

The image runs the SSR entrypoint (node ./dist/server/entry.mjs). The server binds HOST (default 0.0.0.0) and PORT (default 4321); platforms such as Coolify usually set PORT—no code changes required.

Persist these paths on a volume so SQLite and sign-in sessions survive container restarts:

Path Purpose
/app/data SQLite database (MACARI_DB_PATH default)
/app/.astro Filesystem session store (Astro @astrojs/node)

The Dockerfile declares both as **VOLUME**s and includes a HEALTHCHECK that requests / using the runtime PORT.

Coolify

  1. Create the service from this repo’s Dockerfile (repository build).
  2. Set build argument PUBLIC_SITE_URL to your public URL (scheme + host, no trailing path).
  3. Set runtime env: MACARI_BOOTSTRAP_USERNAME, MACARI_BOOTSTRAP_PASSWORD, and optionally MACARI_DB_PATH (default /app/data/macari.db under the mounted volume).
  4. Attach persistent storage mapped to /app/data and /app/.astro (two mounts or one parent volume—both directories must remain writable by the container user).
  5. Ensure the proxy forwards X-Forwarded-Proto / Host correctly so Astro’s origin checks and redirects match PUBLIC_SITE_URL.

Nixpacks / Railway / Render

  • Install: npm install
  • Build: npm run build
  • Start: npm start

Set PUBLIC_SITE_URL at build time. Set MACARI_BOOTSTRAP_* or provision users separately for production.

Project layout

src/
  components/
  content.config.ts
  content/posts/
  data/
  layouts/
  lib/
    auth/          # password helpers
    db.ts          # SQLite + schema + bootstrap user
  middleware.ts    # gates /command/**
  pages/
    api/auth/      # login, logout
    auth/
    blog/
    command/       # private shell (SSR)
  styles/
public/
docs/              # product spec, tracker, architecture notes

Contributing

Branching, PR expectations, lint/format, and CI are documented in CONTRIBUTING.md.

License

MIT — use freely for your own site.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages