Warning
To avoid major frustration from Google and the YouTube Team, this project requires You to supply your own API key for access to YouTube related data and information. For more information, click here.
A lightweight Tube viewing experience.
LiteTube is a client-side, single-page web application I designed for a streamlined, minimalist experience when searching and viewing YouTube content. Built primarily with HTML, CSS, and modern Vanilla JavaScript, this project demonstrates strong client-side development principles, efficient API interaction, and performance optimization techniques.
It's an excellent example of a LocalStorage-based web app that utilizes the YouTube Data API for search and the YouTube Iframe Player API for robust video playback management.
This project is licensed under the MIT License. See the LICENSE.
I built LiteTube with a focus on efficiency, persistence, and a clean user experience.
-
API Key Persistence: Your YouTube Data API key is securely stored in LocalStorage and pre-filled on subsequent visits if the "Remember Key" option is checked. The key is masked for security after initial entry.
-
Persistent Search State: The last successful search query, current search filters, and the
nextPageTokenare saved to LocalStorage to maintain the application's state across sessions. -
Fully Responsive Layout: The application adapts fluidly. On desktops (
$>1024$px), it uses a 50/50 split for results and the player. On mobile and smaller screens, it automatically switches to a stacked, column layout. -
Advanced Search Filters: Filter results by Sort Order (Relevance, Date, View Count), Duration (Short, Medium, Long), and Upload Date (Last Hour, Day, Week, Month, Year).
-
Efficient Data Fetching: I use asynchronous JavaScript (
async/await) andPromise.all()to simultaneously fetch detailed video statistics (views, duration) and channel statistics (subscriber count) after the initial search. -
Custom Player Error Handling: I implement the YouTube Iframe Player API to detect and handle playback errors (e.g., embedding disabled by the creator). A custom error overlay displays an "Open on YouTube" fallback button when an error is detected.
-
Load More Pagination: I implement continuous loading for results using the API's
nextPageTokenfor a seamless "infinite scroll" experience. -
Optimized Rendering: I employ a
DocumentFragmentto batch multiple DOM insertions when displaying search results, minimizing layout thrashing and improving rendering performance.
| Language/Tool | Purpose |
|---|---|
| HTML5 | Core structure and semantic markup. |
| CSS3 | Minimal in-line styling and a single <style> block for layout and responsiveness. |
| JavaScript (ES6+) | All application logic, API interaction, state management, and DOM manipulation. |
| YouTube Data API v3 | Searching for videos and fetching statistics/details. |
| YouTube Iframe Player API | Handling video playback and detecting embed errors. |
| LocalStorage | Persistence for API key and last application state. |
To use LiteTube, you must have a valid YouTube Data API v3 key:
- Go to the Google Cloud Console.
- Create a new project (if necessary).
- Enable the YouTube Data API v3 service for your project.
- Create an API key under the Credentials section.
This is a single HTML file application:
- Save the project code as
litetube.html. - Open
litetube.htmldirectly in any modern web browser.
- Enter your YouTube Data API key into the input field at the top of the page.
- (Optional) Check the "Remember Key" box to save the key to your browser's LocalStorage.
- The main warning banner will disappear once a valid key is recognized.
- Enter a search query (e.g., "latest technology breakthroughs") into the search input.
- Adjust filters (Sort, Duration, Date) as needed.
- Click "Search Videos" or press Enter.
- Click on any video in the results list to load it into the Video Player.
To prevent a waterfall effect and speed up the display of rich result data (like views, subscribers, and duration), detail fetching is executed concurrently:
// Fetch details for all videos and their channels in parallel
const [videoDetailsMap, channelDetailsMap] = await Promise.all([
fetchVideoDetails(videoIds, currentKey), // Gets views, duration, tags
fetchChannelDetails(channelIds, currentKey) // Gets subscriber count
]);
The VideoPlayerController class intercepts API errors, providing a graceful fallback for users when the video creator has restricted embedding:
// Part of the VideoPlayerController class
onPlayerError(event) {
// Error codes 150, 101, 153 typically indicate embedding is disabled.
if (event.data === 150 || event.data === 101 || event.data === 153) {
// Show an overlay with an external link instead of a broken player
this.showErrorOverlay(this.currentVideoId, "This video cannot be embedded. Please watch it on YouTube.");
}
}
The core state is initialized and saved on every successful search, ensuring the user returns to the same search context:
// Initialization on load
const savedKey = localStorage.getItem('youtubeApiKey');
// ... other state loading ...
// Saving state after a successful search
const saveState = () => {
localStorage.setItem('lastQuery', searchInput.value);
localStorage.setItem('sortOrder', sortSelect.value);
// ... other state saving ...
if (rememberKeyToggle.checked) {
localStorage.setItem('youtubeApiKey', apiKeyInput.value);
} else {
localStorage.removeItem('youtubeApiKey');
}
};