A robust backend REST API built using Node.js, Express, and MongoDB that powers a Spotify clone. It supports user registration, role-based authorization (Users & Artists), file uploads (via Multer and ImageKit), and album creation.
Backend/
βββ node_modules/ # Node.js dependencies
βββ src/
β βββ controllers/ # Request controllers (auth, music)
β βββ db/ # Database connection logic
β βββ middleware/ # Custom authentication/role middlewares
β βββ models/ # Mongoose schemas (user, music, album)
β βββ routes/ # API routes definition
β βββ services/ # External integrations (storage service)
β βββ app.js # Express app setup and middleware configuration
βββ .env # Environment variables (local-only)
βββ package.json # Project manifest & dependencies
βββ server.js # Entry point of the server
βββ README.md # API Documentation
Ensure you are in the Backend directory:
cd spotify/Backendnpm installCreate a .env file in the root of the Backend directory and populate it with your credentials:
PORT=3000
MONGODB_URI=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret_key
IMAGEKIT_PUBLIC_KEY="your_imagekit_public_key"
IMAGEKIT_PRIVATE_KEY="your_imagekit_private_key"
IMAGEKIT_URL_ENDPOINT="https://ik.imagekit.io/your_endpoint_id"- Development mode (with nodemon):
npm run dev
- Production mode:
npm start
username: String (Required, Unique)email: String (Required, Unique)password: String (Required, Hashed)role: String (Enum:["user", "artist"], Default:"user")
uri: String (Required) - CDN URL pointing to the uploaded audio filetitle: String (Required) - Track titleartist: ObjectId (Required) - Reference toUser(must be an artist)
title: String (Required) - Album titlemusics: Array of ObjectIds - References toMusictracksartist: ObjectId (Required) - Reference toUser(must be an artist)
All secure endpoints check for a valid JSON Web Token (JWT) in two locations:
- HTTP-only Cookie: Named
token. - Authorization Header: Bearer token (
Bearer <JWT>).
authUser: Checks if the token is valid and if the role is either"user"or"artist".authArtist: Checks if the token is valid and if the role is"artist"(or"admin"if applicable).
Registers a new account. Setting "role": "artist" allows the user to upload music and create albums.
- Method & Path:
POST /api/auth/register - Request Body (JSON):
(Note:
{ "username": "johndoe", "email": "johndoe@example.com", "password": "securepassword", "role": "artist" }roledefaults to"user"if not specified) - Responses:
201 Created: Returns user details and setstokenin an HTTP-only cookie.{ "user": { "_id": "603d7b42f63e411bf88f34bc", "username": "johndoe", "email": "johndoe@example.com", "role": "artist" } }400 Bad Request: User or email already exists.{ "error": "User already exists" }
Logs in an existing user or artist.
- Method & Path:
POST /api/auth/login - Request Body (JSON):
(Can also login with
{ "email": "johndoe@example.com", "password": "securepassword" }"username"instead of"email") - Responses:
200 OK: Returns user details and setstokenin an HTTP-only cookie (expiring in 1 hour).{ "user": { "_id": "603d7b42f63e411bf88f34bc", "username": "johndoe", "email": "johndoe@example.com", "role": "artist" } }404 Not Found: User not found.{ "error": "User not found" }401 Unauthorized: Password is incorrect.{ "error": "Invalid password" }
Logs out the current session by clearing the token cookie.
- Method & Path:
POST /api/auth/logout - Responses:
200 OK: Clears the cookie.{ "message": "User logged out successfully" }
Retrieves info about the currently logged-in user.
- Method & Path:
GET /api/auth/profile - Headers:
Cookie: token=<token>orAuthorization: Bearer <token> - Responses:
200 OK:{ "user": { "_id": "603d7b42f63e411bf88f34bc", "username": "johndoe", "email": "johndoe@example.com", "role": "artist", "__v": 0 } }401 Unauthorized: No token provided or token invalid.{ "message": "Unauthorized: No token provided" }
Uploads a track to ImageKit and registers the music track in the database.
- Role required:
artist - Method & Path:
POST /api/music/upload - Headers:
Cookie: token=<token>orAuthorization: Bearer <token> - Request Body (Multipart Form-Data):
title: String (Required) - e.g.,"Stairway to Heaven"music: File (Required) - The audio file binary
- Responses:
201 Created:{ "message": "Music created successfully", "music": { "id": "603d7e5af63e411bf88f34bd", "title": "Stairway to Heaven", "artist": "603d7b42f63e411bf88f34bc", "uri": "https://ik.imagekit.io/p3c8xt7ms/music/music_1614618202568.mp3", "image": "https://ik.imagekit.io/p3c8xt7ms/music/music_1614618202568.mp3" } }400 Bad Request: Missing title or missing music file.{ "error": "Music file is required under field name 'music'" }403 Forbidden: Logged-in user is not an artist.{ "message": "Unauthorized: Not an artist" }
Creates an album containing multiple music tracks.
- Role required:
artist - Method & Path:
POST /api/music/album - Headers:
Cookie: token=<token>orAuthorization: Bearer <token> - Request Body (JSON):
{ "title": "Classic Rock Hits", "musics": [ "603d7e5af63e411bf88f34bd", "603d7e6cf63e411bf88f34be" ] } - Responses:
201 Created:{ "message": "Album created successfully", "album": { "id": "603d7eb8f63e411bf88f34bf", "title": "Classic Rock Hits", "artist": "603d7b42f63e411bf88f34bc", "musics": [ "603d7e5af63e411bf88f34bd", "603d7e6cf63e411bf88f34be" ] } }400 Bad Request: Missing title or musics array empty.{ "error": "Musics is required" }
Fetches all uploaded tracks with artist details populated.
- Role required:
userorartist - Method & Path:
GET /api/music/ - Headers:
Cookie: token=<token>orAuthorization: Bearer <token> - Responses:
200 OK:{ "message": "Musics fetched successfully", "musics": [ { "_id": "603d7e5af63e411bf88f34bd", "uri": "https://ik.imagekit.io/p3c8xt7ms/music/music_1614618202568.mp3", "title": "Stairway to Heaven", "artist": { "_id": "603d7b42f63e411bf88f34bc", "username": "johndoe", "email": "johndoe@example.com" }, "__v": 0 } ] }
Fetches all albums (populated with general artist info).
- Role required:
userorartist - Method & Path:
GET /api/music/album - Headers:
Cookie: token=<token>orAuthorization: Bearer <token> - Responses:
200 OK:{ "message": "Albums fetched successfully", "albums": [ { "_id": "603d7eb8f63e411bf88f34bf", "title": "Classic Rock Hits", "artist": { "_id": "603d7b42f63e411bf88f34bc", "username": "johndoe", "email": "johndoe@example.com" } } ] }
Retrieves details of a single album, fully populating both the artist info and all nested tracks.
- Role required:
userorartist - Method & Path:
GET /api/music/album/:albumId - Headers:
Cookie: token=<token>orAuthorization: Bearer <token> - Responses:
200 OK:{ "message": "Album fetched successfully", "album": { "_id": "603d7eb8f63e411bf88f34bf", "title": "Classic Rock Hits", "artist": { "_id": "603d7b42f63e411bf88f34bc", "username": "johndoe", "email": "johndoe@example.com" }, "musics": [ { "_id": "603d7e5af63e411bf88f34bd", "uri": "https://ik.imagekit.io/p3c8xt7ms/music/music_1614618202568.mp3", "title": "Stairway to Heaven", "artist": "603d7b42f63e411bf88f34bc", "__v": 0 } ], "__v": 0 } }404 Not Found: Album not found.{ "error": "Album not found" }