Overview
The Shorts feature on Jefftube provides a mobile-optimized, vertical video viewing experience similar to TikTok, Instagram Reels, or YouTube Shorts. Videos marked with the is_shorts flag are displayed in a full-screen, swipeable format.
What Are Shorts?
Shorts are videos specifically marked for vertical viewing:
export const videos = pgTable ( "videos" , {
id: varchar ( "id" , { length: 50 }). primaryKey (),
title: varchar ( "title" , { length: 255 }),
is_shorts: boolean ( "is_shorts" ). notNull (). default ( false ), // Marks video as a short
// ... other fields
});
The is_shorts flag determines whether a video appears on the Shorts page. Videos are not automatically classified—they must be explicitly marked in the database.
Accessing Shorts
Navigate to the Shorts page by:
Click Shorts in Navigation
Select “Shorts” from the sidebar menu (desktop) or navigation drawer (mobile).
Direct URL
Navigate to /shorts in your browser.
Shorts Interface
The Shorts page provides a unique full-screen viewing experience:
Layout
Full-Screen Video Each short takes up the full viewport height (minus header), optimized for vertical 9:16 aspect ratio videos.
Snap Scrolling Swipe or scroll to navigate between shorts. The interface snaps to each video for a clean viewing experience.
Auto-Play The currently visible short automatically starts playing. Scrolling to a new video pauses the previous one and plays the new one.
Video Player
< div className = "h-[calc(100vh-56px)] snap-start flex items-center justify-center" >
< div className = "relative h-full aspect-9/16 bg-black rounded-xl overflow-hidden" >
{ /* Poster image when not active */ }
{ showPoster && (
< img src = { thumbnailUrl } className = "absolute inset-0 object-contain" />
) }
{ /* Video element */ }
< video
ref = { videoRef }
src = { getVideoUrl ( video . filename ) }
className = "w-full h-full object-contain"
loop
playsInline
onClick = { togglePlay }
/>
</ div >
</ div >
Navigation Controls
Mobile Navigation
Swipe up to see the next short, swipe down to return to the previous one. The interface uses snap scrolling for smooth transitions.
Tap anywhere on the video to pause/play. A brief play/pause icon overlay confirms the action.
Desktop Navigation
On larger screens (≥ 1024px), dedicated navigation buttons appear:
< div className = "fixed right-6 top-1/2 -translate-y-1/2 flex-col gap-3 z-50" >
< button
onClick = { goPrev }
disabled = { activeIndex === 0 }
className = "w-12 h-12 rounded-full bg-secondary"
>
< NavUpIcon />
</ button >
< button
onClick = { goNext }
disabled = { activeIndex === videos . length - 1 }
className = "w-12 h-12 rounded-full bg-secondary"
>
< NavDownIcon />
</ button >
</ div >
Navigation buttons are hidden on mobile (< 1024px) to avoid cluttering the interface. Mobile users navigate via touch gestures.
Video Controls
Play/Pause Overlay
When you tap to play or pause, a temporary overlay appears:
< div className = { `transition-opacity ${ showPlayPauseOverlay ? 'opacity-100' : 'opacity-0' } ` } >
< div className = "w-20 h-20 rounded-full bg-black/60" >
{ overlayIcon === 'play' ? (
< svg viewBox = "0 0 24 24" fill = "currentColor" >
< path d = "M8 5v14l11-7z" />
</ svg >
) : (
< svg viewBox = "0 0 24 24" fill = "currentColor" >
< path d = "M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
</ svg >
) }
</ div >
</ div >
The overlay automatically fades after 1 second.
Top Controls
The top of the video displays:
Play/Pause Button Toggle video playback
Volume/Mute Button Toggle audio on/off
< div className = "absolute top-0 left-0 right-0 p-3 bg-gradient-to-b from-black/50" >
< button onClick = { togglePlay } >
{ isPlaying ? < PauseIcon /> : < PlayIcon /> }
</ button >
< button onClick = { toggleMute } >
{ isMuted ? < VolumeMutedIcon /> : < VolumeIcon /> }
</ button >
</ div >
Video Information Overlay
The bottom of each short displays video and channel information:
< div className = "absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/70" >
{ /* Channel info */ }
< div className = "flex items-center gap-3 mb-3" >
< Link to = "/" >
< Avatar src = { channelAvatar } size = "md" />
</ Link >
< Link to = "/" className = "font-semibold text-white" >
@jefferyepstein
</ Link >
</ div >
{ /* Video title */ }
< p className = "text-white line-clamp-2" > { video . title } </ p >
</ div >
The overlay uses a gradient background to ensure text remains readable over any video content.
Action Buttons
Action buttons are positioned on the right side of the screen:
Button Layout
Like Button
Shows a heart icon (filled when liked) and the total like count. < ActionButton
icon = { < LikeIcon filled = { userLike === true } /> }
label = { formatCount ( video . likes ) }
onClick = { handleLike }
active = { userLike === true }
/>
Comment Button
Shows a comment icon and comment count. Opens a slide-out comment modal. < ActionButton
icon = { < CommentIcon /> }
label = { formatCount ( video . commentCount ?? 0 ) }
onClick = { () => setShowComments ( true ) }
/>
Share Button
Copies the current video URL to clipboard. Changes to “Copied” for 1 second. < ActionButton
icon = { shareCopied ? < CheckIcon /> : < ShareIcon /> }
label = { shareCopied ? "Copied" : "Share" }
onClick = { handleShare }
/>
More Options
Displays additional options (three vertical dots).
Count Formatting
Large numbers are abbreviated for clean display:
function formatCount ( count : number ) : string {
if ( count >= 1_000_000 ) {
return ` ${ ( count / 1_000_000 ). toFixed ( 1 ). replace ( / \. 0 $ / , '' ) } M` ;
}
if ( count >= 1_000 ) {
return ` ${ ( count / 1_000 ). toFixed ( 1 ). replace ( / \. 0 $ / , '' ) } K` ;
}
return count . toString ();
}
// Examples:
// 1234 → "1.2K"
// 1234567 → "1.2M"
// 1000000 → "1M" (trailing .0 removed)
Clicking the comment button opens a full-height slide-out modal:
< div className = { `fixed top-0 right-0 h-full w-full sm:w-[400px] bg-primary z-50 transform ${ isOpen ? 'translate-x-0' : 'translate-x-full' } ` } >
{ /* Header */ }
< div className = "flex items-center justify-between p-4 border-b" >
< h2 > Comments { formatCount ( commentCount ) } </ h2 >
< button onClick = { onClose } >
< CloseIcon />
</ button >
</ div >
{ /* Comments content */ }
< div className = "h-[calc(100%-64px)] overflow-y-auto px-4" >
< CommentSection videoId = { videoId } />
</ div >
</ div >
On mobile, the modal takes full width. On larger screens (≥ 640px), it’s constrained to 400px width.
Modal Features
Slide Animation : Smoothly slides in from the right
Backdrop : Semi-transparent black overlay
Body Scroll Lock : Prevents background scrolling when open
Auto-Close : Closes automatically when navigating to a different short
Progress Bar
A thin progress bar at the bottom shows playback position:
< div className = "absolute bottom-0 left-0 right-0 h-1 bg-white/30" >
< div
className = "h-full bg-red-600"
style = { { width: ` ${ progress } %` } }
/>
</ div >
Progress updates in real-time as the video plays:
const handleTimeUpdate = () => {
const prog = ( videoEl . currentTime / videoEl . duration ) * 100 ;
setProgress ( isNaN ( prog ) ? 0 : prog );
};
Auto-Play Behavior
Shorts implement smart auto-play:
Detect Active Video
The scroll position determines which video is currently visible. const handleScroll = () => {
const scrollTop = container . scrollTop ;
const itemHeight = container . clientHeight ;
const newIndex = Math . round ( scrollTop / itemHeight );
setActiveIndex ( newIndex );
};
Play Active Video
When a video becomes active, it automatically plays and shows the actual video (hiding the poster). useEffect (() => {
if ( isActive ) {
setShowPoster ( false );
videoRef . current ?. play ();
} else {
videoRef . current ?. pause ();
videoRef . current . currentTime = 0 ;
setShowPoster ( true );
}
}, [ isActive ]);
Loop Playback
Videos automatically loop when they reach the end. < video loop playsInline />
Videos are set to preload="none" for inactive shorts to conserve bandwidth. Only the active video preloads and plays.
Performance Optimization
Virtualization
To handle many shorts efficiently, the page uses virtualization:
// Only render videos within range of current position
const BUFFER_SIZE = 2 ;
const virtualizedVideos = useMemo (() => {
const start = Math . max ( 0 , activeIndex - BUFFER_SIZE );
const end = Math . min ( videos . length , activeIndex + BUFFER_SIZE + 1 );
return videos . slice ( start , end ). map (( video , i ) => ({
video ,
originalIndex: start + i ,
}));
}, [ videos , activeIndex ]);
This renders:
The current video
2 videos before
2 videos after
Spacer divs for unmounted videos
Loading all video elements at once would consume massive amounts of memory and bandwidth. Virtualization renders only the videos near the current position, dramatically improving performance, especially with large catalogs.
Random Sorting
Shorts are displayed in random order to provide variety:
const { randomSortedShorts } = useData ();
The randomization happens server-side or in the data context, ensuring a consistent but unpredictable viewing order each session.
Responsive Design
Mobile-First Approach
The Shorts interface is optimized for mobile:
Touch Gestures : Swipe to navigate
Full-Screen : Maximizes video visibility
Large Tap Targets : Buttons sized for touch (48px minimum)
Overlaid Controls : Maximize video real estate
Desktop Adaptations
Centered Video Videos center on screen with black letterboxing
Navigation Buttons Circular up/down buttons for scrolling
Side Actions Action buttons positioned beside video, not overlaid
Hover States Interactive elements respond to mouse hover
{ /* Action buttons - mobile: overlaid, desktop: beside */ }
< div className = "absolute right-2 bottom-24 flex flex-col gap-3 lg:static lg:self-end lg:pb-24" >
{ /* Buttons */ }
</ div >
Keyboard Shortcuts
While not explicitly implemented in the current codebase, standard HTML5 video keyboard shortcuts work when the video element has focus (spacebar for play/pause, arrow keys for seek, etc.).
Differences from Regular Videos
Feature Regular Videos Shorts Page Layout Horizontal with sidebar Full-screen vertical Navigation Click suggested videos Swipe/scroll up/down Comments Below video Slide-out modal Aspect Ratio 16:9 (horizontal) 9:16 (vertical) Auto-Play On page load only On scroll to video Video Controls Standard HTML5 controls Custom overlaid controls Playlist Support Yes No