# ๐Ÿ•น๏ธ RetroBlog **A self-hosted blog engine with swappable OS / game-console skins.** Write Markdown posts, flip between retro themes (Windows, PS1, PS2, PS3, Wii, NDS, Dreamcast, JV2002โ€ฆ), and run the whole thing from a single SQLite file.
--- ## Features - **Markdown posts** โ€” create / edit / delete with slugs, tags, excerpts, dates. - **Swappable skins** โ€” pick the default theme; optionally let visitors switch. - **Admin panel** โ€” single-password login, signed session cookie. - **Import / export** โ€” JSON backup of settings and posts. - **Zero external services** โ€” data lives in one SQLite file (`data/blog.db`). Stack: Next.js 16 (App Router) ยท React 19 ยท better-sqlite3 ยท marked. --- ## Quick start (development) ```bash pnpm install pnpm dev ``` Open . Admin panel at (default password `admin` in dev). --- ## Configuration All config is environment variables. Copy `.env.example` to `.env` and edit. | Variable | Required | Default | Purpose | | ---------------------- | -------- | ---------------- | --------------------------------------------------------- | | `ADMIN_PASSWORD` | **prod** | `admin` | Password for `/admin`. **Set this in production.** | | `ADMIN_SESSION_SECRET` | **prod** | `ADMIN_PASSWORD` | Signs the admin session cookie. Use a long random string. | | `PORT` | no | `3000` | Port the server listens on. | Generate a secret: ```bash openssl rand -hex 32 ``` **Data** is stored in `./data/blog.db` (created automatically). Back up that directory to back up the whole site. --- ## Deploy โ€” Docker (recommended) Needs Docker + the Compose plugin. ```bash # 1. Set production secrets cp .env.example .env $EDITOR .env # set ADMIN_PASSWORD and ADMIN_SESSION_SECRET # 2. Build and run docker compose up -d --build ``` Site is live on . The database persists in the `retroblog-data` Docker volume across rebuilds. Common operations: ```bash docker compose logs -f # tail logs docker compose down # stop (keeps the data volume) docker compose up -d --build # update after pulling new code ``` **Back up the database:** ```bash docker compose exec retroblog sh -c 'cat /app/data/blog.db' > backup-$(date +%F).db ``` > Put a TLS-terminating reverse proxy (Caddy, nginx, Traefik) in front for > HTTPS in production. RetroBlog speaks plain HTTP on `PORT`. --- ## Deploy โ€” bare metal Needs Node.js 22+ and `pnpm` (`corepack enable`). A C toolchain (`build-essential`, `python3`) is required once, to compile better-sqlite3. ```bash # 1. Install deps and build pnpm install --frozen-lockfile pnpm build # 2. Set production secrets export ADMIN_PASSWORD='your-strong-password' export ADMIN_SESSION_SECRET="$(openssl rand -hex 32)" # 3. Start pnpm start # serves on PORT (default 3000) ``` ### Run it as a service (systemd) `/etc/systemd/system/retroblog.service`: ```ini [Unit] Description=RetroBlog After=network.target [Service] Type=simple WorkingDirectory=/opt/retroblog ExecStart=/usr/bin/pnpm start Restart=on-failure Environment=NODE_ENV=production Environment=PORT=3000 Environment=ADMIN_PASSWORD=your-strong-password Environment=ADMIN_SESSION_SECRET=your-long-random-secret User=www-data Group=www-data [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl daemon-reload sudo systemctl enable --now retroblog ``` The SQLite database lives in `WorkingDirectory/data/blog.db` โ€” make sure the service `User` can write there, and back up that file. --- ## Admin panel Sign in at `/admin` with `ADMIN_PASSWORD`. From there: - **Posts** โ€” full create / edit / delete with Markdown bodies, slugs, tags, dates. - **Settings** โ€” branding (title, subtitle, footer, version), default theme for new visitors, whether the public theme switcher is shown, and which skins it offers. - **Import / export** โ€” download a JSON backup of settings and/or posts, and import one back (posts can replace or append). All `/admin/*` routes are gated by middleware behind the signed session cookie. --- ## License See repository.