openjutsu
영상에서 원클릭으로 인물 교체, ComfyUI·MiniMax H3 기반 오픈소스 로컬 힉스필드 겐주츠 대안, FLUX.3 Klein 재조명 지원
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A Next.js 15 web app for discovering, rating, and getting AI-powered recommendations for TV shows and movies.
Users can search for titles, maintain a watchlist, rate shows/movies 1-5 stars, and receive personalised AI recommendations. The homepage also features daily AI-curated picks sourced from online community buzz.
openai) - single-call structured output for recommendations; Responses API with web_search_preview for cronvercel.json)Install dependencies:
yarn install
Copy .env.local.example to .env.local and fill in the required values (see Environment Variables below).
Run the development server:
yarn dev
Open http://localhost:3000.
| Variable | Description |
|---|---|
TMDB_API_KEY | TMDB v3 API key |
TMDB_ACCESS_TOKEN | TMDB v4 Bearer token (used for all requests) |
OPENAI_API_KEY | OpenAI API key - used for recommendations and cron web search |
DATABASE_URL | Neon PostgreSQL connection string (pooled) |
DATABASE_URL_UNPOOLED | Neon PostgreSQL connection string (direct, for migrations) |
NEXTAUTH_SECRET | NextAuth secret |
NEXTAUTH_URL | App base URL (e.g. http://localhost:3000) |
GOOGLE_CLIENT_ID | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Google OAuth client secret |
CRON_SECRET | Bearer token for Vercel cron authentication |
NEXT_PUBLIC_CACHE_VERSION | Cache-busting version for client-side SWR requests |
STRIPE_SECRET_KEY | Stripe secret key (sk_test_... locally, sk_live_... on Vercel) |
STRIPE_WEBHOOK_SECRET | Stripe webhook signing secret (see note below) |
STRIPE_PRICE_ID | Stripe Price ID for the £1.99/month Pro plan (price_...) |
OMDB_API_KEY | OMDb API key for fetching IMDb and Rotten Tomatoes ratings on title pages - free tier (1,000 req/day) at omdbapi.com. If unset, both rating pills are hidden. |
The project uses Drizzle ORM with a Neon PostgreSQL database.
| Table | Purpose |
|---|---|
users | Google OAuth users + Stripe subscription state |
titles | TMDB title cache (keyed by tmdb_id + media_type) |
user_titles | Watchlist entries and ratings (status: WATCHLIST | RATED, rating: 1-5) |
recommendation_sets | Cached AI recommendation batches (7-day expiry) |
recommendation_items | Individual titles within a recommendation set |
ai_popular_titles | Daily AI-curated popular titles populated by the cron job |
yarn db:generate # Generate Drizzle migration files from schema changes
yarn db:push # Push schema changes directly to the database
yarn db:studio # Open Drizzle Studio (database browser)
Note:
db:pushcan get stuck prompting about existing constraints. When that happens, run the SQL statements directly via@neondatabase/serverlessusingDATABASE_URL_UNPOOLED.
| Method | Route | Description |
|---|---|---|
GET | /api/discover?type=movie|tv&timeframe=recent|all | TMDB popular or top-rated titles |
GET | /api/discover?type=movie|tv&source=ai | Daily AI picks from the ai_popular_titles table |
GET | /api/autocomplete?q={query} | TMDB title search for the search bar |
GET | /api/resolve-title?title={title}&type=movie|tv | Advanced TMDB title resolution with scoring |
| Method | Route | Description |
|---|---|---|
GET | /api/watchlist | Get the current user's watchlist |
POST | /api/watchlist | Add a title to the watchlist |
DELETE | /api/watchlist | Remove a title from the watchlist |
GET | /api/rated | Get all titles the current user has rated |
POST | /api/rated | Rate a title (1-5 stars) |
GET | /api/rating?tmdbId={id}&type=movie|tv | Get the current user's rating for a specific title |
GET | /api/recommendations | Fetch cached AI recommendations for the current user |
POST | /api/recommend | Generate AI recommendations via OpenAI - subscription-gated (3 free lifetime calls, then £1.99/month) |
GET | /api/subscription-status | Returns current user's subscription status and free call count |
POST | /api/stripe/checkout | Create a Stripe Checkout session for TellySauce Pro |
POST | /api/stripe/portal | Create a Stripe Billing Portal session (manage/cancel subscription) |
| Method | Route | Description |
|---|---|---|
GET | /api/cron/ai-popular | Daily job: fetch AI picks via OpenAI web search, resolve via TMDB, store in DB |
The cron route requires Authorization: Bearer $CRON_SECRET. Vercel adds this header automatically when the env var is set. To trigger manually:
curl -H "Authorization: Bearer <CRON_SECRET>" https://<your-domain>/api/cron/ai-popular
All AI calls use the shared openai client from src/lib/ai.ts.
Recommendations (src/app/api/recommend/route.ts): a single gpt-4o-mini call using response_format: json_schema (strict structured output). Returns { recommendations: [...] } directly - no intermediate text parsing or retry loops.
Cron (src/app/api/cron/ai-popular/route.ts): a 4-stage pipeline:
openai.responses.create with gpt-4o-mini + web_search_preview tool. Finds trending titles from Reddit.gpt-4o-mini chat completions with json_schema. Parses the Stage 1 text into structured title objects.gpt-4o-mini chat completions with json_schema. Generates Reddit-style viewer quotes per title.Scheduled daily at 06:00 UTC. The job:
gpt-4o-mini + web_search_preview tool) to find the 10 most positively discussed movies and TV shows from the past 7 days across Reddit and similar communitiesai_popular_titles with a fetched_date batch keyRegional focus: prioritises English-speaking markets (US, UK, AU, CA, IE) and Western Europe. East Asian content is included only for major Western crossovers (e.g. Squid Game, Parasite).
Guard: if 0 titles resolve successfully, the DB write is skipped and the previous day's data is preserved.
New-first ordering: before writing today's batch, the previous day's titles are queried. Titles not seen yesterday are assigned lower rank values and appear at the start of the carousel; duplicate/returning titles follow in their AI-returned order.
The /api/recommend route uses the user's rating history to generate a personalised recommendation list via OpenAI. Results are cached in recommendation_sets / recommendation_items for 7 days.
All TMDB requests use the v4 Bearer token (TMDB_ACCESS_TOKEN).
fetchTMDBTitle(tmdbId, mediaType) - src/server/tmdb.ts - canonical function for fetching full title detailsyear, TV shows use first_air_date_yearfetchTitleSources(kind, id, revalidate) - returns streaming providers for all regions as Record<string, TitleSource[]>. The title page passes this to WhereToWatch, which lets users pick their country from a dropdown. The selected region persists in localStorage (watch_region key) and auto-detects from navigator.language on first visit.AI recommendations (profile and seed modes) are gated behind a £1.99/month subscription (TellySauce Pro). Users get 3 free lifetime recommendation generations before the paywall appears. Daily AI picks remain free.
price_... ID into STRIPE_PRICE_ID./api/stripe/webhook listening to: customer.subscription.created, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed. Copy the signing secret into STRIPE_WEBHOOK_SECRET.The Stripe CLI forwards events to your local server:
stripe listen --forward-to localhost:3000/api/stripe/webhook
Important: The
whsec_...secret printed bystripe listenis different from the one in the Stripe dashboard. Use the CLI secret in.env.localand the dashboard secret in Vercel environment variables.
Test with card number 4242 4242 4242 4242, any future expiry, any CVC.
The project uses Vitest + React Testing Library + MSW for mocking.
yarn test # Run all tests (watch mode)
yarn test:coverage # Run with coverage report
Test files live next to the code they test (*.test.ts / *.test.tsx). Global test setup is in src/test/setup.ts and shared MSW handlers in src/test/mocks/.
Deployed on Vercel. The vercel.json at the project root configures the daily cron job. Make sure CRON_SECRET is set in your Vercel project environment variables - Vercel uses it to authenticate cron requests automatically.