The oriz family — eleven sites, one knowledge bundle
How the chirag127/oriz monorepo coordinates eleven static sites, a shared design kit, and an Open Knowledge Format bundle that captures every architectural decision in plain markdown.
Most of my side-projects used to live as one-off repos that drifted from each other within a release. Different deploy commands, different env conventions, different design tokens, different "what does this do again" tax every time I came back. The oriz family is the cure: one master repo, eleven sister sites as git submodules, one design kit, one secrets pipeline, one knowledge bundle.
The eleven sites
Roughly in order of how often they get pushed:
- oriz-home — apex domain, family directory, personal-portfolio page, and (per the apex-only-monitoring lock) the only site uptime-pinged.
- oriz-blog — this site. Long-form engineering writing.
- oriz-me — lifestream of timestamped events (the only family member that stores content as JSONL, not MDX, per the lifestream-jsonl-canonical decision).
- oriz-books — book reviews, reading log, ratings.
- oriz-finance — finance writing, calculators, reviews of cards and brokers.
- oriz-tools — small dev tools (regex tester, JSON pretty, image-to-WebP, the usual).
- oriz-extensions — landing pages for the browser extensions I publish.
- oriz-status — status board (read-only mirror of Better Stack monitors for the apex).
- oriz-omnipost — the cross-post engine. CLI that reads RSS
from any site in the family and reposts to dev.to / Bluesky /
Buttondown / Telegra.ph / WordPress / Reddit. Idempotent on
the RSS
<guid>. - oriz-app — the only Firebase project. Auth, Firestore for bookmarks and per-user preferences, and a thin REST shim (no Admin SDK — Spark tier forever).
- oriz-kit — shared component library. Header, Footer,
<JsonLd>,<MultiSearch>,<StatusBanner>, the design tokens, the typography scale.
How the master repo holds it together
The master repo (chirag127/oriz) is not where the eleven sites'
code lives — that's the opposite of how a monorepo usually works.
Instead the master repo holds:
- A
sites/directory full of git submodules pointing at the eleven sister repos. - A
templates/directory with the canonical.env.example(the superset every site copies and trims), the canonicalwrangler.tomlshape, the canonical Cloudflare Pages config. - An
AGENTS.mdthat documents every architectural lock — the source of truth that LLM agents read first when working on anything in the family. - A
knowledge/directory: an Open Knowledge Format (OKF) v0.1 bundle. Every architectural decision, every rejected service, every glossary term, written as a single.mdfile with strict frontmatter and arelated:graph.
That last one earns its weight. When I sit down to add a new
service — say, "should the blog use Tally or Web3Forms for the
contact form?" — there's already a decision file under
knowledge/decisions/services/ with the answer, the rejected
alternatives, and the date the decision was locked. Or there
isn't, in which case the rule is: write the decision file first,
implement second.
OKF, briefly
OKF is a frontmatter-driven schema for durable knowledge. Each
file declares a type: (decision / glossary / service / rule),
plus tags:, timestamp:, status: (active / superseded /
rejected), and a related: array of sibling paths. It's just
markdown with conventions, but the conventions buy:
- Greppability. Every decision is
decisions/**/*.md. Every rejected service isservices/**withstatus: rejected. No Notion search, no Slack archaeology. - LLM-friendliness. Agents can load a focused subtree
(
decisions/architecture/) instead of the entire repo. - Portability. If GitHub disappears tomorrow, the bundle still renders from any static-site generator on any host.
The blog post I'm writing right now will, before it lands, get a
companion entry in knowledge/concepts/ describing the
"family-wide cross-post chain" so the next agent that touches
oriz-omnipost has a single place to read about it.
Shared kit, not shared monorepo
Each family site uses Astro 6, React 19, and Tailwind v4 directly,
with small community libraries (firebase, lucide-react,
react-hook-form, zod, @vite-pwa/astro, @fontsource/*) pulled
in per-app. Shared primitives — BaseLayout, Footer,
<JsonLd>, <MultiSearch>, <StatusBanner> — are copied (not
linked) between sites so no app is ever broken by an upstream
change it didn't opt into. Per the
no-turborepo decision,
each site is its own repo with its own deploy.
The deploy story
All eleven sites deploy to Cloudflare Pages (free tier
forever per the cloudflare-pages lock),
with a GitHub Pages mirror per site as a static fallback. Auth
goes to the single oriz-app Firebase project on Spark tier
(Spark forever; Admin SDK forbidden; REST-only Firestore access
from any client that needs to write). Secrets are managed by
envpact and mirrored
into Cloudflare via wrangler.
The diagram I should embed
A picture is worth several paragraphs of submodule explanation. This Excalidraw board is the canonical family-architecture diagram, embedded so it stays current:
What's next
Two things I'm working through right now:
- A
knowledge/viewer. OKF is greppable but a render layer would make the decision graph navigable to humans. Likely lives atoriz.in/knowledge/. - More cross-posting destinations. Telegra.ph and Reddit are the next adapters in oriz-omnipost. The next post digs into how the engine handles idempotency across destinations that don't share a cross-post-id concept.
If you're into this kind of "small infra, written down" work,
the master repo is at
github.com/chirag127/oriz
and the rule of thumb is: every interesting decision is a
.md file you can find with grep.
Comments
Comments are powered by giscus. Set
PUBLIC_GISCUS_REPO_IDandPUBLIC_GISCUS_CATEGORY_IDin your environment to enable them.