An entry for the streamplace vod showcase
Streamhut Frontend#
Nuxt 4 web application for browsing and watching videos on Streamhut.
Features#
- Video Playback - HLS streaming with hls.js
- Hover Previews - YouTube-style sprite sheet previews
- Creator Profiles - Browse videos by creator
- Watch History - Local storage tracking of watched videos
- Search - Filter videos by title
- Social Sharing - Share videos and creator profiles with rich link previews
- Responsive Design - Works on desktop and mobile
Pages#
| Route | Description |
|---|---|
/ |
Home page with featured video, latest, and recommended sections |
/watch?v={uri} |
Video player with related videos sidebar |
/profile/{did} |
Creator profile with their videos |
/search?q={query} |
Search results |
/docs |
Documentation |
Development#
# Install dependencies
bun install
# Start dev server
bun run dev
# Build for production
bun run build
# Generate static site
bun run generate
Configuration#
Create .env in the frontend directory:
# Required: at-run runner URL
NUXT_PUBLIC_RUNNER_URL=https://at-run.example.com
# Required: Bundle path for VOD API
NUXT_PUBLIC_BUNDLE_PATH=/bundle/did:plc:xxx/atmosphereconf-vod/latest
Architecture#
apps/frontend/
├── app/
│ ├── pages/
│ │ ├── index.vue # Home page
│ │ ├── watch.vue # Video player
│ │ ├── search.vue # Search results
│ │ └── profile/
│ │ └── [did].vue # Creator profile
│ ├── components/
│ │ └── VideoCard.vue # Video thumbnail with hover preview
│ ├── composables/
│ │ ├── useApi.ts # VOD API client
│ │ ├── useWatchHistory.ts # Local watch history
│ │ └── useShare.ts # Social sharing utilities
│ └── types/
│ └── index.ts # TypeScript types
├── nuxt.config.ts # Nuxt configuration
└── package.json
Composables#
useApi()#
API client for the VOD backend.
const {
listVideos, // Fetch video list
batchCheckMetadata, // Check which videos have thumbnails
batchGetProfiles, // Fetch creator profiles
getPlaylistUrl, // Get HLS playlist URL
formatDuration, // Format nanoseconds to "1:23:45"
} = useApi()
useWatchHistory()#
Track watched videos in localStorage.
const {
recordWatch, // Record a watch session
getContinueWatching, // Get videos with progress < 90%
sortByRecommendation, // Sort videos by watch history
} = useWatchHistory()
useShare()#
Share videos and creators.
const {
shareVideo, // Copy/share video link
shareCreator, // Copy/share creator link
} = useShare()
Video Player#
Uses hls.js for HLS playback:
import Hls from 'hls.js'
const hls = new Hls()
hls.loadSource(playlistUrl)
hls.attachMedia(videoElement)
Hover Previews#
The VideoCard component shows sprite previews on hover:
- Fetches sprite VTT from
/getVtt?uri=... - Parses timestamp-to-coordinates mapping
- On hover, cycles through frames using CSS
background-position
Static Generation#
The app uses ssr: false and generates a static SPA:
bun run generate
Output goes to .output/public/ (symlinked to dist/).
Styling#
- CSS custom properties for theming (
--bg,--text,--border, etc.) - Dark theme by default
- Instrument Serif for headings
- Inter for body text
- Responsive breakpoints at 600px, 800px, 1000px, 1200px