Library / SDK
CaliCastle/cali.so avatar
CaliCastle/cali.so

cali.so: source code, deployment model and licence for a Next.js 16.3 personal site

Personal website for Cali Castle

2,025 stars538 forksTypeScriptNOASSERTION

At a glance

What is it?
cali.so publishes the TypeScript source for Cali Castle's personal website, built on Next.js 16.3 and React 19 with a bilingual routing model and a strict deployment pipeline. The MIT licence covers the application code only; blog posts, photographs, and personal data are reserved.
Who is it for?
cali.so is worth reading for its Next.js 16.3 and React 19 architecture: bilingual routing, an expand-only Neon migration policy, Clerk-based owner authentication, and a GitHub Actions deployment that separates migrations from application commits. It is not a starting point for a personal blog.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The README names one explicit constraint before the architecture

One sentence in the README sets up everything else. This repository publishes Cali Castle's personal site and is not maintained as a reusable template for third parties. That constraint is not a disclaimer; it shapes every design decision in the repository, from the credential model to the licence split.

cali.so is the personal website of Cali Castle. The current release, v3.0, reached the main branch on July 20, 2026, after a ground-up rewrite from the v2 codebase that ran on Sanity and Next.js 14. Two earlier tagged releases exist in the repository: v2.0 in March 2024, which introduced that Sanity setup, and v1.1 also in March 2024, which migrated the legacy database from PlanetScale to Neon. A 2023/2024 cloning guide preserved in the repository as historical content describes the old Sanity setup, comment system, and guestbook, none of which applies to v3.

The repository has two long-lived branches: dev is the protected Staging and integration branch, and main is Production. Feature pull requests target dev, and reviewed releases promote dev to main through pull request, meaning no direct commit ever reaches production outside that reviewed process.

Next.js 16.3, React 19 and a bilingual URL strategy

Version 3 runs on Next.js 16.3, React 19, TypeScript, and Tailwind CSS v4. Base UI primitives come from the `@fluid` component registry, and blog posts are written in MDX with colocated media under `content/blog/`.

Routing was designed around existing Chinese URLs. Release routing keeps Chinese content at its existing unprefixed URLs and gives English content the matching `/en` route family. Changing that split after deployment would break existing inbound links, which is presumably why the constraint is documented in the README rather than left implicit in the code.

Static public pages use ISR-backed social data alongside committed fallback snapshots. When the upstream source is unavailable, the committed snapshot is served instead of a blank page. The owner admin for Media and AMA operations is protected by Clerk authentication, exact owner metadata, origin checks, and rate limits. Provider-backed AMA capabilities require complete credential pairs and fail closed when the pair is absent. There is no partial AMA mode for incomplete configuration.

Media storage is Bunny-backed, with owner review and curation in admin. Its active Published Photo Selection powers the /photos route and the homepage preview, while CDN path rules expose only immutable Renditions rather than the originals.

Four commands for local setup, with a strict credential rule

The README gives a four-command sequence for local setup:

bash
corepack enable
pnpm install --frozen-lockfile
cp .env.example .env.local
pnpm dev

The `package.json` sets `[email protected]` as the package manager and constrains Node to `^22.22.2 || ^24.15.0 || >=26.0.0`. The `--frozen-lockfile` flag means pnpm refuses to update any package version implicitly, keeping development against the checked-in lockfile.

All runtime variables and fail-closed provider boundaries are documented in `.env.example`. One credential gets special attention in the README: `MIGRATION_DATABASE_URL` goes only into the shell environment of an explicit migration command and must never appear in `.env.local` or in any Vercel config.

bash
MIGRATION_DATABASE_URL=postgresql://... pnpm db:migrate

Filling `.env.example` requires credentials for Clerk, a Neon database using a CRUD-only role, and the site URLs. Four more provider slots appear in `.env.example` (Google, Upstash, Bunny, and Tencent), and each is optional or production-only; any that lacks a credential pair fails closed rather than falling back to a degraded mode. The README instructs using isolated development credentials and never copying production data or secrets into a local or preview environment. That is structural, not advisory: staging and production use separate Neon projects, and the production migration credential lives only in a `main`-only GitHub environment, outside the application runtime.

GitHub Actions controls every deployment, Vercel Git integration is off

Vercel's own Git integration is disabled: migrations must finish before the matching commit is deployed, and Vercel's Git integration does not provide that ordering guarantee. All deployments go through GitHub Actions, which is the only system authorized to trigger them.

Feature pull requests target dev, and dev automatically migrates and deploys persistent Staging on each push; internal feature branches receive persistent Neon `preview/<git-branch>` children of Staging, while fork pull requests receive code-only CI with no database access.

When a commit reaches main, GitHub Actions automatically migrates and deploys that exact commit using credentials stored in a main-only GitHub environment, ensuring that the Vercel runtime never receives migration credentials. Neon handles rate limits in staging and preview; Redis is available in Production only. Porting this deployment setup to another host requires replacing the GitHub Actions workflows, re-creating the environment-scoped credential model, and providing an equivalent ordering guarantee for migrations before each deploy. The README links to docs/security/baseline.md for the enforced security boundary and to docs/security/verification.md for hosted controls requiring current evidence.

Expand-only migrations and hash-locked SQL in production

Under the normal release workflow, the database schema can only grow: adding a column or table is the standard path, but removing or altering an existing one requires a separate, explicitly approved release. Any migration that has been reviewed gets a hash lock; SQL written after it must satisfy an explicitly maintained allowlist. A migration that alters or removes an existing contract cannot go through the normal path and requires a separately approved release.

The database credential split reinforces this boundary. `DATABASE_URL` must not carry DDL access or schema ownership; it is a CRUD-only role. Schema changes go through `MIGRATION_DATABASE_URL`, which is never stored in the application runtime environment.

The /photos route and homepage photo preview each depend on three prerequisites: migrations `0005` through `0008`, the Bunny Media zone path separation between protected originals and public Renditions, and an active Published Photo Selection. If any one of those is absent, those routes will not function.

Admin access to production database records or sensitive cloud data requires two fresh confirmations made immediately before the access, enforced inside the admin interface rather than at an environment boundary.

The full validation suite covers 23 named commands before a release

The README lists every command required before a production release: `pnpm typecheck`, `pnpm test:unit`, `pnpm test:localization`, `pnpm test:ama`, `pnpm test:deployment`, `pnpm test:security`, nine separate media test commands covering storage, catalog, processing, ingestion, geocoding, alt-text, admin, asset-review, photo-selection, purge, and reconciliation, then `pnpm build`, `pnpm verify:legacy-urls`, `pnpm verify:links`, `pnpm verify:public-discovery`, `pnpm verify:security-boundary`, and `pnpm audit:prod`.

Each is a named entry in `package.json`. The localization test runs via Node's built-in test runner: `node --test scripts/localization.test.mjs`. The AMA test also runs `pnpm db:validate`, which the `package.json` defines as `node --test scripts/ama-migrations.test.mjs`.

The README states that before a release, the full suite and production build must pass from a frozen-lockfile install. Preview releases of Next.js are not automatically adopted: each one requires explicit review, a lockfile update, and a full suite run before it enters the codebase, and the version stays pinned until that sequence completes. That strictness has a cost: a routine dependency bump can block a release until the full suite passes against the new lockfile.

MIT for source code, but blog posts and personal media are excluded

The application source code is available under the MIT License. What the MIT grant does not cover is listed explicitly in the README: Cali's personal writing, photographs, artwork, identity, likeness, logos, branding, personal data, and third-party assets. Those materials remain subject to their respective rights and may not be reused except with separate permission or as allowed by law.

The README names the locations: authored work under `content/blog/`, personal media under `public/images/`, biographical and taste data in other paths. GitHub classifies the repository licence as Other rather than MIT because the combination of an MIT source licence and reserved content rights does not map to a single standard identifier.

Anyone who forks the repository and runs a public copy needs to handle both halves. The application code runs under MIT. Content in those paths, and content in repository history that originated with Cali Castle, is outside that grant. The README does not offer a mechanism for requesting separate permission; it states only that the exclusion applies. Before redistributing a fork, read the LICENSE file in the repository root in full.

Editorial conclusion

cali.so is worth reading for its Next.js 16.3 and React 19 architecture: bilingual routing, an expand-only Neon migration policy, Clerk-based owner authentication, and a GitHub Actions deployment that separates migrations from application commits. It is not a starting point for a personal blog. The README says so directly, and the credential model and content licence both confirm it. Read `.env.example` before running locally to identify which providers fail closed when unconfigured. The MIT source licence does not cover content in `content/blog/` and `public/images/`, which is the first boundary to resolve if you plan to run a public fork.

Frequently asked questions

What is cali.so?

cali.so is the personal website of Cali Castle, and this repository is its TypeScript source code. The current version is v3.0, released on July 20, 2026, built on Next.js 16.3, React 19, and Tailwind CSS v4.

Can I fork cali.so as a starting point for my own blog?

The README states directly that the repository is not maintained as a general-purpose blog template. The credential architecture, deployment model, and content licence are all built for a single owner's production site.

How do I run cali.so locally?

Enable corepack, install dependencies with `pnpm install --frozen-lockfile`, copy `.env.example` to `.env.local` and fill in the required credentials, then run `pnpm dev`. Node must satisfy `^22.22.2 || ^24.15.0 || >=26.0.0`.

What database does cali.so use?

cali.so uses Neon (Postgres). The application runtime credential must be a CRUD-only role. Schema migrations run through a separate `MIGRATION_DATABASE_URL` that is kept out of the application runtime and Vercel.

What licence does cali.so use?

The application source code is MIT licensed. Blog posts, photographs, personal media, and identity assets are excluded from that grant and remain subject to their own rights. GitHub classifies the combined licence as Other.

Official sources

  1. CaliCastle/cali.so on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/calicastle-cali-so.svg)](https://hysenlabs.com/projects/calicastle-cali-so)