<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Abdellah Shafi — Blog</title><description>Deep dives on projects I have built: architecture decisions, what I learned, and what I would do differently.</description><link>https://abdellah-shafi.dev/</link><language>en-us</language><item><title>Building Birr AI: a Django + React navigator for NBE directives</title><link>https://abdellah-shafi.dev/blog/building-birr-ai-nbe-navigator/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/building-birr-ai-nbe-navigator/</guid><description>How I shaped Birr AI around source-grounded regulatory answers, a real document index, and a constrained RAG orchestrator instead of a loose chatbot.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>React</category><category>AI/RAG</category><category>pgvector</category></item><item><title>Streaming grounded answers: the SSE architecture behind Birr AI</title><link>https://abdellah-shafi.dev/blog/birr-ai-streaming-sse-architecture/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/birr-ai-streaming-sse-architecture/</guid><description>How Birr AI streams RAG answers with async Django, Server-Sent Events, persisted messages, and source payloads without adding WebSockets or a separate realtime service.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>SSE</category><category>AI/RAG</category><category>async</category></item><item><title>Keeping Birr AI current: the nightly document ingestion pipeline</title><link>https://abdellah-shafi.dev/blog/birr-ai-nightly-ingestion-pipeline/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/birr-ai-nightly-ingestion-pipeline/</guid><description>How the Birr AI ingestion job discovers NBE files, extracts Markdown, embeds chunks into pgvector, handles quotas, and stays resumable with ordinary Django models.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><category>Python</category><category>Django</category><category>pgvector</category><category>ETL</category></item><item><title>EvalBoard: treating prompts like tests</title><link>https://abdellah-shafi.dev/blog/evalboard-byok-llm-evaluation-dashboard/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/evalboard-byok-llm-evaluation-dashboard/</guid><description>How EvalBoard models datasets, prompt templates, runs, and per-row results so LLM behavior can be measured instead of judged from one good demo.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>React</category><category>LLM</category><category>DRF</category></item><item><title>BYOK in EvalBoard: provider access without storing secrets</title><link>https://abdellah-shafi.dev/blog/evalboard-byok-provider-architecture/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/evalboard-byok-provider-architecture/</guid><description>How EvalBoard supports OpenAI-compatible LLM providers, sends user API keys per request, and keeps provider integration small while accepting the tradeoffs of browser-held keys.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>BYOK</category><category>LLM</category><category>API Design</category></item><item><title>EvalBoard analytics: turning run history into a dashboard with the Django ORM</title><link>https://abdellah-shafi.dev/blog/evalboard-django-orm-analytics-dashboard/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/evalboard-django-orm-analytics-dashboard/</guid><description>How EvalBoard uses aggregate queries, conditional counts, cached stats, and Recharts to summarize LLM evaluation history from one DRF endpoint.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>ORM</category><category>Recharts</category><category>Analytics</category></item><item><title>From cart to order: safe checkout in a Django e-commerce API</title><link>https://abdellah-shafi.dev/blog/ecommerce-api-payments-stock-ci/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/ecommerce-api-payments-stock-ci/</guid><description>How the e-commerce API turns carts into orders with price snapshots, row locks, atomic transactions, F expressions, and stock validation that prevents overselling.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>PostgreSQL</category><category>DRF</category><category>Transactions</category></item><item><title>Chapa payments: treating the provider as the source of truth</title><link>https://abdellah-shafi.dev/blog/ecommerce-api-chapa-webhooks/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/ecommerce-api-chapa-webhooks/</guid><description>How the e-commerce API initializes Chapa payments, stores pending transactions, verifies webhooks, and atomically updates payment and order state.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>Payments</category><category>Chapa</category><category>Webhooks</category></item><item><title>Testing an e-commerce API as a complete workflow</title><link>https://abdellah-shafi.dev/blog/ecommerce-api-tests-docs-ci/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/ecommerce-api-tests-docs-ci/</guid><description>How the e-commerce API uses pytest-django, DRF test clients, OpenAPI docs, Docker, and CI to protect the registration, checkout, and payment paths.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>pytest</category><category>OpenAPI</category><category>CI/CD</category></item><item><title>Virtual Blood Bank: modeling healthcare workflows beyond CRUD</title><link>https://abdellah-shafi.dev/blog/virtual-blood-bank-django-api/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/virtual-blood-bank-django-api/</guid><description>How the Virtual Blood Bank API models facilities, blood units, inter-facility requests, and request history for a healthcare workflow where state changes matter.</description><pubDate>Tue, 23 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>REST API</category><category>PostgreSQL</category><category>Healthcare</category></item><item><title>Least-privilege roles and request transitions in Virtual Blood Bank</title><link>https://abdellah-shafi.dev/blog/virtual-blood-bank-rbac-lifecycle/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/virtual-blood-bank-rbac-lifecycle/</guid><description>How VBB separates clinicians, supply staff, and admins, then routes every blood request action through an authorizer and lifecycle service.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>RBAC</category><category>State Machines</category><category>DRF</category></item><item><title>Inventory summaries, expiry alerts, and notifications in Virtual Blood Bank</title><link>https://abdellah-shafi.dev/blog/virtual-blood-bank-inventory-dashboard-notifications/</link><guid isPermaLink="true">https://abdellah-shafi.dev/blog/virtual-blood-bank-inventory-dashboard-notifications/</guid><description>How VBB turns facility inventory into dashboard summaries, low-stock alerts, expiring-soon flags, notification events, and audit records without overbuilding infrastructure.</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><category>Django</category><category>ORM</category><category>Notifications</category><category>Healthcare</category></item></channel></rss>