{"slug": "i-built-an-ai-powered-movie-curator-with-python-and-streamlit-here-s-what-i", "title": "I built an AI-powered movie curator with Python and Streamlit — here's what I learned", "summary": "A developer built CineAntologia AI, a movie and TV show curator using Python, Streamlit, TMDb API, and OpenAI's GPT-4o-mini. The app allows users to describe desired viewing experiences and receive AI-curated suggestions with cultural context. Key design decisions included shipping early, requiring users to bring their own API key, and separating UI from business logic.", "body_md": "I've been a movie person my whole life.\n\nGrowing up in the 80s and 90s, I'd go to the video store without knowing what I wanted and walk out with five tapes. Browsing shelves, reading back covers, picking something just because the title was weird. It was slow and it worked.\n\nToday you open Netflix with 10,000 options and spend 40 minutes picking nothing.\n\nThe problem isn't lack of content. It's lack of curation. So I built something about it.\n\n**What I built**\n\nCineAntologia AI — a public catalog of movies and TV shows from the 80s to today, with an AI chat that works like a film curator instead of a search engine.\n\nYou describe what you want to feel while watching:\n\n\"Something like Stranger Things, that 80s atmosphere and suspense\"\n\n\"Heavy crime drama like The Wire\"\n\n\"Philosophical sci-fi in the style of Blade Runner\"\n\nAnd it gives you suggestions with actual cultural context — not just a list.\n\nLive demo: ([https://cineantologia-ai.streamlit.app](https://cineantologia-ai.streamlit.app))\n\n**The stack**\n\nNothing exotic:\n\nPython 3.11\n\nStreamlit — for the UI and deploy\n\nTMDb API — free, great data, covers posters, genres, ratings, where to watch\n\nOpenAI GPT-4o-mini or Groq for the AI chat\n\nStreamlit Community Cloud — free deploy for public repos\n\nNo database in v1. No auth. No over-engineering.\n\n**Three decisions worth talking about**\n\nShip on day one\n\nI pushed the repo public and deployed the moment it minimally worked. No months of polishing in private.\n\nWhen it's a drawer project you optimize for the code. When it's public you optimize for the person using it. That shift in perspective is worth the discomfort of shipping something imperfect.\n\nUsers bring their own API key\n\nThe AI Chat uses GPT-4o-mini or Groq. Instead of covering API costs for everyone — unpredictable at scale — users paste their own key in the sidebar. It lives only in their browser session, never hits my server.\n\nThree wins: zero cost to scale, real privacy, and the user actually learns how an AI API works.\n\nFor anyone without a key, I point them to Groq — free, no credit card, fast as hell:\n\nDumb pages, smart services\n\napp/\n\n├── pages/ # only renders, no logic\n\n├── services/ # all data and AI logic lives here\n\n└── utils/ # config, CSS, shared sidebar\n\nEach page is as dumb as possible — it just calls a service and renders the result. All TMDb calls, normalization, and AI prompting stay in services/. Made the whole thing much easier to iterate on.\n\n**What was actually hard**\n\nThe system prompt. Getting the AI to respond like a real curator took more iteration than I expected. The fix that worked was enforcing a strict output format:\n\n```\nSYSTEM_PROMPT = \"\"\"You are CineAntologia AI, a film curator specialized \nin movies and TV shows from every decade.\n\nAlways end your response with suggestions in this exact format:\nTitle (Year) — reason in one line\n\nMinimum 4, maximum 6 suggestions.\"\"\"\n```\n\nThat fixed format made a huge difference in consistency.\n\nNormalizing TMDb data. Movies have title and release_date. Shows have name and first_air_date. I wrote a _normalize() function that flattens everything into the same schema before any page touches the data:\n\n``` php\ndef _normalize(items: list) -> list[dict]:\n    out = []\n    for item in items:\n        mt = item.get(\"media_type\", \"movie\")\n        if mt == \"person\":\n            continue\n        title = item.get(\"title\") or item.get(\"name\") or \"—\"\n        date = item.get(\"release_date\") or item.get(\"first_air_date\") or \"\"\n        year = int(date[:4]) if date and len(date) >= 4 else None\n        out.append({\n            \"id\": item.get(\"id\"),\n            \"title\": title,\n            \"year\": year,\n            \"type\": \"Movie\" if mt == \"movie\" else \"Series\",\n            \"genres\": [...],\n            \"synopsis\": item.get(\"overview\", \"\"),\n            \"poster\": poster_url(item.get(\"poster_path\")),\n            \"rating\": round(item.get(\"vote_average\", 0), 1),\n        })\n    return out\n```\n\nCSS in Streamlit. Streamlit has strong opinions about styling. Custom dark theme with Bebas Neue + Inter required injecting CSS via st.markdown() with unsafe_allow_html=True. Not pretty, but it works.\n\n**What's next**\n\nAnime and K-drama — huge audience, badly served by recommendation tools\n\nOscar Hall of Fame since 1929 — every category, with poster and where to watch today\n\nSemantic search — embeddings to search by vibe, not just title\n\nSpecialized agents — horror agent, sci-fi agent, drama agent\n\n**Try it**\n\n🎬 ([https://cineantologia-ai.streamlit.app](https://cineantologia-ai.streamlit.app))\n\nFor the AI Chat, grab a free Groq key at [https://console.groq.com](https://console.groq.com) — no credit card, takes 2 minutes.\n\nFeedback, suggestions, and PRs are very welcome. Still early, lots of room to grow.\n\nBuilt with Python, Streamlit, TMDb API, and coffee.", "url": "https://wpnews.pro/news/i-built-an-ai-powered-movie-curator-with-python-and-streamlit-here-s-what-i", "canonical_source": "https://dev.to/claudiomjedi1979/i-built-an-ai-powered-movie-curator-with-python-and-streamlit-heres-what-i-learned-48j1", "published_at": "2026-06-26 15:07:24+00:00", "updated_at": "2026-06-26 15:34:32.945481+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "ai-products", "developer-tools", "generative-ai"], "entities": ["CineAntologia AI", "Streamlit", "TMDb", "OpenAI", "GPT-4o-mini", "Groq", "Streamlit Community Cloud"], "alternates": {"html": "https://wpnews.pro/news/i-built-an-ai-powered-movie-curator-with-python-and-streamlit-here-s-what-i", "markdown": "https://wpnews.pro/news/i-built-an-ai-powered-movie-curator-with-python-and-streamlit-here-s-what-i.md", "text": "https://wpnews.pro/news/i-built-an-ai-powered-movie-curator-with-python-and-streamlit-here-s-what-i.txt", "jsonld": "https://wpnews.pro/news/i-built-an-ai-powered-movie-curator-with-python-and-streamlit-here-s-what-i.jsonld"}}