Build Bear Blog
YESreplaces $5/mosaves $60/yrback to the verdict
A minimal blog with Bear's constitution: Markdown in, static HTML out, zero client-side JavaScript and one stylesheet under 5 KB. Tags, RSS, a sitemap, optional privacy analytics, and a custom domain. Everything you add is a reason it stops being Bear.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Everything in this build runs on it: the server, the scripts, the tests.
Get it Download the LTS installer from nodejs.org, or install with your package manager (brew install node, or nvm install 22). Restart the terminal afterwards. open ↗
Verify
node --version prints v22 or higher - installfree
Why Every step below is a command you type or a file you edit.
Get it VS Code (code.visualstudio.com), Cursor or Zed. Open a folder for the project and use the editor's built-in terminal. open ↗
Verify
You can open a folder and run a command in its terminal - installfree
Why History for your code, and the way most hosts deploy.
Get it Install from git-scm.com or with your package manager, then run git init in the project folder once it exists. open ↗
Verify
git --version prints a version - have readyfree
Why Phase 1 renders them.
Get it Bear: Dashboard > Settings > Export. Otherwise copy your posts into Markdown files with a date.
- accountfree
Why Deploy on push.
Get it Cloudflare Pages, Netlify or GitHub Pages connected to the repo. open ↗
- accountroughly $10 a year, or free on an existing domain
Why The point of leaving is a domain you own.
Get it Register at Cloudflare Registrar, Porkbun or Namecheap, or use a subdomain of one you already own. You add one DNS record in the deploy phase. open ↗
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
posts/*.md with frontmatter: title, date, slug, tags, draft. The folder is the CMS.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
SITE_URL | required | https://yourname.blog | Canonical base for RSS and OG. |
The build, in order
Build pipeline
posts/*.md to dist/, drafts excluded, frontmatter errors loud.
Read posts/*.md with frontmatter (title, date, slug, tags, draft), render index.html newest first and one page per post, copy static assets.
Files
build.mjsterminalmkdir bear && cd bear && git init && npm init -y && npm pkg set type=module && npm install markdown-it@14 gray-matter@4 mkdir -p posts static && cp .env.example .env
done when · tick each as it passesThe stylesheet
Under 5 KB, inlined, no script tag anywhere.
Inline it in build.mjs.
done when · tick each as it passesTags and RSS
Privacy analytics (optional)
Pageviews without a cookie or a raw IP, or nothing at all.
The endpoint logs a daily-salted hash of IP and user agent per path; /stats behind basic auth. Write the decision down.
done when · tick each as it passesDeploy
Keep it Bearproduct builder
Guardrails so the blog stays small as it grows.
done when · tick each as it passes
That is the whole plan for Bear Blog. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- The Bear discover feed; it is the community.
- Newsletters, comments, themes.
- the Bear discover feed and its upvotes
- hosted privacy analytics
- the built-in newsletter
- someone else keeping it online for $5
- An email-me-new-posts option via RSS-to-email you do not run
Need the files? The project pack on the verdict page hands your agent the whole brief · more publishing.