From your commit to your LinkedIn
Six real examples of the full flow: the source that inspired the post (a commit, a framework decision, an RSS article), the draft commitvoice generated, and the final version the author edited and shipped. Zero editorial polish outside the editor.
- 01
The "I'll fix it later" that already cost you hours
SourceFramework docdocs/session-log/lessons/lesson-27-the-gate-is-the-floor.mdeamg-globalint/commitvoiceTwo floors of validation separate "code written" from "code delivered": the gate (typecheck + tests + build) and preview validation. Skipping the gate produces a specific class of failures — typos in type unions, removed SDK deps, tests pinned to old constants — that accumulate invisibly until an audit uncovers them all at once.
Draft generated by commitvoiceAspirational scaffolding. It looks generic on purpose — the LLM starts close to "average AI" until the author works it.
🚀 Let's reflect on the importance of quality in software development. In the world of software, maintaining high standards is fundamental. That's why on our team we follow a rigorous process before every commit: ✅ Type checking ✅ Automated tests ✅ Production build This helps us prevent errors and deliver value to our users. What's your QA process? 🤔 #SoftwareDevelopment #QualityAssurance #BestPractices
Published versionIn the author's voice, with citable evidence. This is what their audience sees on LinkedIn / X.com.
An audit surfaced 5 type debts in my working tree that had been there for weeks. None of them were introduced by the commit I was reviewing. They all piled up before — every time I extended a union type, swapped an SDK, or moved a constant, without running the full gate. The gate is three commands: pnpm typecheck pnpm exec vitest run pnpm build If all three are green, the code qualifies as "shipped." If any fails, it's not ready yet — no matter how well it runs on my machine. Important framing: the gate isn't "best practice." It's the compilation floor. What sits below it isn't shippable code; it's in-progress code that doesn't know it yet. The cost of running it now is 90 seconds. The cost of not running it is a 2-hour forensic session three weeks later, trying to attribute which of 18 commits introduced the debt. Wrote it down as a permanent lesson for the project — source below.
- 02
The rule that changed how I direct AI agents
SourceFramework docdocs/session-log/lessons/lesson-18-ai-is-a-collaborator-not-an-apprentice.mdeamg-globalint/commitvoiceA directive that forces the author to approve every mechanical phase transition is the failure relocated from the entry layer to the execution layer. The AI runs the directive end-to-end, decides every judgment call citing the lesson/spec/declarative that justified it, emits a Decisions Log, and stops only under three exceptions — E1 unresolvable contradiction, E2 required input genuinely absent, E3 irreversible destructive operation.
Draft generated by commitvoiceAspirational scaffolding. It looks generic on purpose — the LLM starts close to "average AI" until the author works it.
AI is our best ally for modern productivity. To get the most out of it, the key is to set up a continuous review process: check each step the agent proposes, validate every decision, and adjust course as it goes. In my experience, the human + AI combo works best when there's constant supervision and immediate feedback. How do you handle your AI collaboration? #AI #Productivity #Leadership
Published versionIn the author's voice, with citable evidence. This is what their audience sees on LinkedIn / X.com.
I stopped my agent 11 times in one session to "approve the next step." Each stop was a mechanical transition. The agent already knew what was next — I was the slow part of the flow. What changed everything was making explicit the only three legitimate reasons to stop: E1 — unresolvable contradiction between two corpus documents. E2 — required input that genuinely does not exist. E3 — irreversible destructive operation. If the stop doesn't fall into E1, E2, or E3, it's not a stop — it's a request for reassurance dressed up as governance. And it doubles the time of any task. The healthy version: the agent runs the directive end-to-end, decides every judgment call citing what lesson/spec/declarative justified it, and emits a Decisions Log inside the deliverable. I review once, at the end — accept, or reject naming the specific failure mode. That's the difference between directing a collaborator and supervising an apprentice.
- 03
Why we didn't put Redis in front of Postgres
SourceCommitapps/api/src/services/scheduler.ts@ 3f0a812eamg-globalint/commitvoicefeat(scheduler): atomic claim via UPDATE ... WHERE status='scheduled' RETURNING — replaces SELECT FOR UPDATE pattern. Two workers competing for the same row cannot both win; the loser sees zero rows returned and yields. No Redis layer in front; business state must remain authoritative in Postgres per domain-rules §6.
Draft generated by commitvoiceAspirational scaffolding. It looks generic on purpose — the LLM starts close to "average AI" until the author works it.
In the microservices era, caching is our best friend for boosting performance. Today I want to talk about how Redis can transform your architecture. Benefits of Redis: ⚡ Ultra-fast speed 🔄 Reduced DB load 📈 Improved scalability At commitvoice we make careful architecture decisions to guarantee performance and reliability. What caching tools do you use? #Backend #Performance
Published versionIn the author's voice, with citable evidence. This is what their audience sees on LinkedIn / X.com.
Three queries I deliberately left uncached: 1. Post status (draft / scheduled / publishing / published). 2. scheduled_at on every publication. 3. publish_attempt_count. All three are business state. All three are correctness-sensitive. A stale read of status="scheduled" while the row has actually moved to "publishing" is exactly how double-publishes happen. Redis is for queues (BullMQ) and rate limiting. Not for business data. The latency I'd gain by caching those fields doesn't offset the cost of a single double-publish: a customer who sees their post twice on LinkedIn loses trust in the product in seconds. The atomic claim is one query: UPDATE schedules SET status = 'publishing' WHERE id = $1 AND status = 'scheduled' RETURNING *; Two workers competing for the same schedule can't both win. The loser gets zero rows back and yields. Zero duplicates, zero distributed coordination, zero extra software layer. The cheap thing isn't Redis. The cheap thing is Postgres doing its job.
- 04
Your library is a graveyard. Your inbox is a promise.
SourceArchitecture Decision Recorddocs/decisions/0019-inbox-as-triage-flow.mdeamg-globalint/commitvoiceWhen a data collection grows beyond a handful of rows, the "library" shape — list + filter pills by origin — stops answering the user's real question. The right shape is an inbox: items with a triage state, default view shows only unprocessed, every row offers a primary verb, the sidebar counts what's left. Library thinking makes users open the same 35 items every day. Inbox thinking gives them a finish line.
Draft generated by commitvoiceAspirational scaffolding. It looks generic on purpose — the LLM starts close to "average AI" until the author works it.
UX matters! Today I want to share a thought on how we design data collections in our products. There are two main approaches: list with filters, or inbox with states. Each has pros and cons. What matters is understanding the user and picking the one that best fits their needs. At commitvoice we chose a user-centered approach. How do you think about list UX? #UX #ProductDesign
Published versionIn the author's voice, with citable evidence. This is what their audience sees on LinkedIn / X.com.
I shipped my "sources" feature as a library: 35 items, repo filters, click for preview, a "Create post" button on every detail pane. Opening the tab felt the same every day. Same 35 items. I couldn't tell new from old. What I'd already used didn't look different from what was pending. After three weeks I rewrote the screen as an inbox: — A state per item (new / archived / saved / in use). — Default view: only the "new" ones. — Every row offers a primary verb (dismiss, save, send to editor). — Sidebar badge: number of unprocessed items. That last line is what changed how the feature felt. It went from "endless list" to "finish line." When the badge drops to zero, I'm done. When it goes back to 5, I know exactly what's new. Library thinking makes you open the same 35 items every day. Inbox thinking makes you a promise: if you triage, you finish. If your collection grows beyond a handful of rows, the decision isn't "what filters do I add." It's "what triage states make sense."
- 05
Why I run my SaaS on a single €15/mo Hetzner box
SourceArchitecture Decision Recorddocs/decisions/0010-self-host-first.mdeamg-globalint/commitvoiceSelf-host first, managed services second. Evaluate self-host honestly. Name the moat a managed service would provide. Pick managed only when the moat justifies the added subprocessor. Postgres self-hosted on Hetzner — Neon/Supabase branching/autoscale don't justify the cost for a single-operator load. Redis same. Image storage local filesystem. LinkedIn publishing managed (Make.com) — real moat: compliance + OAuth review.
Draft generated by commitvoiceAspirational scaffolding. It looks generic on purpose — the LLM starts close to "average AI" until the author works it.
The cloud gives us superpowers! Today I want to share my stack for running a productive SaaS. I use a mix of managed services for maximum flexibility and scalability. My stack includes: ☁️ Cloud DB 🔄 Cache as a service 📦 Object storage 🚀 Edge functions Each tool has its role and together they make a robust platform. What's your favorite stack? #SaaS #CloudComputing
Published versionIn the author's voice, with citable evidence. This is what their audience sees on LinkedIn / X.com.
commitvoice runs on a €15/mo Hetzner VM. Postgres, Redis, API, web UI, image storage — all on the same machine. It's not asceticism. It's moat discipline. Every time we evaluate a managed service we ask one question: what moat does it give me that self-host cannot match? — Managed Postgres (Neon, Supabase) → branching + autoscale. Not needed at my scale. Self-host. — Managed Redis → multi-AZ HA. Not needed yet. Self-host. — S3/R2 storage → global throughput + lifecycle policies. When local filesystem is a real problem, I migrate. Self-host. — Make.com as a publishing bridge to LinkedIn → compliance + LinkedIn OAuth review. Real moat. Managed. Simple rule: every managerial SaaS I add is one more risk surface, one more invoice, one more vendor lock-in, one more account whose credentials I have to rotate. I add it only when the moat is genuine and nameable. It's not "I'm hardcore." It's that every managed decision has to defend itself against a concrete self-host alternative. Most don't.
- 06
X.com thread on the client who switched providers
SourceRSS articlehttps://bytes.dev/archives/362Bytes by Tyler — newsletterBun 1.2 ships a faster bundler with native CSS, eliminates the need for Vite in many SPA setups. Benchmarks show 3-4x cold start improvement vs Vite + esbuild stack on medium-sized React apps. Migration involves swapping bun build flags; the breaking change surface is small.
Draft generated by commitvoiceAspirational scaffolding. It looks generic on purpose — the LLM starts close to "average AI" until the author works it.
Big news from Bun 1.2! 🚀 The bundler got 3-4x faster and now supports native CSS. This is a game changer for the JavaScript ecosystem. Thinking about migrating from Vite to Bun? I'd love to hear your take! 💭 #JavaScript #WebDev #Performance #Bun
Published versionIn the author's voice, with citable evidence. This is what their audience sees on LinkedIn / X.com.
1/ Bun 1.2 shipped a bundler with native CSS and benchmarks 3-4x vs Vite+esbuild on medium SPAs. Gut take: not migrating. Sharing why. 2/ My local Vite build takes 1.8s. If it dropped to 0.5s, the change would be invisible: I'm in HMR 95% of the time, not cold start. 3-4x sounds huge. In absolute seconds: 1.3s saved per build. ~5 fresh builds a day. ~7s daily. 3/ The real cost isn't the tech migration (small). It's the new bug surface. Vite has 5 years of closed issues on my specific stack (React + Tailwind + MDX + Astro plugins). Bun will have its own list — not worse, but different. 4/ When I would migrate: — CI cold start > 2 min (not my case, 28s). — Large team where aggregate build time > 1h/day. — I need the Bun runtime for another reason (workers, FFI). 5/ Rule: a 3x improvement on something that's no longer the bottleneck is bait. New stuff is interesting for being new, not for solving a real problem. Newsletter quote ↓
Want to see your commit here?
Connect your repo, pick the RSS categories you care about, and ship your first post in under 5 minutes. No card, no lock-in.