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:

  1. oriz-home — apex domain, family directory, personal-portfolio page, and (per the apex-only-monitoring lock) the only site uptime-pinged.
  2. oriz-blog — this site. Long-form engineering writing.
  3. oriz-me — lifestream of timestamped events (the only family member that stores content as JSONL, not MDX, per the lifestream-jsonl-canonical decision).
  4. oriz-books — book reviews, reading log, ratings.
  5. oriz-finance — finance writing, calculators, reviews of cards and brokers.
  6. oriz-tools — small dev tools (regex tester, JSON pretty, image-to-WebP, the usual).
  7. oriz-extensions — landing pages for the browser extensions I publish.
  8. oriz-status — status board (read-only mirror of Better Stack monitors for the apex).
  9. 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>.
  10. 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).
  11. 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 canonical wrangler.toml shape, the canonical Cloudflare Pages config.
  • An AGENTS.md that 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 .md file with strict frontmatter and a related: 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 is services/** with status: 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 at oriz.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_ID and PUBLIC_GISCUS_CATEGORY_ID in your environment to enable them.