Skip to content

jake0lawrence/writebook-ops

Repository files navigation

writebook-ops  📚⚙️

Automation, CI/CD, backups & growth-hacking scripts for my self-hosted Writebook instance at https://books.jakelawrence.io.

CI
Deploy
MIT

Mission: treat writing like software — reproducible builds, Git-first content, and one-push deploys.


✨ What’s inside

Area Highlights
Docs (/docs/) Architecture, CI/CD, backup strategy, bulk importer, theming & integrations, FAQ.
GitHub Actions (.github/workflows/) 🔀 Lint/test 🚀 Build + deploy ⬆️ Weekly upstream sync ☁️ Nightly S3 backup.
Scripts (/scripts/) backup.sh, import-chapters.js, teaser-maker.mjs, healthcheck.sh.
Cron (/cron/) Single entry that calls backup.sh nightly at 02:05.
Dockerfile (fork) Builds Writebook + custom CSS + GA snippet into a tagged image.

📂 Repository layout


writebook-ops/
├─ .github/workflows/   # CI jobs
├─ scripts/             # Bash / Node / Python helpers
├─ cron/                # backup schedule
├─ docs/                # deep-dive guides (see index below)
├─ .env.example         # fill & copy to .env
├─ .gitignore
├─ LICENSE              # MIT
└─ README.md

Big-picture diagram lives in docs/00-overview.md


🚀 Quick start

  1. Clone & configure
   git clone [email protected]:jake0lawrence/writebook-ops.git
   cd writebook-ops
   cp .env.example .env    # fill SSH_HOST, S3_BUCKET, GA_ID, etc.
  1. Run local lint/tests

    npm ci && npm run lint && npm test
  2. Push to main

    • Lint → Build Docker → Push image to GHCR → SSH deploy → Live.
    • Markdown added to content/ auto-imports via content-sync workflow.

📜 Documentation index

Doc What you’ll find
00-overview.md Repo goals, component diagram, data-flow ASCII map.
10-architecture.md Droplet layout (Ubuntu → Docker → Traefik → Writebook), “fork + disable auto-update” rationale.
20-ci-cd.md Full GitHub Actions patterns, secret handling, sample deploy.yml, weekly upstream rebases.
30-backups.md Nightly once data backup → S3, restore drills, cost table.
40-content-import.md Bulk Markdown importer (Node & Python examples), image handling, GH Action trigger.
50-customization.md Persistent theming (custom CSS, fonts, cover partial), keeping a small patch-set.
60-integrations.md Google Analytics (GA4) build-time injection, Mailchimp/Buttondown email workflow, auto-tweet script, RSS worker.
90-faq.md Auto-update gotchas, 127.0.1.1 DNS confusion, SSL fixes, help links.

🛠 Key scripts

Script Purpose One-liner
backup.sh Safe snapshot (once data backup), sync to S3, prune local. ./scripts/backup.sh
import-chapters.js Idempotent Markdown → Pages via rails runner. node scripts/import-chapters.js
teaser-maker.mjs Duplicate a page, trim to 500 words, set public. node scripts/teaser-maker.mjs <slug>
healthcheck.sh Ping /healthz, Slack alert if non-200. Cron every 5 min

🔄 Workflows in action

Workflow Trigger What happens
lint.yml push, PR ESLint + Prettier + Shellcheck + unit tests.
deploy.yml Merge/push to main Build image with GA ID arg → Push to GHCR → SSH restart containers.
upstream-sync.yml Weekly cron Rebase fork on upstream 37signals & open PR.
backup.yml Nightly cron Runs backup.sh via SSH; uploads tarball to S3 / DO Spaces.

Implementation details in docs/20-ci-cd.md.


🎨 Custom look

  • Override styles in app/assets/stylesheets/custom.css — survives updates per Jason Fried’s note.
  • Use Google Fonts or self-hosted .woff2; reference via Rails asset helpers.
  • Branded cover partial lives in app/views/pages/_cover.html.erb.

Full walkthrough: docs/50-customization.md


📦 Backup & restore cheatsheet

# manual snapshot
once data backup /var/backups/writebook_$(date +%F).tgz

# restore on a fresh droplet
docker compose down
tar -xzf backup.tgz -C /opt/writebook/data
docker compose up -d

More details + cost table: docs/30-backups.md


🤝 Community & references


🗺 Roadmap

  • ✅ Visual regression tests
  • ☐ Slack webhook for successful deploy
  • ☐ Optional Fly.io staging environment

PRs and ideas welcome!


📝 License

Scripts & docs © 2025 Jake Lawrence — released under the MIT License. Writebook itself remains © 37signals and distributed under their single-installation ONCE license (not included here).

Enjoy—and happy shipping! 🚀

About

Automation & CI scripts for my self-hosted Writebook at books.jakelawrence.io

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages