


[{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/cloudflare/","section":"Tags","summary":"","title":"Cloudflare","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/dev-notes/","section":"Tags","summary":"","title":"Dev-Notes","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/","section":"Dorm Room Dev","summary":"","title":"Dorm Room Dev","type":"page"},{"content":"This blog went live tonight. Not on the nice domain, though — on blog.sp1128node.duckdns.org:9443, port number and all, because that\u0026rsquo;s where Caddy serves it on my little VPS. The last step was supposed to be the easy one: point blog.sp1128.top at the box through Cloudflare, add one Origin Rule to rewrite the origin port to 9443 (port 443 on the origin belongs to a different service), and enjoy the clean URL.\nIt took three attempts. All three failures were mine.\nSymptom # DNS record added (proxied, pointing at 198.44.52.74). Origin Rule created: if hostname is blog.sp1128.top, rewrite origin port to 9443. Open https://blog.sp1128.top:\nError 525 — SSL handshake error.\nCloudflare could reach the origin, but the TLS handshake died. Meanwhile the blog itself was perfectly healthy on the duckdns URL, certificates and all. So the origin could do TLS — just not for this hostname.\nThe detour # First suspect: Caddy simply had no certificate for blog.sp1128.top. That part was true. When the blog was installed a few hours earlier, the hostname didn\u0026rsquo;t exist in DNS yet, and the Caddy log said so in plain language:\nchallenge failed … \u0026#34;detail\u0026#34;:\u0026#34;DNS problem: NXDOMAIN looking up A for blog.sp1128.top\u0026#34; Fine — DNS exists now. Restart Caddy, let ACME do its thing, done. Except: still 525. A caddy reload didn\u0026rsquo;t even try — it answered \u0026ldquo;config is unchanged\u0026rdquo; and skipped re-issuance entirely. Only a full container restart forced a fresh attempt.\nAnd the fresh attempt failed again, with much more interesting logs.\nRoot cause # http-01: \u0026#34;detail\u0026#34;:\u0026#34;… Invalid response from http://blog.sp1128.top/.well-known/acme-challenge/…: 400\u0026#34; tls-alpn-01: \u0026#34;detail\u0026#34;:\u0026#34;Cannot negotiate ALPN protocol \\\u0026#34;acme-tls/1\\\u0026#34; for tls-alpn-01 challenge\u0026#34; Probing the challenge URL by hand returned the smoking gun — a 400 whose body was Caddy\u0026rsquo;s TLS port saying:\nClient sent an HTTP request to an HTTPS server. My Origin Rule rewrote the origin port for every request to blog.sp1128.top — including plain HTTP. Let\u0026rsquo;s Encrypt\u0026rsquo;s HTTP-01 validation is a plain-HTTP GET. Cloudflare dutifully fetched it from the origin at port 9443, where Caddy only speaks TLS. Plaintext hit a TLS port, got a 400, validation failed — forever. TLS-ALPN-01 was no rescue either; the proxy in the middle can\u0026rsquo;t negotiate the acme-tls/1 ALPN protocol.\nThe server itself was innocent: minutes earlier, the exact same HTTP-01 flow had issued a certificate for the duckdns hostname, which reaches the origin directly (served key authentication → certificate obtained successfully). The only broken path was the one through my own rule. The certificate couldn\u0026rsquo;t be born because the rule I wrote to serve the site was eating the midwife\u0026rsquo;s requests.\nOne more trap on the way out: my first fix attempt, (http.host eq \u0026quot;blog.sp1128.top\u0026quot; and http.request.scheme eq \u0026quot;https\u0026quot;), was rejected by Cloudflare\u0026rsquo;s validation — http.request.scheme is not a field that exists at the Origin Rules stage.\nThe fix # Scope the rule to HTTPS requests only, using the boolean field that Origin Rules actually offer:\n(http.host eq \u0026#34;blog.sp1128.top\u0026#34; and ssl) Now HTTPS traffic gets its port rewritten to 9443, while plain-HTTP traffic stays on port 80 — where the HTTP-01 challenge needs to land. Restart Caddy once more (docker restart panels-caddy-1), and about 90 seconds later the log had the line I wanted:\n\u0026#34;certificate obtained successfully\u0026#34;,\u0026#34;identifier\u0026#34;:\u0026#34;blog.sp1128.top\u0026#34;, \u0026#34;issuer\u0026#34;:\u0026#34;acme-v02.api.letsencrypt.org-directory\u0026#34; curl https://blog.sp1128.top → 200. Clean URL, real Let\u0026rsquo;s Encrypt certificate, auto-renewed by Caddy from here on — and renewals will keep passing HTTP-01 precisely because the rule no longer touches HTTP.\nThe lesson # A rule that rewrites where traffic goes must be scoped as narrowly as possible — by scheme, by path, by everything you can name. An unscoped rule doesn\u0026rsquo;t just serve your site; it intercepts everything that merely mentions your site, including the certificate authority knocking on the front door.\n","date":"24 October 2026","externalUrl":null,"permalink":"/posts/cloudflare-525-origin-rule-acme/","section":"Posts","summary":"My blog was already live — on the ugly URL with a port number. Moving it to blog.sp1128.top took three attempts, because the Cloudflare Origin Rule I wrote to serve the site kept eating the Let’s Encrypt challenges its own certificate depended on.","title":"Error 525: The Origin Rule That Ate My Own Certificate","type":"posts"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/self-hosting/","section":"Tags","summary":"","title":"Self-Hosting","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/ssl/","section":"Tags","summary":"","title":"Ssl","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/ai/","section":"Tags","summary":"","title":"Ai","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/claude/","section":"Tags","summary":"","title":"Claude","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/claude-code/","section":"Tags","summary":"","title":"Claude-Code","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/cli/","section":"Tags","summary":"","title":"Cli","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/devtrack/","section":"Tags","summary":"","title":"Devtrack","type":"tags"},{"content":"Standup. Every morning. \u0026ldquo;What did you do yesterday?\u0026rdquo;\nAnd me, every morning, staring at the ceiling trying to reconstruct my own day. I shipped stuff! There were commits! I just couldn\u0026rsquo;t tell you what they were without opening four different tools.\nSo I built the tool I wanted: DevTrack.\n→ GitHub: github.com/sp1128/DevTrack\nWhat it does # DevTrack is a local CLI that hooks into Claude Code and quietly records your dev activity as you work:\nSessions and active coding time Files changed (Claude\u0026rsquo;s edits plus git working-tree changes) The important commands you ran — tests, builds, installs — with secrets scrubbed out Git commits: branch, message, files touched, lines added/removed Tasks, inferred from Claude\u0026rsquo;s task tools or from your commits Then it answers the standup question directly:\nnpm install -g devtrack devtrack init claude # work like normal — DevTrack records in the background devtrack today # what did I actually do today? There are week and month views, a Markdown weekly report you can paste anywhere (with an optional AI summary), and an activity heatmap for when you want to feel something about your own consistency.\nThe part I care about most # Everything stays on your machine. No account, no cloud sync, no analytics. Your dev history is yours. DevTrack doesn\u0026rsquo;t modify the Claude Code client either — it just listens to the hooks Claude Code already exposes.\nWhen I demo\u0026rsquo;d it for the video, it showed my day back to me: 19 active minutes in the test session, 3 files, 2 commits, 4 commands — including the build that failed. Especially the build that failed. That\u0026rsquo;s the stuff I always forget by the next morning, and it\u0026rsquo;s exactly what a standup is supposed to surface.\nTry it # It\u0026rsquo;s MIT-licensed and on npm. If you live in Claude Code and your standups sound like mine, give it a spin — issues and PRs welcome.\nThe video version of this post is on my TikTok: @dormroomdev.\n","date":"24 October 2026","externalUrl":null,"permalink":"/posts/devtrack/","section":"Posts","summary":"Standup kept asking what I shipped yesterday, and I kept blanking. So I built DevTrack — a local CLI that tracks my Claude Code sessions, commits and commands, then writes my daily summary and weekly report for me.","title":"DevTrack: I Built a CLI That Remembers What I Did Yesterday","type":"posts"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/gamedev/","section":"Tags","summary":"","title":"Gamedev","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/github/","section":"Tags","summary":"","title":"Github","type":"tags"},{"content":"Ask an AI assistant to evaluate your startup idea and watch what happens. It finds a market. It invents a TAM. It lists ten features and tells you the idea has \u0026ldquo;strong potential.\u0026rdquo;\nThat is the single least useful response possible at the exact moment you\u0026rsquo;re deciding whether to spend three months of your life on something.\nSo I built the opposite. It\u0026rsquo;s called idea-review, a skill for Claude:\n→ GitHub: github.com/sp1128/idea-review\nHow it works # You hand it a raw idea. Before judging anything, it researches — real searches, in that session, not the model\u0026rsquo;s memory. And it deliberately hunts for disconfirming evidence: \u0026ldquo;why did X fail\u0026rdquo;, \u0026ldquo;X alternative\u0026rdquo;, the graveyard posts.\nThen it writes you two files:\n\u0026lt;idea\u0026gt;-feasibility.md — the idea restated, research findings, a 7-dimension scorecard, a one-sentence verdict, and \u0026ldquo;how this most likely dies.\u0026rdquo; If a mature free alternative already exists, that\u0026rsquo;s the opening paragraph, not a footnote. \u0026lt;idea\u0026gt;-tasks.md — if (and only if) the verdict isn\u0026rsquo;t \u0026ldquo;no\u0026rdquo;: a dependency-ordered build plan, tasks sized half a day to two days, each with acceptance criteria a coding agent can actually check. Every market number carries a source link. No source? It writes \u0026ldquo;no reliable public data\u0026rdquo; instead of making one up.\nFirst test: \u0026ldquo;an app that pays you to walk\u0026rdquo; # Sounds harmless, right? The skill dug in and came back with 17/35 — Don\u0026rsquo;t build it.\nThe receipts:\nSweat Economy — the biggest player in this exact space — just announced it\u0026rsquo;s shutting down on Dec 30, 2026. Their CEO\u0026rsquo;s words: \u0026ldquo;no sustainable profitability.\u0026rdquo; Real-world earnings for walkers: roughly $0.03–0.12 per day. That\u0026rsquo;s the whole business model. STEPN is down ~99%. Step App shut down in August 2026. Pay people for steps and you don\u0026rsquo;t get users, you get bot farms spoofing steps — and handing out cash makes you a money transmitter, with the licensing that implies. No tasks file for this one. The skill skips it on a \u0026ldquo;don\u0026rsquo;t build\u0026rdquo; verdict, which is the entire point: a plan for a dead idea is just a slower way to find out.\nInstall it # git clone https://github.com/sp1128/idea-review.git ~/.claude/skills/idea-review Bring it your favorite idea. Bring a thick skin too.\n","date":"24 October 2026","externalUrl":null,"permalink":"/posts/idea-review/","section":"Posts","summary":"Ask any AI if your app idea is good and it’ll throw you a party. I built idea-review to do the opposite: research first, lead with the bad news, and say ‘don’t build it’ when that’s the honest answer. First test case inside.","title":"I Built a Skill That Tells You NOT to Build Your App Idea","type":"posts"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/idea-review/","section":"Tags","summary":"","title":"Idea-Review","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/meta/","section":"Tags","summary":"","title":"Meta","type":"tags"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/projects/","section":"Tags","summary":"","title":"Projects","type":"tags"},{"content":"New series, every Friday: Weekly AI Flex. The format is simple — I let AI build something it shouldn\u0026rsquo;t be able to, then I test it for real.\nEpisode 1 is the one-sentence challenge:\nBuild me a game.\nThat\u0026rsquo;s it. That\u0026rsquo;s the prompt. What came back was a playable neon asteroid shooter — movement, shooting, waves of asteroids, the works — as one single HTML file. No game engine, no build step, no assets. Open it in a browser and play.\nThen I pushed it, because episode 1 needed a twist: now add a boss fight. It did. The boss has health phases, attack patterns, and it absolutely killed me on my first run. On camera.\nWatch it:\n🎵 TikTok: One Sentence. One Game. 📘 Facebook: the same episode as a Reel The honest takeaway isn\u0026rsquo;t \u0026ldquo;AI is magic.\u0026rdquo; It\u0026rsquo;s that the gap between a sentence and a thing you can play has basically collapsed — if you know how to ask, and how to test what you got back. That\u0026rsquo;s the skill I\u0026rsquo;m practicing in this series, one Friday at a time.\nNext episode drops Friday. Every Friday, I let AI build something it shouldn\u0026rsquo;t be able to.\n","date":"24 October 2026","externalUrl":null,"permalink":"/posts/weekly-flex-ep1-one-sentence-one-game/","section":"Posts","summary":"New Friday series: I give AI one sentence and see if it can build something it shouldn’t be able to. Episode 1 — a playable neon asteroid shooter with a boss fight, in a single HTML file.","title":"Weekly AI Flex, Ep. 1: One Sentence. One Game.","type":"posts"},{"content":"","date":"24 October 2026","externalUrl":null,"permalink":"/tags/weekly-ai-flex/","section":"Tags","summary":"","title":"Weekly-Ai-Flex","type":"tags"},{"content":"This blog is open. Same person as the TikTok (@dormroomdev), same rule I\u0026rsquo;ve had since day one:\nIf I haven\u0026rsquo;t run it, I don\u0026rsquo;t post it.\nHere\u0026rsquo;s why. Open-source Twitter and TikTok are full of accounts posting \u0026ldquo;10 GitHub repos that will blow your mind\u0026rdquo; — and half the time, the person posting never cloned a single one. The README looks great, the demo GIF looks great, and then you install it and it doesn\u0026rsquo;t even start. I\u0026rsquo;ve wasted enough evenings on repos like that.\nSo my process is boring on purpose:\nClone the repo. Run whatever the README says to run. Actually use the thing — click the buttons, run the commands, break it if I can. Only then make the video. It costs me an extra hour per video. It\u0026rsquo;s also the whole point. When I say a tool is fast, it\u0026rsquo;s because I watched it be fast. When I say \u0026ldquo;skip this one,\u0026rdquo; it\u0026rsquo;s because it crashed on me, not because the vibes were off.\nWhat this blog is for # TikTok is 50 seconds. That\u0026rsquo;s enough for a demo and a verdict, but not enough for the interesting stuff — the setup gotchas, the \u0026ldquo;here\u0026rsquo;s what actually died when I ran it,\u0026rdquo; the longer comparisons. That\u0026rsquo;s what goes here.\nExpect three kinds of posts:\nRepo write-ups — the long version of my tutorial videos, with the commands and the caveats. My own projects — stuff I build, like DevTrack and idea-review. Building in public, including the parts that don\u0026rsquo;t work yet. Weekly AI Flex — every Friday I let AI build something it shouldn\u0026rsquo;t be able to. The blog post gets the behind-the-scenes version. One post a day is the goal, matching the videos. If a repo isn\u0026rsquo;t worth your time, I\u0026rsquo;ll say so here too — just with more receipts.\nFirst project post is already up: DevTrack, the CLI I built because I kept blanking at standup.\n","date":"24 October 2026","externalUrl":null,"permalink":"/posts/why-i-run-every-repo/","section":"Posts","summary":"This blog is open. The rule here is the same as on my TikTok: if I haven’t run it, I don’t post it.","title":"Why I Run Every Repo Before I Post About It","type":"posts"},{"content":"🎓 CS undergrad | I run repos before I post ⭐ Daily GitHub tutorials\nI\u0026rsquo;m a computer science undergrad posting daily videos about GitHub open source — every repo gets cloned, run and honestly reviewed before it gets a video. On Fridays, Weekly AI Flex: I let AI build something it shouldn\u0026rsquo;t be able to.\nThis blog is the long-form companion: write-ups with the commands, the caveats, and the receipts.\nElsewhere\nTikTok: @dormroomdev Facebook: Dorm Room Dev GitHub: sp1128 — home of DevTrack and idea-review ","externalUrl":null,"permalink":"/about/","section":"Dorm Room Dev","summary":"About Dorm Room Dev","title":"About","type":"page"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]