This guide covers creating a comprehensive music catalog database with the following features:
Field | Type | Description |
---|---|---|
Album ID | Auto-generated | Unique identifier |
Album Name | Text/Title | Primary album title |
Album Type | Select | LP, EP, Single, etc. |
Album Duration | Duration/Text | Total runtime |
UPC Number | Text | Universal Product Code |
Release Date | Date | Release date |
Total Tracks | Number | Track count |
Album Cover | File/URL | Cover artwork |
Field | Type | Description |
---|---|---|
Track ID | Auto-generated | Unique identifier |
Album Name | Relation/Text | Links to album |
Track Number | Number | Order in album |
Track Name | Text/Title | Song title |
ISRC Number | Text | International Standard Recording Code |
Track Duration | Duration/Text | Track length |
Genre | Multi-select | Musical genres |
Featured Artists | Multi-select | Guest artists |
Apple Music | URL | Streaming link |
Spotify | URL | Streaming link |
YouTube Music | URL | Streaming link |
Amazon Music | URL | Streaming link |
Tidal | URL | Streaming link |
iTunes | URL | Purchase link |
Stream URL | URL | Direct audio file |
Database Name: 🎵 Music Albums Catalog
Properties:
- Album Name (Title)
- Album Type (Select: LP, EP, Single, Compilation, Mixtape)
- Album Duration (Text)
- UPC Number (Text)
- Release Date (Date)
- Album Cover (Files)
- Total Tracks (Number)
Database Name: 🎶 Music Tracks Catalog
Properties:
- Track Name (Title)
- Album Name (Text)
- Track Number (Number)
- ISRC Number (Text)
- Track Duration (Text)
- Genre (Multi-select)
- Featured Artists (Multi-select)
- [All streaming platform URLs]
- Stream URL (URL)
Album Grid View
Track List View
Recent Releases View
<iframe src="YOUR_NOTION_PUBLIC_URL"
width="100%"
height="600"
style="border: none;">
</iframe>
// Notion API Setup
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_KEY });
// Fetch albums
const response = await notion.databases.query({
database_id: 'YOUR_DATABASE_ID',
sorts: [{ property: 'Release Date', direction: 'descending' }]
});
A1: Album ID | B1: Album Name | C1: Album Type | D1: Album Duration
E1: UPC Number | F1: Release Date | G1: Total Tracks | H1: Album Cover URL
A1: Track ID | B1: Album Name | C1: Track Number | D1: Track Name
E1: ISRC Number | F1: Track Duration | G1: Genre | H1: Featured Artists
I1: Apple Music | J1: Spotify | K1: YouTube Music | L1: Amazon Music
M1: Tidal | N1: iTunes | O1: Stream URL
Column C (Album Type):
- Data → Data validation
- Criteria: List of items
- Items: LP,EP,Single,Compilation,Mixtape
Column B (Album Name):
- Data → Data validation
- Criteria: List from range
- Range: Albums!B2:B1000
Column G (Genre):
- Data → Data validation
- Criteria: List of items
- Items: Pop,Rock,Hip-Hop,Electronic,R&B,Jazz,Classical
// Album ID (Column A)
=IF(B2<>"", "ALB-"&TEXT(ROW()-1, "000"), "")
// Track ID (Column A)
=IF(D2<>"", "TRK-"&TEXT(ROW()-1, "0000"), "")
// In Albums sheet, Column G
=IF(B2<>"", COUNTIF(Tracks!B:B, B2), "")
// In Albums sheet, Column D
=IF(B2<>"", SUMIF(Tracks!B:B, B2, Tracks!F:F), "")
<!-- Embed full spreadsheet -->
<iframe
src="https://docs.google.com/spreadsheets/d/e/YOUR_SHEET_ID/pubhtml?widget=true&headers=false"
width="100%"
height="600">
</iframe>
<!-- Embed specific sheet -->
<iframe
src="https://docs.google.com/spreadsheets/d/e/YOUR_SHEET_ID/pubhtml?gid=0&single=true&widget=true&headers=false"
width="100%"
height="600">
</iframe>
Code.gs:
function doGet() {
return HtmlService.createTemplateFromFile('index')
.evaluate()
.setTitle('Music Catalog')
.addMetaTag('viewport', 'width=device-width, initial-scale=1');
}
function getAlbums() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Albums');
const data = sheet.getDataRange().getValues();
const headers = data.shift();
return data.map(row => {
const album = {};
headers.forEach((header, index) => {
album[header] = row[index];
});
return album;
});
}
function getTracks() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Tracks');
const data = sheet.getDataRange().getValues();
const headers = data.shift();
return data.map(row => {
const track = {};
headers.forEach((header, index) => {
track[header] = row[index];
});
return track;
});
}
// Using Google Sheets API v4
const SHEET_ID = 'YOUR_SHEET_ID';
const API_KEY = 'YOUR_API_KEY';
const ALBUMS_RANGE = 'Albums!A1:H100';
const TRACKS_RANGE = 'Tracks!A1:O500';
async function fetchSheetData(range) {
const url = `https://sheets.googleapis.com/v4/spreadsheets/${SHEET_ID}/values/${range}?key=${API_KEY}`;
const response = await fetch(url);
const data = await response.json();
return data.values;
}
// Fetch albums
const albumsData = await fetchSheetData(ALBUMS_RANGE);
// Fetch tracks
const tracksData = await fetchSheetData(TRACKS_RANGE);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Music Catalog</title>
<style>
/* Responsive grid layout */
.albums-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.album-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
transition: transform 0.3s;
}
.album-card:hover {
transform: translateY(-5px);
}
/* Add more styles as needed */
</style>
</head>
<body>
<div id="app">
<!-- Dynamic content loads here -->
</div>
<script>
// Your API integration code here
</script>
</body>
</html>
// Shortcode for WordPress
function music_catalog_shortcode() {
ob_start();
?>
<div id="music-catalog">
<iframe src="YOUR_EMBED_URL" width="100%" height="800"></iframe>
</div>
<?php
return ob_get_clean();
}
add_shortcode('music_catalog', 'music_catalog_shortcode');
import React, { useState, useEffect } from 'react';
const MusicCatalog = () => {
const [albums, setAlbums] = useState([]);
const [tracks, setTracks] = useState([]);
const [view, setView] = useState('albums');
useEffect(() => {
// Fetch data from your API
fetchMusicData();
}, []);
return (
<div className="music-catalog">
<div className="controls">
<button onClick={() => setView('albums')}>Albums</button>
<button onClick={() => setView('tracks')}>Tracks</button>
</div>
{view === 'albums' ? (
<AlbumsGrid albums={albums} />
) : (
<TracksList tracks={tracks} />
)}
</div>
);
};
Create Integration
Connect to Databases
API Configuration
const NOTION_API_KEY = 'YOUR_INTEGRATION_TOKEN';
const ALBUMS_DB_ID = 'YOUR_ALBUMS_DATABASE_ID';
const TRACKS_DB_ID = 'YOUR_TRACKS_DATABASE_ID';
Enable API
Create Credentials
Make Sheet Public
<audio controls>
<source src="YOUR_AUDIO_URL" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
www.dropbox.com
with dl.dropboxusercontent.com
Feature | Notion | Google Sheets |
---|---|---|
Cost | Free up to 1000 blocks | Completely free |
Learning Curve | Moderate | Easy |
API Access | Yes (with limits) | Yes (generous limits) |
Mobile App | Excellent | Good |
Collaboration | Good | Excellent |
Custom Views | Excellent | Limited |
Embedding | Good | Excellent |
Formulas | Basic | Advanced |
File Storage | Built-in | Via Google Drive |
Design Flexibility | High | Low |
Choose Notion if you want:
Choose Google Sheets if you want:
Data Entry
Organization
Performance
Security