The Year-Rollover Trap of a Date Input: Read the Year Back Before Saving
There’s a page on the site called /masturbation that publicly shows each day’s count and an annual heatmap, plus an admin backend /dash/masturbation where the administrator can backfill, edit, and clear entries. The data is private and the page is ordinary: a year-scoped query RPC, a calendar, a date input and a count input. On launch day there was a bug that silently ate data. 0 means both “nothing that day” and “zero out that day” The heatmap loads by year, and the editor’s selectedCount c...
After Moving Off Vercel, the Safety Nets the Platform Provided Started Showing One by One
On September 29 and 30, twenty-one commits over two days moved nav-site from Vercel + Neon to a Singapore VPS: Cloudflare Tunnel in, the origin exposes no public ports, postgres binds only to 127.0.0.1:5432, the app runs in Docker Compose, and builds are done on the server with a dedicated buildx builder. The migration ultimately succeeded. But those earlier commits were almost all patching the same category of thing: assumptions the platform used to make on my behalf. This post records them ...
Rate Limiting Before the Write: Debugging a Verification Code Invalidated by Itself
In September’s auth milestone, email OTP, password reset, and Google login all wrapped up together. Among the things the first review round turned up, one was related to rate limiting, and I’m writing it down because it’s nothing like “just configuring a few numbers.” Look at the code order first better-auth’s email-otp plugin first calls resolveOTP (email-otp/routes.mjs:31) in the endpoint, unconditionally inserting a code row; the sendVerificationOTP callback that sends the email only runs...
The Client CSV Is the Single Source of Truth: C1 to C68, Handing Back Each Value One by One
To set the context: this is my own Boom Beach private server, client version 57.135. Besides the server, there’s a webclient that rebuilds base rendering and editing in the browser. The client ships its own complete set of csv/ — buildings, obstacles, decorations, traps, entries, globals — and even “how much gold it takes to remove this rock, how much wood it drops, what Headquarters level you need” is written in there. These things used to be copied separately into the engine and into the sh...
AI Can Write Features but Not Dockerfiles: Next.js Self-Hosting Pitfall Notes
Official docs referenced in this post: Next.js 自托管, Serwist, PM2 配置项, postgres 镜像说明 I’ve been self-hosting three or four Next.js projects back to back lately, so here’s a record of a few pitfalls I hit. Claude writes features amazingly fast — pages, tRPC routes, Prisma schemas all churned out in one go and they just run. But the moment deployment and wrap-up come around, it’s back and forth, the same file edited over and over. Everything below is the “build passes but it won’t run” category,...
When Multiple AIs Write Code Together, the Boundaries I Draw for Them
Lately, across a few projects, the same repo has been modified by two AI coding tools at once, plus a few people pushing code themselves… At first I figured it was no big deal — it’s all just writing code, right? But after stumbling through it, I found the problems were almost never in the code itself; they were in collaboration mechanics — “who read which set of rules,” “who can touch what on the machine.” Here I’m writing down the boundaries I eventually drew. First, a twist: the so-called...
9 Commits, Not a Single Human Author: After an AI Wrote an Entire Project Alone
Recently I took over a project someone dumped on me. I pulled it down with git log and paused for a second — 9 commits, all authored by the same AI Dev <ai-dev@local>, not a single human commit. I won’t paste hashes for the commits I mention below; I’ll just refer to them by what they did. The repo has no CLAUDE.md, no AGENTS.md, no .claude/, no .cursor/, no CI, lint is just tsc --noEmit, and tests are nonexistent. I spent a day going through it and jotted down what it did well and what...
Next.js Rendering Mode Troubleshooting Notes: force-dynamic, hydration, and No Database at Build Time
I’ve been writing several Next.js projects back to back lately. The features themselves went smoothly, but they all got stuck on the same class of problems: next dev works fine locally, then everything blows up the moment you build or deploy. Not one of these issues is “the code is wrong” — they’re all “the rendering mode isn’t set up right,” and the error messages usually point somewhere else entirely, which makes them a huge time sink… Here I’ll write down a few I’ve run into, with file lin...
Getting Claude to Make Fewer Data-Layer Mistakes: Prisma, Drizzle, and a Few Structured Practices
Recent projects each used Prisma, Drizzle, or skipped the ORM entirely and wrote raw SQL. The same AI makes completely different mistakes on each of the three—that surprised me quite a bit… On Prisma it writes “the correct way from the previous major version”; on Drizzle it gets stuck on types and API signatures; on raw SQL it has no idea what limitations that driver has. Here I’ll note down a few fallback practices I use along the schema-to-migration chain—just notes for myself. Prisma 7 / D...
My CLAUDE.md Is Only One Line: How Much Should a Convention File Actually Contain
I recently rewrote a Galgame resource site entirely from Hugo to Next.js. The repo is vns-next. From the initial commit create-next-app to being deployable, it took 13 commits over less than 20 hours. When I looked back through the repo afterward, I noticed something pretty funny — the convention file I wrote for Claude is just one line long. And I didn’t even write that line myself… This post isn’t about rendering modes or deployment. It’s only about one thing: “what conventions should you l...
