- Static home page with ISR (
src/app/page.tsx
) and lazy-loaded search. - Aggressive API caching headers and Redis-backed query caching (
src/lib/cache.ts
). - Prisma
select
-only responses on hot endpoints and reduced payloads. - Bundle trimming via
modularizeImports
and fewer fonts. - Tailwind v4 JIT already enabled; keep CSS minimal.
Add to .env.local
to enable Redis caching:
UPSTASH_REDIS_REST_URL=...
UPSTASH_REDIS_REST_TOKEN=...
If not set, an in-memory cache is used.
A minimalist, premium platform for rating actors' performances in specific movies using five Oscar-inspired criteria.
- Live Search Suggestions: Real-time autocomplete as you type
- Multi-Entity Search: Search by movie name, actor name, or character name
- Clickable Results: All search results are clickable and navigate directly to performance pages
- Smart Categorization: Results are organized by Performances, Actors, and Movies
- Debounced Search: Optimized performance with 300ms debouncing
-
5 Oscar-Inspired Criteria:
- Technical Skill (20% weight): Voice control, physical presence, technique mastery
- Emotional Depth (25% weight): Range of emotions, authenticity, vulnerability
- Character Transformation (25% weight): Physical/mental transformation, believability
- Story Impact (15% weight): Essential to film's narrative and emotional impact
- Difficulty Factor (15% weight): Challenge of role, accents, physicality, historical accuracy
-
Interactive Sliders: Beautiful, responsive rating sliders with visual feedback
-
Real-time Score Calculation: Weighted average score updates as you adjust ratings
-
Quality Zones: Visual indicators (Poor, Fair, Good, Very Good, Excellent, Outstanding)
-
Draft Saving: Auto-saves your progress as you rate
- Performance Detail Pages: View existing ratings with detailed breakdowns
- Integrated Rating Forms: Rate performances directly from their detail pages
- Success Confirmations: Clear feedback when ratings are submitted
- Anonymous Ratings: Store ratings anonymously (user authentication ready)
- Global Search: Search across all actors, movies, and performances
- Performance-Focused Results: Prioritize performance results in search
- Quick Navigation: Direct links to performance pages from search results
- Responsive Design: Works seamlessly on desktop and mobile
- Node.js 18+
- PostgreSQL database
- npm or yarn
-
Clone the repository
git clone <repository-url> cd actor-rating
-
Install dependencies
npm install
-
Set up environment variables
cp .env.example .env.local
Configure your database and Supabase Auth settings in
.env.local
:# Database DATABASE_URL="postgresql://user:password@localhost:5432/actor_rating_db" # Supabase Auth (required) NEXT_PUBLIC_SUPABASE_URL="your_supabase_project_url" NEXT_PUBLIC_SUPABASE_ANON_KEY="your_supabase_anon_key" SUPABASE_SERVICE_ROLE_KEY="your_supabase_service_role_key" # Optional: Redis caching UPSTASH_REDIS_REST_URL="your_redis_url" UPSTASH_REDIS_REST_TOKEN="your_redis_token"
-
Set up Supabase Auth
- Create a new project at supabase.com
- Go to Authentication > Settings in your Supabase dashboard
- Enable Google OAuth provider and configure with your Google OAuth credentials
- Set the redirect URL to:
https://your-project-ref.supabase.co/auth/v1/callback
- Copy your project URL and anon key to your
.env.local
-
Set up the database
npx prisma generate npx prisma db push npx prisma db seed
-
Start the development server
npm run dev
-
Open your browser Navigate to
http://localhost:3000
-
Search for a Performance
- Use the search bar on the homepage
- Type an actor name, movie title, or character name
- Click on a performance result to view details
-
Rate the Performance
- Click "Rate Performance" on the performance detail page
- Adjust the 5 sliders based on Oscar-inspired criteria
- Add optional comments about the performance
- Submit your rating
-
View Results
- See your rating alongside others
- View detailed breakdowns of all criteria
- Compare different performances
- Live Autocomplete: Start typing to see instant suggestions
- Categorized Results: Results are organized by type (Actors, Movies)
- Quick Navigation: Click any result to go directly to that page
- Smart Filtering: Search across multiple fields simultaneously
The search API provides powerful full-text search capabilities across movies, actors, and performances.
Endpoint: GET /api/search?q=<search_term>
Parameters:
q
(required): Search query (minimum 2 characters)
Response Format:
{
"movies": [{ "id": "string", "title": "string" }],
"actors": [{ "id": "string", "name": "string" }]
}
Features:
- Full-text Search: Uses PostgreSQL
to_tsvector
andplainto_tsquery
for natural language search - Trigram Similarity: Falls back to
similarity()
function for fuzzy matching - Parameterized Queries: Prevents SQL injection attacks
- Result Limiting: Maximum 10 results per category
- Error Handling: Returns 400 for invalid queries, 500 for server errors
Example Usage:
# Search for movies
curl "http://localhost:3000/api/search?q=Inception"
# Search for actors
curl "http://localhost:3000/api/search?q=Leonardo"
- Frontend: Next.js 15, React 19, TypeScript
- Styling: Tailwind CSS, Framer Motion
- Database: PostgreSQL with Prisma ORM
- Authentication: Supabase Auth with SSR support
- Deployment: Vercel-ready
- Search: PostgreSQL full-text search with trigram similarity
- Caching: Redis (optional) with in-memory fallback
The platform uses a relational database with the following key models:
- Actor: Actor information and metadata
- Movie: Movie details and metadata
- Performance: Individual performance ratings with 5 criteria
- User: User accounts and authentication
- Rating: Alternative rating model with weighted scores
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
This repo includes a production-ready share pipeline:
- API
POST /api/generate-share
generates images, uploads to S3, creates a shortlink, and returns URLs. - Edge
GET /api/og?ratingId=<id_or_slug>&size=og|feed|story
renders a PNG for quick testing. - Rating page
/r/[slug]
renders server-side with OG tags pointing to the generated OG image. - Shortlink
/s/:code
redirects to rating page and logs clicks.
- Copy env and run services:
cp env.example .env
docker-compose up -d
- Migrate and seed demo data:
npx prisma migrate dev
npm run demo:seed
- Run dev server:
npm run dev
- Test OG endpoint and save image:
curl 'http://localhost:3000/api/og?ratingId=demo-123&size=og' > demo.png
- Generate share assets for demo rating:
curl -X POST 'http://localhost:3000/api/generate-share' \
-H 'Content-Type: application/json' \
-d '{"ratingId": "demo-123"}'
- POST
/api/generate-share
β returns{ feedUrl, storyUrl, ogUrl, pageUrl, shortUrl }
- GET
/api/og?ratingId=...&size=og|feed|story
β PNG with cache headers - GET
/s/:code
β 302 redirect to rating page; logs click - Page
/r/[slug]
β SSR page with OG meta
DATABASE_URL
NEXT_PUBLIC_BASE_URL
S3_BUCKET
,S3_REGION
,AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
SHORT_URL_DOMAIN
(optional; defaults toNEXT_PUBLIC_BASE_URL
)REDIS_URL
(optional)USE_PUPPETEER
(optional fallback)TMDB_API_KEY
(optional, not needed for share pipeline)
- Set Vercel envs:
NEXT_PUBLIC_SUPABASE_URL
,NEXT_PUBLIC_SUPABASE_ANON_KEY
,SUPABASE_SERVICE_ROLE_KEY
. - In Supabase dashboard: enable Google provider and set Google client ID/secret.
- In Google Cloud Console: set Authorized redirect URI to the Supabase callback URL:
https://<supabase-project-ref>.supabase.co/auth/v1/callback
. - Redeploy.
Default is AWS S3. Override CDN_BASE_URL
to serve through CloudFront or another CDN. Keys are written under share/{kind}/{slug}.png
.
Run tests locally:
npm test
GitHub Actions CI runs migrations, seeds demo, and tests on each push.
- Deploy to Vercel; set env vars above.
- Create S3 bucket and CloudFront distribution; set
CDN_BASE_URL
to CloudFront domain. - Ensure bucket policy allows public GET or use CloudFront OAI.
- Cache images long-lived; invalidate when regenerating.
-
Image endpoint sends
s-maxage
for CDN caching. -
Add queueing (BullMQ/Redis) around
generate-share
for heavy traffic. -
Apply rate limits per IP using
src/lib/rateLimit.ts
. -
Inspired by Oscar voting criteria
-
Built with modern web technologies
-
Designed for performance enthusiasts and critics