MinhVo

Minh Vo

rss feed

Slaying code & making it lit fr fr πŸ”₯ tagline

Hey there πŸ‘‹ I'm an AI Engineer with 7 years of experience building scalable web and mobile applications. Currently at Neurond AI (May 2025 β€” present), architecting an Enterprise AI Assistant Platform with multi-tenant RAG on pgvector, multi-provider LLM orchestration, and Azure-native infrastructure. Previously spent 5+ years at SNAPTEC (Sep 2019 β€” Apr 2025), leading SaaS themes, admin dashboards, and e-commerce platforms β€” earned the Hero of the Year award in 2021. I specialize in TypeScript, React, Next.js, and AI-Native engineering with Claude Code and Cursor.bio

May 26, 2026
  • Click-origin theme toggle β€” ported react-theme-switch-animation into this site: View Transitions + clipPath animation, flushSync inside startViewTransition, prefers-reduced-motion respected. More on /projects/react-theme-switch-animation.
  • Cloudflare edge stack on Astro 6 for hoatuoidanangnhanhi.com β€” one _worker.js/ bundles Pages Functions + Astro SSR + R2 media. See /projects/hoatuoidanangnhanhi. New patterns this round: centralized CSRF allow-list middleware, +84/0 phone normalization, edge s-maxage + SWR on prerendered sitemap XMLs, ctx.waitUntil(logError) for non-blocking error reporting.
  • RAG on the edge: Workers AI + Vectorize via Cloudflare AI Gateway β€” caching, rate limits, analytics in one config. Gotcha: "empty result" errors usually mean [ai] binding = "AI" is missing from wrangler.toml β€” Vectorize and Workers AI bindings are separate.
  • VN-first: store name + a diacritic-stripped search_name in D1. VietQR image URLs are HAR-traceable and cacheable β€” pin bank/account/amount server-side so the CDN can't poison the QR.
  • Cache-poisoning lesson: CDN cache keys must not vary on session cookies for public endpoints, or one authed POST poisons everyone's response.
  • Partytown moves analytics into a Web Worker; CI audit locks images to WebP.
  • Skill-first design beats monolithic agents β€” marlin-skill, sentinel-skill, Rotura: review patterns belong in Claude Code skills, not prompt strings.
  • Two takes on the Snorkel watcher: snorkel-watcher-bot (Python stdlib + Cognito refresh without boto3, ~50min token rotation, systemd on Azure B2pts) vs snorkel-watcher-desktop (~14 MB Electrobun + Bun + React, no VM). Reinforces the Electrobun-vs-Electron finding from March.
  • Portfolio refresh on Cloudflare Workers Builds β€” pattern routes retire sibling workers without breaking incoming links; gpt-image-2 via Azure OpenAI (/openai/deployments/<name>/images/generations?api-version=2024-02-01) handles hero portrait + OG images.
  • Tauri v2 rewrite of CodexBar produces signed .dmg + .AppImage + .msi from one Rust toolchain β€” a viable Electron alternative when you need real native binaries.
  • Subdomain SEO leak: dev/staging/uat get indexed unless per-subdomain robots.txt and X-Robots-Tag: noindex are both set.
  • cv now ships role-specific variants (backend NestJS, mobile) from one LaTeX source.
March 3, 2026
  • Released Capturia β€” open-source Screen Studio alt on Electron + PixiJS. PixiJS beats raw <canvas> for the editor preview (GPU cursor effects + zoom at 60fps). Details on /projects/capturia.
  • macOS unsigned-app unblock: xattr -rd com.apple.quarantine "/Applications/<App>.app" clears Gatekeeper without code-signing.
  • Shipped two takes on the same idea: GitAccountSwitcher (Swift/SwiftUI) vs git-account-switcher (Electrobun + Bun). Verdict: Electrobun installers ~10Γ— smaller than Electron, SwiftUI still wins first-paint and idle memory. See /projects/git-account-switcher.
  • Transactional credential switching: snapshot Keychain + git config + gh auth state before any write, replay the inverse on failure.
  • AES-256-GCM is the right call for encrypted JSON on disk β€” built-in auth tag means tampering surfaces as a decode error, no separate HMAC.
  • Built interview-coder + interview-assistant β€” invisible window via transparent frameless BrowserWindow + setContentProtection. See /projects/interview-coder.
  • models.dev (3,000+ LLMs with pricing/context) wired as a 3-tier fallback (provider API β†’ models.dev β†’ static) so the settings UI is never empty.
  • Karpenter NodePool limits: 0 during off-hours scale-down (otherwise Redis re-provisions a baseline node); ACR cleanup must abort on unreachable clusters or it cascade-deletes live images.
  • pg_trgm trigram index on managed Postgres replaces a third-party lib for tolerant Vietnamese search.
  • Astro on Cloudflare D1: always parameterize queries β€” never string-interpolate user content. $ collisions with PG-escape surface as cryptic errors.
  • AKS ingress-nginx pre-stop hook (lifecycle.preStop.exec: sleep 15) fixes rolling-deploy downtime by letting in-flight requests drain.
  • E2B sandbox templating: files uploaded to /home/user/ get baked into the snapshot β€” runtime mutations don't persist unless you snapshot again.
  • Karpenter/NAP doesn't auto-rebalance pods across nodes β€” only schedules new ones; need descheduler or PDB-driven rolling (caveat to the Feb entry).
  • resumable-stream: a cancelStream reusing the existing request channel beats opening a separate cancel topic (doubles Redis traffic).
  • Dangling asverify CNAMEs are a subdomain-takeover vector β€” sweep them on cert rotation.
February 14, 2026
  • AKS node-auto-provisioning (Karpenter for Azure) β€” spot VM types via min/max NodePools beat hand-sized node pools for cost; revisited again in the Mar 2026 entry for the rebalancing caveats.
  • Replaced static KUBE_CONFIG GitHub secret with Azure Login + AKS context (federated identity) across MeetingAgent + NeurondAssistantV3 β€” no long-lived secret, no kubeconfig drift after cluster recreation.
  • Vercel AI SDK v5 β†’ v6: rebuilt the orchestrator on ToolLoopAgent + human approval; prepareStep injecting persisted DB todo state so resumed turns don't reset tasks.
  • 57% Docker image shrink on the NeurondAssistantV3 runner β€” swap full TeX Live for TinyTeX, full Chrome for chrome-headless-shell, strip locales/perl, fc-cache so TinyTeX fonts work in the slim runtime.
  • Never put KeyVault secrets in $GITHUB_OUTPUT β€” they leak in logs if the masking matcher misses. Write to $GITHUB_ENV. A composite Action parallelizes az keyvault secret show for fan-out reads.
  • MS Teams Adaptive Card schema is mandatory β€” sending an Office-365 connector JSON renders the literal string "Card" instead of content.
  • Built google-labs β€” FastAPI shim exposing Google ImageFx (Imagen 4 + Nano Banana) behind OpenAI-compatible /v1/images/generations and /image-edit for drop-in adoption.
  • Experimented with AI-DLC + Spec-Driven Development to scaffold a full Medusa storefront β€” parallel agent teams only work when each team has an isolated workspace + its own test run.
  • x-forwarded-proto / x-forwarded-host are comma-separated when proxied β€” always split(',')[0].trim() for origin checks.
  • chrome-devtools MCP is the right tool for "why is staging down" β€” HAR + console + network in one call. Also tried ascii-motion MCP for image-to-terminal animations.
  • Cloudflare Durable Objects can no longer be provisioned from the dashboard β€” must go through Wrangler config.
December 16, 2025
  • Shipped phatnguoi β€” Vietnam phαΊ‘t nguα»™i lookup on Next.js 15 + MongoDB. Key wins: a canonical key normalizing six VN plate formats, and token-signed unsubscribe URLs so the opt-out flow stays stateless. More on /projects/phatnguoi.
  • Vercel Cron + Nodemailer for daily diff alerts β€” fan out only on new rows, never the full snapshot.
  • React 19 + App Router on minhomega-dev and minhvo: useFormStatus + server actions kill most form boilerplate.
  • From suburbia-skate: Matter.js is much happier when the physics sim is decoupled from the render loop.
  • Built nanabanana β€” Cloudflare Worker proxy for image-gen with Redis-backed rate limiting + request multiplexing so identical concurrent requests collapse to one upstream call.
  • Confirmed the 431 header root cause is NextAuth chunked JWT cookies on custom domains β€” swapping to a DB-backed adapter drops session headers to a single cookie (continuation of the Nov 2025 finding).
  • Service workers silently cache POST responses when the route returns cacheable headers β€” app/sw.ts is the first place to check when "auth works in incognito but not normally".
  • Helm atomic: true: if the initial install fails there's no release to roll back, so retry breaks unless you helm uninstall first.
  • Streaming-aware editor pattern: read-only while the server streams, switch to editable on completion β€” prevents collapsed sections from re-mounting open on every chunk.
  • Dynamic favicon/PWA-icon route for per-tenant SEO branding; Next 16 static-by-default silently breaks multi-tenant theming unless you set dynamic = 'force-dynamic' per layout that reads tenant cookies.
  • Pin @openrouter/ai-sdk-provider to a commit hash; latest ships breaking changes regularly.
November 21, 2025
  • Bootstrapped communal β€” P2P rental marketplace on Next.js 16 + better-auth + Biome + React Compiler. Radix UI needs dynamic() imports to dodge SSR hydration mismatch.
  • Three payment gateways side-by-side in communal β€” PayFast, Yoco, Stripe Connect β€” abstracted behind a gateway-agnostic checkout; Redis for cache + real-time chat.
  • Shipped antisocial β€” Schema.org structured-data audit engine on BullMQ + Playwright (stealth) + Cheerio + Postgres + GCS, with Cloudflare-challenge detection helpers.
  • Spun up microservices β€” NestJS modular DI across services with a dedicated notification transport.
  • LiteLLM in front of Claude Code lets the agent transparently swap Anthropic ↔ OpenRouter/local providers with zero agent-side changes.
  • Next.js 15 App Router: params is now a Promise β€” await or React.use() before reading .slug, or the type errors silently rot.
  • better-auth kills the __Secure-authjs.session-token.* cookie explosion β†’ 431 Request Header Fields Too Large. DB-backed adapter drops session headers to one cookie.
  • Drizzle db:generate diffs against the migrations folder β€” wipe it to force a clean baseline SQL when the chain has drifted past repair.
  • Started migrating NeurondAssistantV3 editor Monaco β†’ CodeMirror 6 β€” CodeMirror's transaction model survives streaming token updates without nuking fold state.
  • Added tokenlens for provider-agnostic token-usage + cost telemetry; no hand-rolled per-model price table needed.
  • bunx --bun shadcn@latest add <component> is faster than pnpm dlx and avoids npx version drift.
October 1, 2025
  • Explored Google A2A (Agent-to-Agent) for multi-agent coordination, OpenAI Agent Builder for tool-integrated workflows, and Google Opal for enterprise AI app deploys.
  • Built a LangGraph human-in-the-loop POC and a comprehensive MCP tool hub for standardized agent tool integration.
  • Adopted Biome as the single lint+format toolchain across a Turborepo (shared packages/config/biome) β€” drops ESLint/Prettier, the single-binary perf is real.
  • LaTeX-to-PDF chat route: @monaco-editor/react needs a hand-registered Monarch tokenizer for TeX β€” Monaco ships no highlighting by default.
  • Docker CI split into Dockerfile.base (weekly β†’ ACR) + Dockerfile (per-commit, base as cache layer) β€” slashes rebuild time on shared deps.
  • supercronic is the right cron-as-PID-1 inside Docker; Puppeteer still needs apt-installed Chromium even with it.
  • TipTap editor coverage requires mocking ProseMirror plugin state β€” TipTap reaches into a real DOM/Schema and breaks under jsdom.
August 1, 2025
  • Built an autolabeling system inspired by Roboflow using FastAPI backend and Next.js frontend for computer vision data annotation workflows. Link: Roboflow
  • Learned about computer use patterns and applied them in real-world scenarios: screen understanding, UI automation, and task execution pipelines.
  • Enhanced Next.js expertise: defined custom conventions for API routes, middleware patterns, and contributed to a status page for a chat application.
  • Studied context engineering and prompt engineering techniques: chain-of-thought, few-shot learning, and retrieval-augmented generation patterns.
  • Read extensively about software architecture and design patterns: microservices, event-driven architecture, monitoring strategies, and observability tools.
May 13, 2025
  • Kicked off a new AI project: explored RAG architectures (chunking, embeddings, retrieval, reranking) and evaluation loops.
  • Integrated Vercel AI SDK with multi-provider adapters (OpenAI, Anthropic, Google Gemini) for a flexible chatbot pipeline.
  • Studied agentic workflows: tool calling, memory, and multi-step planning; experimented with n8n for orchestration and OCR pipelines.
  • Researched model finetuning and OCR stacks (Tesseract, PaddleOCR); designed a data labeling -> finetune -> evaluate workflow for domain tasks.
April 11, 2025
  • Learned Electron.js fundamentals: main vs renderer processes, IPC channels, preload scripts for secure context bridging.
  • Built an Electron app named "Interview Coder" and published the repo. Link: Interview Coder
  • Practiced packaging and auto-updates: electron-builder, code signing basics, and app distribution channels (macOS notarization overview).
  • Explored Electron tooling and patterns: contextIsolation, sandbox, custom protocol handlers, and secure file access permissions.
February 20, 2025
  • Explored monorepo architecture patterns with Nx and Turborepo; compared generators, task graph, and caching. Links: Nx, Turborepo
  • Studied micro-frontend composition using Webpack Module Federation, including shared dependency versioning and runtime remotes. Link: Module Federation
  • Prototyped a codebase layout: apps/ + packages/ with shared UI, utils, and typed API clients; enforced with TS project references.
  • Set up CI for monorepos: remote cache, affected-graph builds, and release workflows (conventional commits + changelogs) to streamline multi-app deployments.
February 11, 2025
  • Dove deep into the Native code module in React Native. Tried some new code with SwiftUI to create a simple login screen.
  • Learned and tried IndexedDB in web development via the Dexie.js library.
  • Learned about RAG (Retrieval-Augmented Generation) and how to use it in web development.
January 21, 2025
  • Learned about new features of Next.js 15 and how to use them.
  • Built a site to help the community learn the new tech stack.
  • Reading the book "Grokking Algorithms" to learn about algorithms and data structures.
December 10, 2024
  • Working on the Zalo Mini App to create a simple app related to games and content for the local food business event.
  • Successfully published the app on the Zalo Mini App platform with ExpressJS backend and Google Sheets for data management.
  • Learned about game development using canvas and third-party libraries, focusing on 2D games.
August 30, 2024
  • Dived deep into native code for building a mobile app with React Native.
  • Learned about building a library for React Native with native code via third-party libraries and publishing it on NPM.
August 4, 2024
  • Learning about Next.js 14 and modern web development to prepare for my new project.
  • Learning about NestJS and TypeORM for building a backend service.
  • Learning about system architecture and DevOps for deploying backend services to AWS.
July 22, 2024
  • Learned about the Go language and how to build a simple GitHub Action using the Go language.
June 23, 2024
  • Learned about how to build and publish a library on NPM.
  • Successfully published the library on NPM with documentation and CI/CD for testing/publishing.
  • Created GitHub tags for the release of the library and release notes.
March 10, 2024
  • Learned about full-stack web development with Next.js 14 and Prisma ORM.
  • Rebuilt my SaaS project with the new tech stack and improved the architecture.
  • Learned the basics of deploying a full-stack web app to AWS, configuring services like S3, EC2, RDS, CloudFront, CloudWatch, etc.
January 10, 2024
  • Learned about Python coding for crawling data from other websites.
  • Used CI/CD with GitHub Actions for deploying my project.