Nuartz can be deployed in two ways: as a static site (GitHub Pages) or with a server (Vercel, Netlify, Docker). Most features work in both modes, but a few things need a server.
Which mode should I use?
| Feature | Static (GitHub Pages) | Server (Vercel) |
|---|---|---|
| Pages, search, graph view | O | O |
| Popover previews (internal links) | O | O |
| Dark mode, tags, backlinks, TOC | O | O |
| RSS feed, sitemap | O | O |
| Dynamic OG images (per-page social cards) | X | O |
| External link previews | X | O |
| Next.js image optimization | X | O |
| Cost | Free | Free tier |
Short version: if you just want to publish your notes for free, GitHub Pages works great. If you want social preview cards or external link previews, use Vercel.
GitHub Pages (static export)
GitHub Pages serves static files for free. Nuartz supports this by building all pages as HTML at build time.
How it works
When you enable static export, Nuartz:
- Pre-generates
graph.json— the same graph data that normally comes from/api/graph, saved as a static file - Pre-generates
preview-index.json— preview data for internal link popups, no API needed - Copies media files from
content/topublic/content/so images work without a server - Temporarily disables server-only routes (API routes, OG image generation) that aren't compatible with static hosting
- Builds all pages as static HTML using Next.js
output: "export"
The prebuild script (apps/web/scripts/prebuild-static.ts) handles steps 1-4 automatically.
Setup
1. Enable GitHub Pages in your repo
Go to your repo's Settings > Pages and set the source to GitHub Actions.
2. Enable automatic deployment
The repo includes .github/workflows/deploy-pages.yml, but it's set to manual dispatch by default (so it doesn't fail on repos that don't use GitHub Pages). To deploy on every push, add the push trigger:
on:
push:
branches: [main]
workflow_dispatch:Or you can leave it as-is and trigger deployments manually from the Actions tab.
3. Push to main
The workflow will:
- Automatically enable
output: "export"innext.config.ts - Run the prebuild script (generate static graph/preview data, copy media files)
- Build all pages as static HTML
- Deploy to GitHub Pages
That's it. Your site will be live at https://<username>.github.io/<repo-name>/.
The workflow automatically enables static export during the build. Your next.config.ts stays unchanged in the repo, so Vercel and local bun dev continue to work normally.
You can test the static build locally:
bun run apps/web/scripts/prebuild-static.ts
bun run build
npx serve apps/web/outVercel (recommended)
Vercel has first-class Next.js support and enables the full feature set, including dynamic OG images and external link previews.
1. Import the repository
Go to vercel.com/new, click Import Git Repository, and select your Nuartz repo.
2. Configure the project
Nuartz is a monorepo — the Next.js app lives in apps/web, not the root. Override the defaults:
| Setting | Value |
|---|---|
| Root Directory | apps/web |
| Framework Preset | Next.js (auto-detected) |
| Install Command | cd ../.. && bun install --frozen-lockfile |
| Build Command | cd ../.. && bun run build:pkg && cd apps/web && next build |
| Output Directory | .next (default) |
The install and build commands run from apps/web by default. The overrides above cd ../.. back to the monorepo root so Bun can resolve the nuartz workspace package.
3. Environment variables
Add these in Settings > Environment Variables if you use optional features:
# Site URL (used for RSS, OG images)
NEXT_PUBLIC_SITE_URL=https://your-site.vercel.app
# Giscus comments (optional)
NEXT_PUBLIC_GISCUS_REPO=your-user/your-repo
NEXT_PUBLIC_GISCUS_REPO_ID=R_xxx
NEXT_PUBLIC_GISCUS_CATEGORY=Announcements
NEXT_PUBLIC_GISCUS_CATEGORY_ID=DIC_xxx4. Deploy
Click Deploy. Vercel rebuilds automatically on every push to main.
Netlify
Netlify's Next.js support (via @netlify/plugin-nextjs) works but is less reliable than Vercel for App Router features. Use Vercel if possible.
- Import your repo at app.netlify.com
- Set Base directory:
apps/web - Set Build command:
cd ../.. && bun run build:pkg && cd apps/web && next build - Set Publish directory:
apps/web/.next - Add the Essential Next.js plugin if not auto-detected
Self-hosting (Node.js / Docker)
Node.js
# From repo root
bun run build # builds nuartz package + Next.js app
cd apps/web
node .next/standalone/server.jsMake sure output: "standalone" is set in apps/web/next.config.ts.
Docker
FROM oven/bun:1 AS builder
WORKDIR /app
COPY . .
RUN bun install --frozen-lockfile
RUN bun run build:pkg
RUN bun run --cwd apps/web build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/apps/web/.next/standalone ./
COPY --from=builder /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=builder /app/apps/web/public ./apps/web/public
EXPOSE 3000
CMD ["node", "apps/web/server.js"]docker build -t nuartz .
docker run -p 3000:3000 nuartz