56,966 blogs · [
{
"id": "01a0e44a-c848-7133-8b0b-7a8358b7f07f",
"title": "The Programming Books I Still Recommend After 15 Years",
"url": "https://belderbos.dev/blog/timeless-programming-books/",
"published_at": "2026-09-26T00:00:00+00:00"
},
{
"id": "01a0d567-0b77-737e-b14f-4710e7071354",
"title": "Ship Your First Python App: a Free Course on the Local Dev Workflow",
"url": "https://belderbos.dev/blog/free-python-foundations-course-local-dev-workflow/",
"published_at": "2026-09-19T00:00:00+00:00"
},
{
"id": "01a0d567-0b77-737e-b14f-4710e7db862e",
"title": "Protocol or ABC? Designing a pluggable provider interface",
"url": "https://belderbos.dev/blog/protocol-vs-abc-provider-interface/",
"published_at": "2026-09-18T00:00:00+00:00"
},
{
"id": "01a0d567-0b77-737e-b14f-4710e8b43c5c",
"title": "Why Rust makes you import a trait to use its methods",
"url": "https://belderbos.dev/blog/rust-import-traits-to-use-methods/",
"published_at": "2026-09-17T00:00:00+00:00"
},
{
"id": "01a0d567-0b77-737e-b14f-4710e97fa1d7",
"title": "How Libraries Run Rust Inside Python (with PyO3)",
"url": "https://belderbos.dev/blog/how-libraries-run-rust-inside-python/",
"published_at": "2026-09-13T00:00:00+00:00"
},
{
"id": "01a094cb-d9dd-735f-b4b8-ac3c359f9294",
"title": "Why Learn to Code If AI Can Code? 6 Reasons",
"url": "https://belderbos.dev/blog/why-learn-to-code-if-ai-can-code/",
"published_at": "2026-09-11T00:00:00+00:00"
},
{
"id": "01a08739-462d-708c-9dd8-47c41beb6495",
"title": "Database-Driven RBAC with FastAPI and Azure Entra ID",
"url": "https://belderbos.dev/blog/database-driven-rbac-fastapi-azure-entra/",
"published_at": "2026-09-09T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafbe0e286",
"title": "5 design patterns used in my new habit tracker app",
"url": "https://belderbos.dev/blog/python-patterns-django-habit-tracker/",
"published_at": "2026-09-06T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafc6e0a09",
"title": "Why does Alembic need an import you never use?",
"url": "https://belderbos.dev/blog/what-table-true-does-sqlmodel/",
"published_at": "2026-09-04T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafc9bace3",
"title": "Unsubscribe links without a login: Django signing",
"url": "https://belderbos.dev/blog/unsubscribe-without-login-django-signing/",
"published_at": "2026-08-22T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafcbd54db",
"title": "Guardrails Protect Your Codebase. What Protects Your Judgment?",
"url": "https://belderbos.dev/blog/ai-skill-atrophy-keep-the-friction/",
"published_at": "2026-08-18T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafd77cedb",
"title": "Learning New Skills in the AI Era (vBrownBag)",
"url": "https://belderbos.dev/blog/vbrownbag-learning-skills-ai-era/",
"published_at": "2026-07-13T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101b62939d4",
"title": "Rust, AI, and the Developer Mindset (Develpreneur Podcast)",
"url": "https://belderbos.dev/blog/develpreneur-podcast-rust-ai/",
"published_at": "2026-07-10T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101b6b84f15",
"title": "Judgment: The Skill AI Can't Give You",
"url": "https://belderbos.dev/blog/thinking-matters-more-than-ever-ai-age/",
"published_at": "2026-07-08T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafe610046",
"title": "One Core, Two Interfaces, No Rewrites",
"url": "https://belderbos.dev/blog/two-interfaces-one-core/",
"published_at": "2026-07-04T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bafe77020c",
"title": "Ask the Canon: Semantic Search Without a Vector Database",
"url": "https://belderbos.dev/blog/semantic-search-without-a-vector-database/",
"published_at": "2026-06-30T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98baff0aef95",
"title": "There Is No Magic: An AI Agent in 60 Lines of Python",
"url": "https://belderbos.dev/blog/build-minimal-ai-agent-python/",
"published_at": "2026-06-26T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb000492ff",
"title": "Python Is Not Enough: Why Pythonistas Love Rust (Podcast)",
"url": "https://belderbos.dev/blog/complexity-dot-fm-podcast/",
"published_at": "2026-06-25T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101b879eb05",
"title": "AI Is an Accelerator, Not a Compass",
"url": "https://belderbos.dev/blog/ai-accelerator-needs-direction/",
"published_at": "2026-06-24T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb00949a71",
"title": "From Python to Rust: Master Iterators by Rebuilding 10 Unix Tools",
"url": "https://belderbos.dev/blog/learn-rust-building-unix-tools/",
"published_at": "2026-06-21T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb015351c2",
"title": "Profile First: A 10x Faster Django Test Suite",
"url": "https://belderbos.dev/blog/profile-django-test-suite-10x-faster/",
"published_at": "2026-06-20T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb015b628e",
"title": "End-to-End Testing Every Rust Exercise with Playwright",
"url": "https://belderbos.dev/blog/playwright-e2e-testing-71-exercises/",
"published_at": "2026-06-19T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb017fc674",
"title": "When to use classmethod, staticmethod, or instance method in Python",
"url": "https://belderbos.dev/blog/classmethod-vs-staticmethod-vs-instance-method-python/",
"published_at": "2026-06-18T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0253a159",
"title": "Building an AI Agent in 6 Weeks (and Finally Understanding How They Work)",
"url": "https://belderbos.dev/blog/jeff-haemer-agentic-ai-cohort/",
"published_at": "2026-06-17T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0337d545",
"title": "Why Rust does not need OOP",
"url": "https://belderbos.dev/blog/why-rust-does-not-need-oop/",
"published_at": "2026-06-14T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101bc14313e",
"title": "AI Doesn't Change What Software Engineering Is",
"url": "https://belderbos.dev/blog/ai-doesnt-change-what-software-engineering-is/",
"published_at": "2026-06-09T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0432aaef",
"title": "How to Update Multiple Page Elements from One htmx Request",
"url": "https://belderbos.dev/blog/htmx-hx-swap-oob-django/",
"published_at": "2026-06-05T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb048a7792",
"title": "\"Rust Is for People Who Want to Be Punished.\" Now Jochen Trusts It More Than Python.",
"url": "https://belderbos.dev/blog/jochen-rust-cohort-beat-cpython/",
"published_at": "2026-06-04T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb048d353d",
"title": "How to Tell if Your Python Mock Is Actually Working",
"url": "https://belderbos.dev/blog/python-mock-patch-verify-interception/",
"published_at": "2026-06-03T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101be851db6",
"title": "Build the Simplest Thing That Works",
"url": "https://belderbos.dev/blog/build-the-simplest-thing-that-works/",
"published_at": "2026-06-02T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb04bbff21",
"title": "AI Human-in-the-loop: News Digest Triage Telegram Bot",
"url": "https://belderbos.dev/blog/human-in-the-loop-telegram-bot-python/",
"published_at": "2026-06-01T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb04d72a3f",
"title": "The control layer is the product, not the model",
"url": "https://belderbos.dev/blog/control-layer-is-the-product/",
"published_at": "2026-05-30T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101bfa5bf0c",
"title": "Learning a New Programming Language Is More Important Now, Not Less",
"url": "https://belderbos.dev/blog/josh-rust-cohort-beat-cpython-json/",
"published_at": "2026-05-29T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb05710684",
"title": "Two Python Scoping Bugs: A Lesson in Object Lifetimes",
"url": "https://belderbos.dev/blog/two-scoping-bugs-object-lifetimes/",
"published_at": "2026-05-28T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb05d83e23",
"title": "From Python Script to Production: A Django Coaching Case Study",
"url": "https://belderbos.dev/blog/daniele-django-movie-anime-discovery/",
"published_at": "2026-05-26T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c19b370d",
"title": "Mind Map Your App Before You Write a Line of Code",
"url": "https://belderbos.dev/blog/mind-map-software-project-scope/",
"published_at": "2026-05-25T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c1a31de7",
"title": "A 500 That Survived Ten Successful Deploys",
"url": "https://belderbos.dev/blog/500-survived-ten-successful-deploys/",
"published_at": "2026-05-23T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb06cadb01",
"title": "What production AI agents actually require",
"url": "https://belderbos.dev/blog/production-ai-agents-real-workflows/",
"published_at": "2026-05-22T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c24a4ecd",
"title": "How to Keep Your Developer Instincts When AI Writes the Code",
"url": "https://belderbos.dev/blog/dont-delegate-the-friction/",
"published_at": "2026-05-20T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c30e1d16",
"title": "10 Days of Rust for Python Developers: A Recap",
"url": "https://belderbos.dev/blog/10-days-rust-python-developers-recap/",
"published_at": "2026-05-15T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb07c17a81",
"title": "Learn agentic AI in Python with 10 small exercises",
"url": "https://belderbos.dev/blog/learn-agentic-ai-python-10-step-journey/",
"published_at": "2026-05-14T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb08bf5db2",
"title": "Coding exercises that run in the browser with Pyodide",
"url": "https://belderbos.dev/blog/python-exercises-browser-pyodide/",
"published_at": "2026-05-13T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb08d14fac",
"title": "A Race Condition Rust Wouldn't Have Let Me Write",
"url": "https://belderbos.dev/blog/race-condition-rust-wouldnt-let-me-write/",
"published_at": "2026-05-12T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb09702644",
"title": "Build a daily AI digest in 200 lines of Python (no framework)",
"url": "https://belderbos.dev/blog/python-ai-trend-digest-asyncio-protocol/",
"published_at": "2026-05-08T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c62c3945",
"title": "The Rust Compiler as an AI Coding Agent Guardrail",
"url": "https://belderbos.dev/blog/rust-compiler-ai-agent-guardrail/",
"published_at": "2026-05-06T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb098c5cb5",
"title": "Event Sourcing in Python: Get More Insights Into Your Data",
"url": "https://belderbos.dev/blog/event-sourcing-python-store-events-not-state/",
"published_at": "2026-05-05T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c745c2f6",
"title": "Python to Rust: A JSON Parser in 6 Weeks",
"url": "https://belderbos.dev/blog/vikas-rust-cohort-ownership-pyo3/",
"published_at": "2026-05-01T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb098d5ee9",
"title": "Build the data layer before you touch the LLM",
"url": "https://belderbos.dev/blog/build-data-layer-before-llm/",
"published_at": "2026-04-29T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0a160c96",
"title": "Vibe Coding is Easy, Owning the Architecture Isn't",
"url": "https://belderbos.dev/blog/vibe-coding-owning-architecture/",
"published_at": "2026-04-28T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0a842fab",
"title": "From Hobby Code to SaaS to Orchestrating AI Agents",
"url": "https://belderbos.dev/blog/ai-coding-tools-fundamentals-case-study/",
"published_at": "2026-04-20T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0b1bf0b1",
"title": "How an AI expense agent is actually structured",
"url": "https://belderbos.dev/blog/ai-agent-architecture-python/",
"published_at": "2026-04-15T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0b4547ec",
"title": "Build Your First MCP Server: Code Tips in Claude and Slack",
"url": "https://belderbos.dev/blog/build-mcp-server-python-tips-slack/",
"published_at": "2026-04-13T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101c9590083",
"title": "Stop Prompting, Start Structuring Your AI Workflow",
"url": "https://belderbos.dev/blog/claude-code-skills-structured-ai-collaboration/",
"published_at": "2026-04-10T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0bc9fabb",
"title": "What Rust Structs Taught Me About State Ownership",
"url": "https://belderbos.dev/blog/what-rust-structs-taught-me-about-state-ownership/",
"published_at": "2026-04-08T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0bd1f1b3",
"title": "Build a Finite State Machine in Python",
"url": "https://belderbos.dev/blog/build-finite-state-machine-python/",
"published_at": "2026-04-07T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0ccabd85",
"title": "How to Migrate Users Seamlessly Between Django Apps on Login",
"url": "https://belderbos.dev/blog/login-triggered-user-migration-django/",
"published_at": "2026-04-06T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101caacb957",
"title": "From 1,069 to 156 LOC: Design Over Code",
"url": "https://belderbos.dev/blog/design-over-code/",
"published_at": "2026-04-01T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0d9a2bad",
"title": "How Modern Python Tooling Simplified My Setup",
"url": "https://belderbos.dev/blog/modern-python-tooling-uv-ruff-ty/",
"published_at": "2026-03-30T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0db8c27a",
"title": "The Repository Pattern: Swap Data Sources in One Line",
"url": "https://belderbos.dev/blog/repository-pattern-swappable-data-sources/",
"published_at": "2026-03-27T00:00:00+00:00"
},
{
"id": "01a08739-462e-71f6-9a39-f101cb42adac",
"title": "What Building a JSON Tokenizer Taught Me About Rust",
"url": "https://belderbos.dev/blog/what-building-a-json-tokenizer-taught-me-about-rust/",
"published_at": "2026-03-25T00:00:00+00:00"
},
{
"id": "01a08214-cdef-7048-a0eb-98bb0dfd6c11",
"title": "Learning Rust Made Me a Better Python Developer",
"url": "https://belderbos.dev/blog/rust-made-me-a-better-python-developer/",
"published_at": "2026-03-23T00:00:00+00:00"
}
] posts Claim your blog