I built an AI-powered movie curator with Python and Streamlit — here's what I learned 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. I've been a movie person my whole life. Growing 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. Today you open Netflix with 10,000 options and spend 40 minutes picking nothing. The problem isn't lack of content. It's lack of curation. So I built something about it. What I built CineAntologia 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. You describe what you want to feel while watching: "Something like Stranger Things, that 80s atmosphere and suspense" "Heavy crime drama like The Wire" "Philosophical sci-fi in the style of Blade Runner" And it gives you suggestions with actual cultural context — not just a list. Live demo: https://cineantologia-ai.streamlit.app https://cineantologia-ai.streamlit.app The stack Nothing exotic: Python 3.11 Streamlit — for the UI and deploy TMDb API — free, great data, covers posters, genres, ratings, where to watch OpenAI GPT-4o-mini or Groq for the AI chat Streamlit Community Cloud — free deploy for public repos No database in v1. No auth. No over-engineering. Three decisions worth talking about Ship on day one I pushed the repo public and deployed the moment it minimally worked. No months of polishing in private. When 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. Users bring their own API key The 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. Three wins: zero cost to scale, real privacy, and the user actually learns how an AI API works. For anyone without a key, I point them to Groq — free, no credit card, fast as hell: Dumb pages, smart services app/ ├── pages/ only renders, no logic ├── services/ all data and AI logic lives here └── utils/ config, CSS, shared sidebar Each 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. What was actually hard The 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: SYSTEM PROMPT = """You are CineAntologia AI, a film curator specialized in movies and TV shows from every decade. Always end your response with suggestions in this exact format: Title Year — reason in one line Minimum 4, maximum 6 suggestions.""" That fixed format made a huge difference in consistency. Normalizing 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: php def normalize items: list - list dict : out = for item in items: mt = item.get "media type", "movie" if mt == "person": continue title = item.get "title" or item.get "name" or "—" date = item.get "release date" or item.get "first air date" or "" year = int date :4 if date and len date = 4 else None out.append { "id": item.get "id" , "title": title, "year": year, "type": "Movie" if mt == "movie" else "Series", "genres": ... , "synopsis": item.get "overview", "" , "poster": poster url item.get "poster path" , "rating": round item.get "vote average", 0 , 1 , } return out CSS 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. What's next Anime and K-drama — huge audience, badly served by recommendation tools Oscar Hall of Fame since 1929 — every category, with poster and where to watch today Semantic search — embeddings to search by vibe, not just title Specialized agents — horror agent, sci-fi agent, drama agent Try it 🎬 https://cineantologia-ai.streamlit.app https://cineantologia-ai.streamlit.app For the AI Chat, grab a free Groq key at https://console.groq.com https://console.groq.com — no credit card, takes 2 minutes. Feedback, suggestions, and PRs are very welcome. Still early, lots of room to grow. Built with Python, Streamlit, TMDb API, and coffee.