Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Node Next.js TS Tailwind License Vercel

Supjav β€” JAV Streaming Platform

A full-stack streaming website with a Next.js 16 + TypeScript frontend and built-in API routes for scraping β€” featuring a sleek red & blue glassmorphism design.
Deploy to Vercel in one click.

Home Β  Player


Table of Contents


πŸ— Architecture

A single Next.js 16 project containing both the frontend (SSR pages) and the scraper API (serverless functions).

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Next.js 16 + TS                     β”‚
β”‚                                      β”‚
β”‚  src/app/page.tsx  ──fetch──▢  /api/β”‚
β”‚  (SSR + ISR)              β”‚         β”‚
β”‚                           β”‚         β”‚
β”‚               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚               β”‚  API Routes       β”‚  β”‚
β”‚               β”‚  (serverless)     β”‚  β”‚
β”‚               β”‚  cheerio + axios  β”‚  β”‚
β”‚               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β–Ό
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚   javtiful.com   β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Everything lives at the project root β€” no subdirectories, no separate scraper server. The scraper logic is embedded as Next.js API routes (src/app/api/*). Deploy the entire app to Vercel with a single push.


πŸš€ Quick Start

Prerequisites

  • Node.js 18+ and npm 9+

1. Clone

git clone https://github.com/zainaqdas/supjav.git
cd supjav

2. Install & run

npm install
npm run dev
# β†’ Opens at http://localhost:3000

The API routes are included β€” no separate scraper server needed!


🚒 Deploy to Vercel

Quick Deploy

  1. Push this repo to GitHub
  2. Go to vercel.com/new and import the repo
  3. Click Deploy

That's it! Vercel auto-detects Next.js β€” no root directory or configuration needed.

Manual Deploy (CLI)

npx vercel
# Follow the prompts to link and deploy

Configuration

The root vercel.json is pre-configured:

Setting Value
Framework nextjs
Build command npm run build
Output directory .next

Environment Variables (Vercel Dashboard)

Variable Value Required
NEXT_PUBLIC_API_URL (leave empty β€” uses internal /api) No

No environment variables needed. The API routes are self-contained within the Next.js app.


πŸ”Œ Scraper API

The scraper parses HTML from javtiful.com and exposes a clean JSON REST API at /api/*.

Base URL: http://localhost:3000/api/* (same origin as the frontend)

API Endpoints

Listing Endpoints

Endpoint Method Params Description
/api/main GET ?page=1 Latest videos (paginated)
/api/trending GET ?page=1 Popular/trending videos (paginated)
/api/categories GET β€” All 21 categories with video counts
/api/category/:slug GET ?page=1 Videos in a category (paginated)
/api/actresses GET β€” All actresses with video counts
/api/actress/:slug GET ?page=1 Videos by an actress (paginated)
/api/channels GET β€” All channels/studios with video counts
/api/channel/:slug GET ?page=1 Videos by a channel (paginated)
/api/search GET ?q=query&page=1 Search videos (paginated)

Video Detail Endpoints

Endpoint Description
/api/video/:id Full video detail (title, poster, metadata, stream URLs)
/api/video/:id/:slug Same as above, but slug ensures correct route matching
/api/video/:id/stream Lightweight β€” returns only stream URLs + quality options
/api/video/:id/comments Video comments (AJAX endpoint)
/api/video/:id/download-link Download link (requires X-CSRF-Token header)
/api/csrf-token Get CSRF token for authenticated requests

Root

Endpoint Description
/ Frontend home page
/api API documentation β€” lists all endpoints and query parameters

Data Types

VideoResult (listing)

{
  "id": "108365",
  "slug": "hrsm-146",
  "title": "HRSM-146 Video Title",
  "url": "https://javtiful.com/video/108365/hrsm-146",
  "thumbnail": "https://...",
  "previewVideo": "https://...",
  "duration": "120 min",
  "quality": "HD",
  "views": "12.3k",
  "timeAgo": "2 days ago",
  "badges": ["Uncensored"]
}

VideoDetail (full)

{
  "id": "108365",
  "slug": "hrsm-146",
  "title": "HRSM-146 Video Title",
  "poster": "https://...",
  "description": "...",
  "keywords": ["keyword1", "keyword2"],
  "videoCode": "HRSM-146",
  "releaseDate": "2024-01-15",
  "qualityOptions": [480, 720, 1080],
  "defaultQuality": 720,
  "streams": [
    {
      "url": "https://...cloudflarestorage.com/...mp4?...",
      "type": "video/mp4",
      "quality": "720p"
    }
  ],
  "previewSources": ["https://jav.si/..."],
  "thumbnails": ["https://..."],
  "actresses": [{ "slug": "actress-name", "name": "Actress Name" }],
  "tags": [{ "type": "category", "slug": "amateur", "name": "Amateur" }],
  "endpoints": {
    "comments": "/video/108365/comments",
    "playlist": "/video/108365/playlist",
    "downloadLink": "/video/108365/download-link",
    "favorite": "/video/108365/favorite",
    "report": "/video/108365/report"
  }
}

Stream URLs are Cloudflare R2 pre-signed URLs valid for approximately 1 hour. They are extracted from the #frontWatchConfig JSON blob embedded in the source video page.

PaginatedResponse

{
  "source": "main",
  "page": 1,
  "totalPages": 3,
  "totalResults": 42,
  "videos": [...]
}

🎨 Next.js Frontend

A modern, responsive streaming website built with Next.js 16, TypeScript, and Tailwind CSS 4.

Design

  • Theme: Deep dark backgrounds (#0a0a0f) with red (#ff4444) and blue (#4488ff) gradient accents
  • Glassmorphism cards with hover overlays, animated border gradients, and fade-in-up animations
  • Custom scrollbar, skeleton shimmer loaders, gradient text, and micro-interactions throughout
  • Fully responsive β€” mobile hamburger nav, adaptive grids

Categories Β  Search

Pages & Routes

Page Route Description
Home / Hero section, latest videos grid, trending section
Trending /trending Popular videos (paginated)
Categories /categories Grid of all 21 categories
Category /category/:slug Videos filtered by category (paginated)
Actresses /actresses Grid of all actresses
Actress /actress/:slug Videos by an actress (paginated)
Channels /channels Grid of all channels/studios
Channel /channel/:slug Videos by a channel (paginated)
Search /search?q=query Search results (paginated)
Video /video/:id/:slug Full video page with player, metadata, actresses, tags, thumbnails
404 /[...] Custom not-found page
Error * Error boundary with reset button
Loading * Skeleton shimmer while pages load

Components

Component Description
VideoPlayer Custom HTML5 player with play/pause, progress bar, volume, quality selector, fullscreen, auto-hide controls
VideoCard Glassmorphism card with hover preview, quality/duration badges, gradient overlays
PreviewVideo 'use client' sub-component for mouse-enter preview playback
VideoGrid Responsive CSS grid with staggered fade-in-up animations
Navbar Sticky nav with scroll blur, mobile hamburger menu, inline search
Footer Links and branding
Pagination 'use client' component with prev/next, page numbers, dots, gradient active state
SectionHeader Gradient-text section titles with optional "View All" link

πŸ”§ Environment Variables

.env.local

Variable Default Description
NEXT_PUBLIC_API_URL /api Base URL for scraper API. Leave empty for internal API routes.

πŸ›  Tech Stack


πŸ“ Project Structure

A single, consolidated Next.js project at root β€” no subdirectories, no separate servers.

supjav/
β”œβ”€β”€ package.json              # Single package.json for everything
β”œβ”€β”€ next.config.ts            # Next.js configuration
β”œβ”€β”€ tsconfig.json             # TypeScript configuration
β”œβ”€β”€ vercel.json               # Vercel deployment config (framework: nextjs)
β”œβ”€β”€ postcss.config.mjs        # PostCSS / Tailwind config
β”œβ”€β”€ eslint.config.mjs         # ESLint configuration
β”œβ”€β”€ .gitignore
β”œβ”€β”€ README.md
β”œβ”€β”€ public/                   # Static assets (favicons, SVGs)
└── src/
    β”œβ”€β”€ app/
    β”‚   β”œβ”€β”€ globals.css       # Global styles & Tailwind imports
    β”‚   β”œβ”€β”€ layout.tsx        # Root layout (theme, fonts, metadata, force-dynamic)
    β”‚   β”œβ”€β”€ page.tsx          # Home page (hero, featured, latest, trending)
    β”‚   β”œβ”€β”€ loading.tsx       # Global loading skeleton (shimmer)
    β”‚   β”œβ”€β”€ error.tsx         # Error boundary with reset
    β”‚   β”œβ”€β”€ not-found.tsx     # Custom 404 page
    β”‚   β”œβ”€β”€ favicon.ico
    β”‚   β”œβ”€β”€ trending/
    β”‚   β”‚   └── page.tsx      # /trending
    β”‚   β”œβ”€β”€ categories/
    β”‚   β”‚   └── page.tsx      # /categories
    β”‚   β”œβ”€β”€ category/
    β”‚   β”‚   └── [slug]/
    β”‚   β”‚       └── page.tsx  # /category/:slug
    β”‚   β”œβ”€β”€ actresses/
    β”‚   β”‚   └── page.tsx      # /actresses
    β”‚   β”œβ”€β”€ actress/
    β”‚   β”‚   └── [slug]/
    β”‚   β”‚       └── page.tsx  # /actress/:slug
    β”‚   β”œβ”€β”€ channels/
    β”‚   β”‚   └── page.tsx      # /channels
    β”‚   β”œβ”€β”€ channel/
    β”‚   β”‚   └── [slug]/
    β”‚   β”‚       └── page.tsx  # /channel/:slug
    β”‚   β”œβ”€β”€ search/
    β”‚   β”‚   └── page.tsx      # /search?q=query
    β”‚   β”œβ”€β”€ video/
    β”‚   β”‚   └── [id]/
    β”‚   β”‚       └── [slug]/
    β”‚   β”‚           └── page.tsx  # /video/:id/:slug (player, metadata, related)
    β”‚   └── api/              # ← All scraper endpoints (serverless on Vercel)
    β”‚       β”œβ”€β”€ route.ts                  # API docs (GET /api)
    β”‚       β”œβ”€β”€ main/route.ts             # GET /api/main?page=1
    β”‚       β”œβ”€β”€ trending/route.ts         # GET /api/trending?page=1
    β”‚       β”œβ”€β”€ categories/route.ts       # GET /api/categories
    β”‚       β”œβ”€β”€ category/[slug]/route.ts  # GET /api/category/:slug?page=1
    β”‚       β”œβ”€β”€ actresses/route.ts        # GET /api/actresses
    β”‚       β”œβ”€β”€ actress/[slug]/route.ts   # GET /api/actress/:slug?page=1
    β”‚       β”œβ”€β”€ channels/route.ts         # GET /api/channels
    β”‚       β”œβ”€β”€ channel/[slug]/route.ts   # GET /api/channel/:slug?page=1
    β”‚       β”œβ”€β”€ search/route.ts           # GET /api/search?q=query&page=1
    β”‚       β”œβ”€β”€ video/[id]/route.ts       # GET /api/video/:id
    β”‚       β”œβ”€β”€ video/[id]/[slug]/route.ts   # GET /api/video/:id/:slug
    β”‚       β”œβ”€β”€ video/[id]/stream/route.ts   # GET /api/video/:id/stream
    β”‚       β”œβ”€β”€ video/[id]/comments/route.ts # GET /api/video/:id/comments
    β”‚       β”œβ”€β”€ video/[id]/download-link/route.ts  # GET /api/video/:id/download-link
    β”‚       └── csrf-token/route.ts       # GET /api/csrf-token
    β”œβ”€β”€ components/
    β”‚   β”œβ”€β”€ Navbar.tsx            # Sticky nav with scroll blur, mobile hamburger, search
    β”‚   β”œβ”€β”€ Footer.tsx            # Links and branding
    β”‚   β”œβ”€β”€ VideoCard.tsx         # Glassmorphism card with hover overlay & badges
    β”‚   β”œβ”€β”€ PreviewVideo.tsx      # 'use client' mouse-enter preview playback
    β”‚   β”œβ”€β”€ VideoPlayer.tsx       # Custom player: play/pause, volume, quality, fullscreen
    β”‚   β”œβ”€β”€ VideoGrid.tsx         # Responsive grid with fade-in-up animations
    β”‚   β”œβ”€β”€ Pagination.tsx        # 'use client' prev/next, page numbers, gradient active
    β”‚   └── SectionHeader.tsx     # Gradient-text titles with optional "View All" link
    └── lib/
        β”œβ”€β”€ api.ts                # Centralized API client (fetch wrapper with ISR caching)
        β”œβ”€β”€ types.ts              # TypeScript interfaces (VideoResult, VideoDetail, etc.)
        └── scraper.ts            # Core scraping engine (TypeScript ESM, cheerio + axios)

πŸ“„ License

MIT Β© zainaqdas


Built with ❀️ using Next.js, cheerio, and TypeScript

Releases

Packages

Contributors

Languages