This commit introduces pagination and real-time updates to the music site, improving performance and user experience for browsing tracks across genres. Key changes include: music_site.js: Added Socket.IO for real-time communication between client and server. Implemented pagination with TRACKS_PER_PAGE (4 tracks per page) in getTracks function, returning paginated tracks, current page, total pages, and total tracks. Enhanced slug generation with usedSlugs Map to ensure uniqueness within genres. Updated routes and WebSocket handlers to support pagination: Modified getTracks to handle page parameters and return paginated data. Added io.on('connection') to handle request_page events and emit page_data or error. Updated / and /sitemap.xml to work with paginated track data. Adjusted track retrieval in /:genre/track/:slug and /json/:genre to use allTracks for consistency. index.ejs: Added pagination controls (Previous/Next buttons) for each genre section, displaying current page and total pages. Introduced page-container divs to manage paginated track displays, with active class for the current page. Implemented client-side WebSocket logic with Socket.IO to request and render new pages dynamically. Added page caching (pageCache) to store rendered pages and reduce server requests. Enhanced lazy loading of iframes to apply to dynamically loaded pages. Updated styling for page-container and iframes to ensure proper layout and responsiveness. These changes enable users to navigate through tracks efficiently without loading all tracks at once, reduce server load, and provide a smoother browsing experience with real-time updates.
Raven Scott Music
Raven Scott Music is a sophisticated, dark-themed web application designed to curate and display music playlists from SoundCloud across three genres: Metal, Alt Rock, and Rap. Built with Node.js, Express, and EJS, this project combines server-side rendering, efficient caching, and a responsive front-end to deliver a seamless music discovery experience. Whether you're a developer looking to explore the code or a music enthusiast browsing tracks, this app offers a robust foundation with plenty of room for customization.
Table of Contents
- Features
- Live Demo
- Prerequisites
- Installation
- Usage
- Technical Overview
- File Structure
- Tech Stack Rationale
- Configuration
- Deployment
- Development
- Troubleshooting
- License
- Acknowledgments
Features
- Genre-Specific Playlists: Dynamically fetches and displays tracks from SoundCloud playlists for Metal, Alt Rock, and Rap.
- Efficient Caching: Stores playlist data in local JSON files, refreshing only after a week to minimize API calls and improve load times.
- Responsive UI: Leverages Bootstrap 4.5.2 and custom CSS for a mobile-friendly, dark-mode interface with orange accents.
- Track Pages: Dedicated pages for each track with embedded SoundCloud players, titles, and descriptions.
- SEO Optimization: Generates a
sitemap.xml
dynamically for better search engine visibility. - JSON API: Provides a RESTful endpoint (
/json/:genre
) for programmatic access to track data. - Custom Styling: Features a slim dark-mode scrollbar, animated navbar hover effects, and a cohesive aesthetic tailored for music lovers.
- Sorting Logic: Tracks are sorted by play count (descending) and then by publication date (newest first) for a curated experience.
Live Demo
Explore the live site at raven-scott.rocks. Check out the Metal, Alt Rock, and Rap sections, dive into individual track pages, or inspect the sitemap at /sitemap.xml
.
Prerequisites
To run this project locally, ensure you have:
- Node.js: Version 14.x or higher (includes npm).
- npm: Package manager for installing dependencies.
- SoundCloud Access: The playlists specified in
music_site.js
must be public and accessible via thesoundcloud-scraper
library. - Git: For cloning the repository (optional but recommended).
Installation
-
Clone the Repository:
git clone https://git.ssh.surf/snxraven/ravenscott-rocks.git cd ravenscott-rocks
-
Install Dependencies:
npm install
This installs
express
,soundcloud-scraper
,ejs
, and other required packages listed inpackage.json
. -
Optional: Environment Variables:
- Create a
.env
file in the root directory to customize the port:PORT=6767
- Alternatively, set the
PORT
variable in your terminal:export PORT=6767 # Linux/macOS set PORT=6767 # Windows
- Create a
-
Start the Server:
node music_site.js
The app will run on
http://localhost:6767
(or your specified port). Open this URL in your browser to begin exploring.
Usage
- Home Page (
/
): Displays all genre playlists with embedded SoundCloud players and "More Details" links. - Genre Navigation (
/#genre
): Use the navbar to jump to specific genres (e.g.,#metal
,#altrock
,#rap
). - Track Details (
/:genre/track/:slug
): Click "More Details" to view a track’s page with its SoundCloud player and description. - JSON API (
/json/:genre
): Fetch raw track data for a genre (e.g.,http://localhost:6767/json/metal
) in JSON format. - Sitemap (
/sitemap.xml
): Access a dynamically generated sitemap for SEO purposes.
Example API response:
[
{
"title": "Heavy Riffs",
"description": "A brutal metal track.",
"url": "https://soundcloud.com/snxraven/heavy-riffs",
"playCount": 1200,
"publishedAt": "2023-05-10T12:00:00Z",
"slug": "heavy-riffs"
}
]
Technical Overview
Backend
- Framework: Uses Express.js to handle routing, static file serving, and API endpoints.
- SoundCloud Integration: The
soundcloud-scraper
library fetches playlist data, including track titles, URLs, play counts, and publication dates. - Routing:
/
: Renders the home page with all genres./:genre
: Redirects to the home page’s genre section (e.g.,/#metal
)./:genre/track/:slug
: Renders individual track pages./json/:genre
: Returns track data in JSON./sitemap.xml
: Generates an XML sitemap.
- Slug Generation: Converts track titles into URL-friendly slugs (e.g., "Heavy Riffs" →
heavy-riffs
).
Frontend
- Templating: EJS renders dynamic HTML with data from the backend.
- Styling:
- Bootstrap 4.5.2 (via CDN) provides the grid system and card components.
- Custom CSS adds a dark theme, orange buttons, a fixed navbar with hover animations, and a slim scrollbar.
- Scripts: jQuery, Popper.js, and Bootstrap JS (via CDN) enable navbar toggling and other interactive elements.
Caching Mechanism
- Purpose: Reduces API calls to SoundCloud by storing playlist data locally.
- Implementation:
- Cache files (
cache_metal.json
, etc.) store tracks and a timestamp. - The
getTracks
function checks if the cache is older than 1 week (configurable viaoneWeekInMs
). - If outdated or missing, it fetches fresh data and updates the cache.
- Cache files (
- Sorting: Tracks are sorted by play count (highest first) and then by publication date (newest first).
File Structure
raven-scott-music/
├── public/ # Static assets
│ └── css/ # Custom CSS (currently empty; styles are inline in EJS)
├── views/ # EJS templates
│ ├── index.ejs # Home page with genre sections
│ ├── layout.ejs # Base layout (not fully utilized in this setup)
│ └── track.ejs # Individual track page
├── cache_metal.json # Cached Metal tracks (auto-generated)
├── cache_altrock.json # Cached Alt Rock tracks (auto-generated)
├── cache_rap.json # Cached Rap tracks (auto-generated)
├── music_site.js # Core server logic and routing
├── package.json # Project metadata and dependencies
├── package-lock.json # Dependency lock file
└── README.md # This documentation
Tech Stack Rationale
- Node.js & Express: Lightweight and fast for building a server-side application with minimal overhead.
- soundcloud-scraper: Chosen for its simplicity and ability to scrape public playlist data without requiring an official API key.
- EJS: Offers server-side rendering with easy integration into Express, ideal for dynamic content like playlists.
- Bootstrap: Speeds up development with pre-built components and ensures responsiveness out of the box.
- File-System Caching: A simple, effective solution for persistence without the complexity of a database.
Configuration
- Playlists: Modify the
playlists
object inmusic_site.js
:const playlists = { metal: { url: 'https://soundcloud.com/snxraven/sets/raven-scott-metal', ... }, // Add new genres here };
- Cache Refresh: Adjust
oneWeekInMs
(in milliseconds) ingetTracks
:const oneWeekInMs = 7 * 24 * 60 * 60 * 1000; // Change to 24 * 60 * 60 * 1000 for daily refresh
- Port: Set via
.env
or directly inmusic_site.js
:const PORT = process.env.PORT || 6767;
Development
Getting Started
- Fork and clone the repo.
- Install dependencies (
npm install
). - Run locally (
node music_site.js
). - Make changes and test in your browser.
Enhancement Ideas
- Database Integration: Replace file caching with MongoDB or SQLite for scalability.
- Search Functionality: Add a search bar to filter tracks by title or description.
- User Accounts: Implement authentication (e.g., with Passport.js) for favoriting tracks.
- Additional Platforms: Integrate Spotify or YouTube using their APIs.
- Analytics: Track page views or play counts with a tool like Google Analytics.
- Lazy Loading: Optimize the home page by loading tracks incrementally.
Troubleshooting
- SoundCloud Fetch Fails:
- Verify playlist URLs in
music_site.js
are correct and public. - Update
soundcloud-scraper
(npm install soundcloud-scraper@latest
).
- Verify playlist URLs in
- Cache Issues:
- Delete
cache_*.json
files and restart the server to force a refresh. - Check file permissions if cache files aren’t being written.
- Delete
- Port Conflicts:
- Change the
PORT
value or kill the conflicting process:lsof -i :6767 # Linux/macOS kill -9 <PID>
- Change the
- 404 Errors:
- Ensure genre or slug matches the data (case-sensitive).
- Check console logs for errors during playlist fetching.
- Styling Problems:
- Clear browser cache if CSS changes don’t appear.
- Verify CDN links for Bootstrap and jQuery are accessible.