Compare commits

...

7 Commits

Author SHA1 Message Date
9d2b6c4748 small fix 2025-12-06 21:03:13 -06:00
63026da874 mote space 2025-12-06 21:00:26 -06:00
86f3dc9cfb readme added 2025-12-06 20:59:08 -06:00
9bcfb91408 working 2025-12-06 20:54:53 -06:00
1b9e7d64b0 removed music 2025-12-06 19:30:16 -06:00
b83fbe9055 e 2025-12-06 19:28:58 -06:00
5534bdf42a Ignore music folder 2025-12-06 19:28:29 -06:00
31 changed files with 279 additions and 12 deletions

2
.gitignore vendored
View File

@@ -36,6 +36,8 @@ build/
# VS Code
.vscode/
/backend/music/
# Temporary files
*.tmp
*.swp

221
README.md Normal file
View File

@@ -0,0 +1,221 @@
# Music Portfolio
This project hosts a music portfolio with a **Node.js backend** serving music files and a **React frontend** displaying tracks. This guide explains how to run everything locally, convert music files to MP3, transfer files to your server, and set up the server with Nginx and SSL.
---
## Table of Contents
1. [Prerequisites](#prerequisites)
2. [Local Setup](#local-setup)
3. [Convert Music to MP3](#convert-music-to-mp3)
4. [Deploy to Server](#deploy-to-server)
5. [Server Setup](#server-setup)
6. [Nginx Configuration](#nginx-configuration)
---
## Prerequisites
* Node.js (v18+ recommended)
* npm / yarn
* Python3 + pip
* `pydub` Python library (for conversion)
* `ffmpeg` installed on both local and server machines
Install Python dependencies:
```bash
pip install pydub
```
Install Node dependencies in backend and frontend:
```bash
cd backend
npm install
cd ../frontend
npm install
npm run build
```
---
## Local Setup
### Backend
```bash
cd backend
node server.js
```
By default, the backend runs at:
```
http://localhost:3001
```
### Frontend
```bash
cd frontend
npm start
```
By default, the frontend runs at:
```
http://localhost:3000
```
---
## Convert Music to MP3
All music files must be in the `backend/music` folder. The project includes a Python script:
```bash
cd backend
python3 convert-to-mp3.py
```
This will:
* Convert `.flac`, `.wav`, `.m4a`, `.ogg` files to `.mp3`
* Delete the original files
* Keep the same filename but with `.mp3` extension
---
## Deploy to Server
### Copy Backend & Music Files
```bash
# Replace <user> and <server-ip> with your server details
scp -r backend/* <user>@<server-ip>:/var/www/musicportfolio.keshavanand.net/backend/
```
### Copy Frontend Build
```bash
scp -r frontend/* <user>@<server-ip>:/var/www/musicportfolio.keshavanand.net/frontend/
```
---
## Server Setup
### 1. Backend as a systemd service
Create `/etc/systemd/system/music-portfolio-backend.service`:
```ini
[Unit]
Description=Music Portfolio Backend
After=network.target
[Service]
User=www-data
WorkingDirectory=/var/www/musicportfolio.keshavanand.net/backend
ExecStart=/usr/bin/node server.js
Restart=always
Environment=PORT=3001
[Install]
WantedBy=multi-user.target
```
Enable and start:
```bash
sudo systemctl daemon-reload
sudo systemctl enable music-portfolio-backend
sudo systemctl start music-portfolio-backend
sudo systemctl status music-portfolio-backend
```
---
### 2. Nginx Configuration
Create `/etc/nginx/sites-available/musicportfolio.keshavanand.net`:
```nginx
server {
server_name musicportfolio.keshavanand.net www.musicportfolio.keshavanand.net;
root /var/www/musicportfolio.keshavanand.net/frontend/dist;
index index.html;
location / {
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /music/ {
alias /var/www/musicportfolio.keshavanand.net/backend/music/;
autoindex off;
types {
audio/mpeg mp3;
audio/wav wav;
}
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/musicportfolio.keshavanand.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/musicportfolio.keshavanand.net/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
listen 80;
server_name musicportfolio.keshavanand.net www.musicportfolio.keshavanand.net;
return 301 https://$host$request_uri;
}
```
Enable site and reload:
```bash
sudo ln -s /etc/nginx/sites-available/musicportfolio.keshavanand.net /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
---
### 3. SSL with Certbot
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d musicportfolio.keshavanand.net -d www.musicportfolio.keshavanand.net
```
---
### 4. Permissions
Ensure the backend can read/write files:
```bash
sudo chown -R www-data:www-data /var/www/musicportfolio.keshavanand.net
```
---
## Notes
* Make sure the backend is running before loading the frontend.
* Frontend calls `/api/tracks` to fetch metadata.
* All music files must be in `.mp3` format for consistent browser support.
* Clear browser cache if changes arent reflected immediately.

43
backend/convert-to-mp3.py Normal file
View File

@@ -0,0 +1,43 @@
# convert_to_mp3.py
import os
from pydub import AudioSegment
# Directory relative to this script
MUSIC_DIR = os.path.join(os.path.dirname(__file__), "music")
# Supported input formats
INPUT_FORMATS = [".flac", ".wav", ".m4a", ".ogg"]
def convert_to_mp3(file_path):
file_root, ext = os.path.splitext(file_path)
ext = ext.lower()
if ext not in INPUT_FORMATS:
return # skip unsupported formats
mp3_path = f"{file_root}.mp3"
print(f"Converting {file_path}{mp3_path}")
# Load audio
audio = AudioSegment.from_file(file_path)
# Export as MP3
audio.export(mp3_path, format="mp3", bitrate="320k")
# Delete original file
os.remove(file_path)
print(f"Deleted original: {file_path}")
def main():
for root, _, files in os.walk(MUSIC_DIR):
for file in files:
full_path = os.path.join(root, file)
convert_to_mp3(full_path)
if __name__ == "__main__":
main()

View File

@@ -1,6 +1,7 @@
{
"name": "music-backend",
"version": "1.0.0",
"type": "module",
"main": "server.js",
"scripts": {
"start": "node server.js",

View File

@@ -1,9 +1,8 @@
// server.js
const express = require('express');
const path = require('path');
const fs = require('fs/promises');
const mm = require('music-metadata');
const cors = require('cors');
import express from 'express';
import path from 'path';
import fs from 'fs/promises';
import * as mm from 'music-metadata';
import cors from 'cors';
const app = express();
app.use(cors()); // adjust for production if needed

View File

@@ -8,13 +8,13 @@ export default function App() {
// Hard-coded featured tracks (filenames only)
const FEATURED = [
"Kanne Kalimaane__Moondram Pirai__Unplucked Instrumental Studio Music Cover__2025-06-26.flac",
"Pudhu Vellai Mazhai__Roja__Unplucked Instrumental Studio Music Cover__2025-03-15.flac",
"Porkalam and Kannana Kanney Medley__Thenali and Viswasam__Unplucked Instrumental Studio Music Cover__2025-01-01.flac"
"Kanne Kalimaane__Moondram Pirai__Unplucked Instrumental Studio Music Cover__2025-06-26.mp3",
"Pudhu Vellai Mazhai__Roja__Unplucked Instrumental Studio Music Cover__2025-03-15.mp3",
"Porkalam and Kannana Kanney Medley__Thenali and Viswasam__Unplucked Instrumental Studio Music Cover__2025-01-01.mp3"
];
useEffect(() => {
axios.get("http://localhost:3001/api/tracks").then(res => {
axios.get('/api/tracks').then(res => {
setAllTracks(res.data.tracks);
});
}, []);
@@ -66,8 +66,8 @@ export default function App() {
<div>
<header>
<h1>Keshavs Music Portfolio</h1>
<p style={{ marginTop: "20px", marginBottom: "20px" }}>
</p>
<p style={{ marginTop: "20px", marginBottom: "20px" }}> </p>
</header>
<main>
@@ -75,6 +75,7 @@ export default function App() {
{featuredTracks.length > 0 && (
<section>
<h2>Featured</h2>
<p style={{ marginTop: "20px", marginBottom: "20px" }}> </p>
<div className="featured-container">
{featuredTracks.map(t => (
<TrackCard key={t.url} t={t} featured={true} />