Bhavana AI

AI/ML insights

Dev Log: December 26, 2025

podcast-summarizer-v2

Continued hardening the podcast summarizer with SQL Server compatibility fixes and building out the admin authentication layer. Fixed a query compatibility issue where SQL Server rejected IN (subquery) in SELECT clauses, replacing it with a database-agnostic LEFT OUTER JOIN pattern. Then shifted to adding admin authorization, extending the auth response with is_admin so the frontend gets admin status at login time, and wiring up protected admin routes with a layered React Router approach.

SQL Server Compatibility Fix

The episodes query initially failed because SQL Server doesn’t support column IN (subquery) directly in SELECT clauses. The fix was to use LEFT OUTER JOINs with CASE expressions:

-- Before (fails on SQL Server):
SELECT episodes.youtube_video_id IN (SELECT ...) AS has_transcript

-- After (works on all databases):
SELECT CASE WHEN subq.video_id IS NOT NULL THEN 1 ELSE 0 END AS has_transcript
FROM episodes LEFT OUTER JOIN transcript_subq ON ...

This pattern is database-agnostic and performs better since it computes the flags during the join rather than per-row.

The integration approach here leverages several key patterns:

  1. Backend-first auth extension - Adding is_admin to VerifyResponse means the frontend gets admin status immediately at login, not via a separate API call
  2. Route-based admin isolation - Using /admin/* routes keeps admin UI cleanly separated while sharing the same React app shell
  3. Protected route composition - AdminProtectedRoute will wrap ProtectedRoute to add the admin check layer

The integration approach uses several key React patterns:

  1. Nested routes with outlet - The admin routes use <Route element={<AdminLayout />}> with nested child routes, and AdminLayout uses <Outlet /> to render child content
  2. Layered route protection - AdminProtectedRoute wraps AdminLayout, checking both authentication AND admin status before rendering
  3. Conditional navigation hiding - Both Navbar and BottomNav check the path and return null on admin routes to avoid double navigation