From f977925880809d1e77fbe4f325fe330b25d48b75 Mon Sep 17 00:00:00 2001 From: Juan Marquez Date: Thu, 18 Jun 2026 17:13:24 +0200 Subject: [PATCH] simplificando app --- README.md | 10 +- app/layout.tsx | 2 +- app/movie/[id]/page.tsx | 41 -------- app/page.tsx | 41 +------- components/MovieInsightPanel.tsx | 30 ++---- components/cards/CardContent.tsx | 14 +-- components/cards/HistoricalAccuracy.tsx | 76 --------------- components/cards/ProductionFacts.tsx | 70 ------------- components/cards/SensitivityGuide.tsx | 56 ----------- components/cards/SkipGuide.tsx | 124 ------------------------ karpathy.md | 59 +++++++++++ lib/card-generator.ts | 58 +---------- lib/cards.ts | 34 +------ lib/schemas/index.ts | 59 ----------- lib/tmdb.ts | 18 +--- package-lock.json | 4 +- 16 files changed, 82 insertions(+), 614 deletions(-) delete mode 100644 app/movie/[id]/page.tsx delete mode 100644 components/cards/HistoricalAccuracy.tsx delete mode 100644 components/cards/ProductionFacts.tsx delete mode 100644 components/cards/SensitivityGuide.tsx delete mode 100644 components/cards/SkipGuide.tsx create mode 100644 karpathy.md diff --git a/README.md b/README.md index 2fd7e85..3f79319 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # Film Intel -Advanced movie insight you won't find in one click. Search any film and generate -ratings explained, skip guides, sensitivity warnings, international ratings, -production facts, and historical-accuracy breakdowns. +Reliable film age ratings, explained. Search any film and get a clear breakdown +of why it received its age rating, plus how that rating differs across +countries. ## Requirements - Node.js 22 - A TMDB API key (https://www.themoviedb.org/settings/api) - An LLM API key (OpenRouter or any OpenAI-compatible endpoint) -- PostgreSQL for caching generated insight cards (optional but recommended) +- PostgreSQL for caching generated rating cards (optional but recommended) Copy `.env.example` to `.env` and fill in the keys. @@ -33,7 +33,7 @@ npm install npm run dev ``` -> Without a database the insight cards will still generate (they just won't be +> Without a database the rating cards will still generate (they just won't be > cached), thanks to graceful cache handling. Run `npm run db:migrate` against a > reachable Postgres to enable caching. diff --git a/app/layout.tsx b/app/layout.tsx index 0b4621a..3898de1 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -14,7 +14,7 @@ const geistMono = Geist_Mono({ export const metadata: Metadata = { title: "Film Intel", - description: "Advanced movie insight you won't find in one click", + description: "Reliable film age ratings, explained", }; export default function RootLayout({ diff --git a/app/movie/[id]/page.tsx b/app/movie/[id]/page.tsx deleted file mode 100644 index 63066c7..0000000 --- a/app/movie/[id]/page.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { notFound } from "next/navigation"; -import { MovieHeader } from "@/components/MovieHeader"; -import { MovieInsightPanel } from "@/components/MovieInsightPanel"; -import { getMovieDetails } from "@/lib/tmdb"; - -export default async function MoviePage({ - params, -}: { - params: Promise<{ id: string }>; -}) { - const { id } = await params; - const movieId = Number(id); - - if (!Number.isFinite(movieId) || movieId <= 0) { - notFound(); - } - - let movie; - try { - movie = await getMovieDetails(movieId); - } catch { - notFound(); - } - - return ( -
-
- - genre.name)} - /> -
- -
- AI-generated content for informational purposes. Verify timestamps on - your copy. -
-
- ); -} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index 4e2254b..53e8c62 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { SearchBar } from "@/components/SearchBar"; import { MovieHeader } from "@/components/MovieHeader"; import { MovieInsightPanel } from "@/components/MovieInsightPanel"; @@ -16,33 +16,6 @@ export default function HomePage() { const [isLoadingMovie, setIsLoadingMovie] = useState(false); const [movieError, setMovieError] = useState(null); - // Preload a random interesting movie on initial page load to demonstrate the app - useEffect(() => { - const DEMO_IDS = [27205, 157336, 155, 550, 496243, 424]; // Inception, Interstellar, Dark Knight, Fight Club, Parasite, Schindler's List - const loadDemo = async () => { - const id = DEMO_IDS[Math.floor(Math.random() * DEMO_IDS.length)]; - try { - const res = await fetch(`/api/movie/${id}`); - if (!res.ok) return; - const details: TmdbMovieDetails = await res.json(); - const minimalSearch: TmdbSearchResult = { - id: details.id, - title: details.title, - release_date: details.release_date || "", - poster_path: details.poster_path, - overview: details.overview || "", - }; - setSelectedMovie(minimalSearch); - setMovieDetails(details); - } catch { - // silently fall back to empty state if demo preload fails - } - }; - if (!selectedMovie) { - void loadDemo(); - } - }, []); - const handleSelect = async (movie: TmdbSearchResult) => { setSelectedMovie(movie); setMovieDetails(null); @@ -77,7 +50,7 @@ export default function HomePage() { Film Intel - Movie insight you won't find in one click + Reliable film ratings, explained @@ -95,9 +68,8 @@ export default function HomePage() { {!selectedMovie && (

- Search for any film using the bar above. We'll generate - ratings explained, skip guides, sensitivity warnings, production - facts, and more. + Search for any film using the bar above. We'll explain its + age rating and how it differs across countries.

)} @@ -136,10 +108,7 @@ export default function HomePage() { )} - g.name) ?? []} - /> + )} diff --git a/components/MovieInsightPanel.tsx b/components/MovieInsightPanel.tsx index f41fdc5..c826a72 100644 --- a/components/MovieInsightPanel.tsx +++ b/components/MovieInsightPanel.tsx @@ -1,35 +1,17 @@ "use client"; import { useState } from "react"; -import { - CARD_META, - CARD_TYPES, - shouldShowHistoricalAccuracy, - type CardType, -} from "@/lib/cards"; +import { CARD_META, CARD_TYPES, type CardType } from "@/lib/cards"; import { CardContent } from "./cards/CardContent"; import { InfoCard } from "./InfoCard"; -export function MovieInsightPanel({ - movieId, - genres, -}: { - movieId: number; - genres: string[]; -}) { - const visibleCards = CARD_TYPES.filter((type) => { - if (type === "historical_accuracy") { - return shouldShowHistoricalAccuracy(genres); - } - return true; - }); - - const [selected, setSelected] = useState(visibleCards[0]); +export function MovieInsightPanel({ movieId }: { movieId: number }) { + const [selected, setSelected] = useState(CARD_TYPES[0]); return (
-
- {visibleCards.map((type) => ( +
+ {CARD_TYPES.map((type) => (
); -} \ No newline at end of file +} diff --git a/components/cards/CardContent.tsx b/components/cards/CardContent.tsx index d9246ec..54ce8e9 100644 --- a/components/cards/CardContent.tsx +++ b/components/cards/CardContent.tsx @@ -2,12 +2,8 @@ import { useEffect, useState } from "react"; import type { CardType } from "@/lib/cards"; -import { HistoricalAccuracyView } from "./HistoricalAccuracy"; import { InternationalRatingsView } from "./InternationalRatings"; -import { ProductionFactsView } from "./ProductionFacts"; import { RatingExplainedView } from "./RatingExplained"; -import { SensitivityGuideView } from "./SensitivityGuide"; -import { SkipGuideView } from "./SkipGuide"; interface CardContentProps { movieId: number; @@ -99,17 +95,9 @@ export function CardContent({ movieId, cardType }: CardContentProps) { switch (cardType) { case "rating_explained": return ; - case "skip_guide": - return ; - case "sensitivity_guide": - return ; case "international_ratings": return ; - case "production_facts": - return ; - case "historical_accuracy": - return ; default: return null; } -} \ No newline at end of file +} diff --git a/components/cards/HistoricalAccuracy.tsx b/components/cards/HistoricalAccuracy.tsx deleted file mode 100644 index 45d3283..0000000 --- a/components/cards/HistoricalAccuracy.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { - historicalAccuracySchema, - type HistoricalAccuracy, -} from "@/lib/schemas"; - -export function HistoricalAccuracyView({ data }: { data: unknown }) { - const result = historicalAccuracySchema.safeParse(data); - if (!result.success) { - return ( -
- Could not display this insight (data format issue). Try another card or refresh later. -
- ); - } - const parsed = result.data as HistoricalAccuracy; - - return ( -
-
-
-

- Accuracy score -

-

- {parsed.accuracyScore} - /100 -

-
-

- Confidence: {parsed.confidence} -

-
- -

{parsed.summary}

- - {parsed.accurateElements.length > 0 && ( -
-

What holds up

-
    - {parsed.accurateElements.map((item) => ( -
  • - {item} -
  • - ))} -
-
- )} - - {parsed.inventions.length > 0 && ( -
-

- Dramatizations & inventions -

-
- {parsed.inventions.map((item, index) => ( -
-

- Film claim: {item.claim} -

-

- Reality: {item.reality} -

-
- ))} -
-
- )} -
- ); -} \ No newline at end of file diff --git a/components/cards/ProductionFacts.tsx b/components/cards/ProductionFacts.tsx deleted file mode 100644 index 259fbe4..0000000 --- a/components/cards/ProductionFacts.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { - productionFactsSchema, - type ProductionFacts, -} from "@/lib/schemas"; - -export function ProductionFactsView({ data }: { data: unknown }) { - const result = productionFactsSchema.safeParse(data); - if (!result.success) { - return ( -
- Could not display this insight (data format issue). Try another card or refresh later. -
- ); - } - const parsed = result.data as ProductionFacts; - - return ( -
- {(parsed.budget || parsed.boxOffice) && ( -
- {parsed.budget ? : null} - {parsed.boxOffice ? ( - - ) : null} -
- )} - - {parsed.filmingLocations?.length ? ( -
-

Filming locations

-
- {parsed.filmingLocations.map((location) => ( - - {location} - - ))} -
-
- ) : null} - -
- {parsed.facts.map((item, index) => ( -
-

- {item.category} -

-

- {item.fact} -

-
- ))} -
-
- ); -} - -function Stat({ label, value }: { label: string; value: string }) { - return ( -
-

{label}

-

{value}

-
- ); -} \ No newline at end of file diff --git a/components/cards/SensitivityGuide.tsx b/components/cards/SensitivityGuide.tsx deleted file mode 100644 index 444875f..0000000 --- a/components/cards/SensitivityGuide.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { - sensitivityGuideSchema, - type SensitivityGuide, -} from "@/lib/schemas"; -import { cn } from "@/lib/utils"; - -const severityColors = { - mild: "border-emerald-400/20 bg-emerald-400/5", - moderate: "border-amber-400/20 bg-amber-400/5", - strong: "border-red-400/20 bg-red-400/5", -}; - -export function SensitivityGuideView({ data }: { data: unknown }) { - const result = sensitivityGuideSchema.safeParse(data); - if (!result.success) { - return ( -
- Could not display this insight (data format issue). Try another card or refresh later. -
- ); - } - const parsed = result.data as SensitivityGuide; - - return ( -
-

{parsed.summary}

- -
- {parsed.themes.map((theme, index) => ( -
-
-

{theme.theme}

- - {theme.severity} - - {theme.approximateTiming ? ( - - ~{theme.approximateTiming} - - ) : null} -
-

- {theme.description} -

-
- ))} -
-
- ); -} \ No newline at end of file diff --git a/components/cards/SkipGuide.tsx b/components/cards/SkipGuide.tsx deleted file mode 100644 index 9422734..0000000 --- a/components/cards/SkipGuide.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { skipGuideSchema, type SkipGuide } from "@/lib/schemas"; -import { cn } from "@/lib/utils"; - -const recommendationStyles = { - recommended: "bg-red-100 text-red-700 border-red-200", - optional: "bg-amber-100 text-amber-700 border-amber-200", - do_not_skip: "bg-stone-200 text-stone-700 border-stone-300", -}; - -const recommendationLabels = { - recommended: "Recommended skip", - optional: "Optional skip", - do_not_skip: "Do not skip", -}; - -function parseTimestamp(value: string): number { - const hours = value.match(/(\d+)\s*h/i); - const minutes = value.match(/(\d+)\s*m/i); - return (hours ? Number(hours[1]) * 60 : 0) + (minutes ? Number(minutes[1]) : 0); -} - -export function SkipGuideView({ data }: { data: unknown }) { - const result = skipGuideSchema.safeParse(data); - if (!result.success) { - return ( -
- Could not display this insight (data format issue). Try another card or refresh later. -
- ); - } - const parsed = result.data as SkipGuide; - const maxMinutes = Math.max( - ...parsed.segments.map((segment) => parseTimestamp(segment.end)), - 120, - ); - - return ( -
-
- - - -
- -
-

Content timeline

-
- {parsed.segments.map((segment, index) => { - const start = parseTimestamp(segment.start); - const end = parseTimestamp(segment.end); - const left = (start / maxMinutes) * 100; - const width = Math.max(((end - start) / maxMinutes) * 100, 1.5); - - return ( -
- ); - })} -
-
- 0:00 - {Math.floor(maxMinutes / 60)}h {maxMinutes % 60}m -
-
- -
- {parsed.segments.map((segment, index) => ( -
-
- - {segment.start} – {segment.end} - - - {recommendationLabels[segment.skipRecommendation]} - - - Plot impact: {segment.plotImpact.replace("_", " ")} - -
-

{segment.reason}

-

- Resume hint:{" "} - {segment.resumeHint} -

-
- ))} -
- -

{parsed.disclaimer}

-
- ); -} - -function Stat({ label, value }: { label: string; value: string }) { - return ( -
-

{label}

-

{value}

-
- ); -} \ No newline at end of file diff --git a/karpathy.md b/karpathy.md new file mode 100644 index 0000000..05ddc06 --- /dev/null +++ b/karpathy.md @@ -0,0 +1,59 @@ +Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed. + +**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment. + +## 1. Think Before Coding + +**Don't assume. Don't hide confusion. Surface tradeoffs.** + +Before implementing: +- State your assumptions explicitly. If uncertain, ask. +- If multiple interpretations exist, present them - don't pick silently. +- If a simpler approach exists, say so. Push back when warranted. +- If something is unclear, stop. Name what's confusing. Ask. + +## 2. Simplicity First + +**Minimum code that solves the problem. Nothing speculative.** + +- No features beyond what was asked. +- No abstractions for single-use code. +- No "flexibility" or "configurability" that wasn't requested. +- No error handling for impossible scenarios. +- If you write 200 lines and it could be 50, rewrite it. + +Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. + +## 3. Surgical Changes + +**Touch only what you must. Clean up only your own mess.** + +When editing existing code: +- Don't "improve" adjacent code, comments, or formatting. +- Don't refactor things that aren't broken. +- Match existing style, even if you'd do it differently. +- If you notice unrelated dead code, mention it - don't delete it. + +When your changes create orphans: +- Remove imports/variables/functions that YOUR changes made unused. +- Don't remove pre-existing dead code unless asked. + +The test: Every changed line should trace directly to the user's request. + +## 4. Goal-Driven Execution + +**Define success criteria. Loop until verified.** + +Transform tasks into verifiable goals: +- "Add validation" → "Write tests for invalid inputs, then make them pass" +- "Fix the bug" → "Write a test that reproduces it, then make it pass" +- "Refactor X" → "Ensure tests pass before and after" + +For multi-step tasks, state a brief plan: +``` +1. [Step] → verify: [check] +2. [Step] → verify: [check] +3. [Step] → verify: [check] +``` + +Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. diff --git a/lib/card-generator.ts b/lib/card-generator.ts index 8356edb..9e34382 100644 --- a/lib/card-generator.ts +++ b/lib/card-generator.ts @@ -2,12 +2,8 @@ import type { CardType } from "./cards"; import { getCachedCard, setCachedCard } from "./cache"; import { generateStructuredResponse } from "./llm"; import { - historicalAccuracySchema, internationalRatingsSchema, - productionFactsSchema, ratingExplainedSchema, - sensitivityGuideSchema, - skipGuideSchema, } from "./schemas"; import { formatMovieContext, getMovieDetails } from "./tmdb"; @@ -29,66 +25,14 @@ You MUST return ONLY valid JSON matching this exact structure (no extra keys, no } Focus on specific scenes or content patterns that drove the rating. Be precise with the allowed category and intensity values.`, - skip_guide: `Create a skip guide for families who want to watch this film with a younger audience. -You MUST return ONLY valid JSON matching this exact structure: -{ - "originalRating": string, - "suggestedAudienceAge": number (integer 0-21), - "totalSkippedMinutes": number (integer), - "segments": array of { - "start": string (e.g. "0:05" or "12m"), - "end": string, - "reason": string, - "intensity": one of exactly ["mild", "moderate", "strong"], - "plotImpact": one of exactly ["none", "minor", "significant"], - "skipRecommendation": one of exactly ["recommended", "optional", "do_not_skip"], - "resumeHint": string - }, - "disclaimer": string -} -Only include genuinely skippable segments. Mark plot-critical scenes as skipRecommendation "do_not_skip". -Timestamps should be approximate for the standard theatrical cut. Use only the exact enum strings listed.`, - - sensitivity_guide: `Create a sensitivity guide grouping potentially upsetting content by theme. -You MUST return ONLY valid JSON: -{ - "summary": string, - "themes": array of { - "theme": string, - "severity": one of exactly ["mild", "moderate", "strong"], - "description": string, - "approximateTiming": string (optional) - } -} -Cover violence, sexuality, substances, self-harm, abuse, animal harm, discrimination, and other difficult themes where relevant. Use only the exact "severity" values.`, - international_ratings: `Summarize how this film is rated across countries using the certification data provided. Return JSON with: ratings (array of {country, countryCode, rating, descriptors?}), discrepancyNote, strictestCountry (optional), mostLenientCountry (optional). Include at least US, GB, ES, DE, FR when data exists. Explain notable differences.`, - - production_facts: `Curate interesting behind-the-scenes production facts for cinephiles. -Return JSON with: facts (array of at least 5 {category, fact}), budget (optional string), boxOffice (optional string), filmingLocations (optional array of strings). -Prefer specific, verifiable-sounding details; note uncertainty in the fact text when needed.`, - - historical_accuracy: `Evaluate historical accuracy for this biographical or historical film. -You MUST return ONLY valid JSON: -{ - "accuracyScore": number (0-100), - "summary": string, - "accurateElements": string[], - "inventions": array of { "claim": string, "reality": string }, - "confidence": one of exactly ["high", "medium", "low"] -} -If the film is not historical/biographical, still assess any real-world basis it claims. Use only the exact confidence value.`, }; const SCHEMAS = { rating_explained: ratingExplainedSchema, - skip_guide: skipGuideSchema, - sensitivity_guide: sensitivityGuideSchema, international_ratings: internationalRatingsSchema, - production_facts: productionFactsSchema, - historical_accuracy: historicalAccuracySchema, } as const; export async function generateCard(movieId: number, cardType: CardType) { @@ -113,4 +57,4 @@ ${context}`; await setCachedCard(movieId, cardType, data); return { data, cached: false }; -} \ No newline at end of file +} diff --git a/lib/cards.ts b/lib/cards.ts index e165a10..4cbdaf1 100644 --- a/lib/cards.ts +++ b/lib/cards.ts @@ -1,10 +1,6 @@ export const CARD_TYPES = [ "rating_explained", - "skip_guide", - "sensitivity_guide", "international_ratings", - "production_facts", - "historical_accuracy", ] as const; export type CardType = (typeof CARD_TYPES)[number]; @@ -20,40 +16,12 @@ export const CARD_META: Record = { title: "Rating Explained", subtitle: "Why this film has its age rating", }, - skip_guide: { - title: "Skip Guide", - subtitle: "Scenes you can skip for a younger audience", - badge: "Families", - }, - sensitivity_guide: { - title: "Sensitivity Guide", - subtitle: "Content warnings by theme", - }, international_ratings: { title: "International Ratings", subtitle: "How ratings differ by country", }, - production_facts: { - title: "Production Facts", - subtitle: "Behind-the-scenes facts", - }, - historical_accuracy: { - title: "Historical Accuracy", - subtitle: "Fact vs fiction breakdown", - }, }; -const HISTORICAL_GENRES = new Set([ - "history", - "war", - "biography", - "documentary", -]); - -export function shouldShowHistoricalAccuracy(genres: string[]): boolean { - return genres.some((genre) => HISTORICAL_GENRES.has(genre.toLowerCase())); -} - export function isCardType(value: string): value is CardType { return CARD_TYPES.includes(value as CardType); -} \ No newline at end of file +} diff --git a/lib/schemas/index.ts b/lib/schemas/index.ts index fa69587..fe13b03 100644 --- a/lib/schemas/index.ts +++ b/lib/schemas/index.ts @@ -26,36 +26,6 @@ export const ratingExplainedSchema = z.object({ borderlineNote: z.string().optional(), }); -export const skipGuideSchema = z.object({ - originalRating: z.string(), - suggestedAudienceAge: z.number().int().min(0).max(21), - totalSkippedMinutes: z.number().int().min(0), - segments: z.array( - z.object({ - start: z.string(), - end: z.string(), - reason: z.string(), - intensity, - plotImpact: z.enum(["none", "minor", "significant"]), - skipRecommendation: z.enum(["recommended", "optional", "do_not_skip"]), - resumeHint: z.string(), - }), - ), - disclaimer: z.string(), -}); - -export const sensitivityGuideSchema = z.object({ - summary: z.string(), - themes: z.array( - z.object({ - theme: z.string(), - severity: intensity, - description: z.string(), - approximateTiming: z.string().optional(), - }), - ), -}); - export const internationalRatingsSchema = z.object({ ratings: z.array( z.object({ @@ -70,34 +40,5 @@ export const internationalRatingsSchema = z.object({ mostLenientCountry: z.string().optional(), }); -export const productionFactsSchema = z.object({ - facts: z.array( - z.object({ - category: z.string(), - fact: z.string(), - }), - ), - budget: z.string().optional(), - boxOffice: z.string().optional(), - filmingLocations: z.array(z.string()).optional(), -}); - -export const historicalAccuracySchema = z.object({ - accuracyScore: z.number().min(0).max(100), - summary: z.string(), - accurateElements: z.array(z.string()), - inventions: z.array( - z.object({ - claim: z.string(), - reality: z.string(), - }), - ), - confidence, -}); - export type RatingExplained = z.infer; -export type SkipGuide = z.infer; -export type SensitivityGuide = z.infer; export type InternationalRatings = z.infer; -export type ProductionFacts = z.infer; -export type HistoricalAccuracy = z.infer; \ No newline at end of file diff --git a/lib/tmdb.ts b/lib/tmdb.ts index 0f18f3b..89dacd2 100644 --- a/lib/tmdb.ts +++ b/lib/tmdb.ts @@ -36,10 +36,6 @@ export interface TmdbMovieDetails { keywords?: { keywords: Array<{ id: number; name: string }>; }; - credits?: { - cast: Array<{ name: string; character: string }>; - crew: Array<{ name: string; job: string; department: string }>; - }; } function getApiKey(): string { @@ -85,7 +81,7 @@ export async function searchMovies(query: string): Promise { export async function getMovieDetails(movieId: number): Promise { return tmdbFetch(`/movie/${movieId}`, { - append_to_response: "release_dates,credits,keywords", + append_to_response: "release_dates,keywords", }); } @@ -115,14 +111,6 @@ export function formatMovieContext(movie: TmdbMovieDetails): string { const genres = movie.genres.map((g) => g.name).join(", "); const keywords = movie.keywords?.keywords.map((k) => k.name).join(", ") ?? ""; const certification = getUsCertification(movie); - const directors = movie.credits?.crew - .filter((c) => c.job === "Director") - .map((c) => c.name) - .join(", "); - const leadCast = movie.credits?.cast - .slice(0, 5) - .map((c) => `${c.name} as ${c.character}`) - .join("; "); const releaseDates = movie.release_dates?.results .map((country) => { @@ -146,10 +134,6 @@ export function formatMovieContext(movie: TmdbMovieDetails): string { `Overview: ${movie.overview}`, certification ? `US Certification: ${certification}` : null, keywords ? `Keywords: ${keywords}` : null, - directors ? `Director(s): ${directors}` : null, - leadCast ? `Lead cast: ${leadCast}` : null, - movie.budget ? `Budget: $${movie.budget.toLocaleString("en-US")}` : null, - movie.revenue ? `Revenue: $${movie.revenue.toLocaleString("en-US")}` : null, releaseDates ? `International certifications:\n${releaseDates}` : null, ] .filter(Boolean) diff --git a/package-lock.json b/package-lock.json index 27719b0..a326682 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2534,7 +2534,7 @@ "version": "20.19.42", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.42.tgz", "integrity": "sha512-5L7SUaFC1RyDraj2yRhyBzHTobyXHmohD100CChNtyPyleoq37Mqab5Gn8XEKI04dfN/oqPdpHk38MgcQWHbZg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -8208,7 +8208,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/unrs-resolver": {