-
+
+
+
diff --git a/app/store/dataStore.ts b/app/store/dataStore.ts
new file mode 100644
index 0000000..d6a0108
--- /dev/null
+++ b/app/store/dataStore.ts
@@ -0,0 +1,51 @@
+import type { Compilation, Artist, Track } from '~/../types/types'
+
+// stores/data.ts
+import { defineStore } from 'pinia'
+
+export const useDataStore = defineStore('data', {
+ state: () => ({
+ compilations: [] as Compilation[], // Store your compilation data here
+ artists: [] as Artist[], // Store artist data here
+ tracks: [] as Track[], // Store track data here
+ isLoaded: false, // Remember if data is already loaded
+ }),
+
+ actions: {
+ async loadData() {
+ if (this.isLoaded) return // Avoid re-fetching if already loaded
+
+ // Fetch your data once (e.g., from an API or local JSON)
+ const { data: compilations } = await useFetch('/api/compilations')
+ const { data: artists } = await useFetch('/api/artists')
+ const { data: tracks } = await useFetch('/api/tracks')
+
+ // Set the data in the store
+ this.compilations = compilations.value
+ this.artists = artists.value
+ this.tracks = tracks.value
+ this.isLoaded = true
+ }
+ },
+
+ getters: {
+ // Obtenir tous les compilations
+ getAllCompilations: (state) => state.compilations,
+ getCompilationById: (state) => {
+ return (id: string) => {
+ return state.compilations.find(compilation => compilation.id === id)
+ }
+ },
+ // Obtenir toutes les pistes d'une compilation donnée
+ getTracksByCompilationId: (state) => (compilationId: string) => {
+ return state.tracks.filter(track => track.compilationId === compilationId)
+ },
+ // Filtrer les artistes selon certains critères
+ getArtistById: (state) => (id: number) => state.artists.find(artist => artist.id === id),
+
+ // Obtenir toutes les pistes d'un artiste donné
+ getTracksByArtistId: (state) => (artistId: string) => {
+ return state.tracks.filter(track => track.artistId === artistId)
+ },
+ },
+})
diff --git a/app/utils/cssVars.js b/app/utils/cssVars.js
new file mode 100644
index 0000000..771f110
--- /dev/null
+++ b/app/utils/cssVars.js
@@ -0,0 +1,6 @@
+// utils/cssVars.js
+export function updateCssVar(name, value, el) {
+ // if (!import.meta.client) return;
+ const target = el?.$el || el || document.documentElement;
+ target.style.setProperty(name, value);
+}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 934c3a1..f0f16dd 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,6 +1,21 @@
// @ts-check
-import withNuxt from './.nuxt/eslint.config.mjs'
+import withNuxt from "./.nuxt/eslint.config.mjs";
-export default withNuxt(
- // Your custom configs here
-)
+export default withNuxt({
+ rules: {
+ // Garde l'ordre correct : class avant @click
+ "vue/attributes-order": "error",
+
+ // Contrôle du nombre d'attributs par ligne
+ "vue/max-attributes-per-line": [
+ "error",
+ {
+ singleline: 3, // autorise jusqu’à 3 attributs sur une ligne
+ multiline: {
+ max: 1, // si retour à la ligne, 1 attr par ligne
+ allowFirstLine: false,
+ },
+ },
+ ],
+ },
+});
diff --git a/nuxt.config.ts b/nuxt.config.ts
index e2f7854..6c69276 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -2,7 +2,7 @@
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
- modules: ['@nuxt/eslint', '@nuxtjs/tailwindcss'],
+ modules: ['@nuxt/eslint', '@nuxtjs/tailwindcss', '@pinia/nuxt'],
app: {
head: {
link: [
diff --git a/package.json b/package.json
index 4644e67..f2196ad 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"build": "nuxt build",
- "dev": "nuxt dev",
+ "dev": "nuxt dev --host",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
@@ -12,11 +12,13 @@
"dependencies": {
"@nuxt/eslint": "1.9.0",
"@nuxtjs/tailwindcss": "6.14.0",
+ "@pinia/nuxt": "0.11.2",
+ "atropos": "^2.0.2",
"eslint": "^9.33.0",
"nuxt": "^4.0.3",
+ "pinia": "^3.0.3",
"vue": "^3.5.18",
- "vue-router": "^4.5.1",
- "atropos": "^2.0.2"
+ "vue-router": "^4.5.1"
},
"engines": {
"pnpm": ">=10 <11"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 799984d..e7d4e94 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,6 +14,9 @@ importers:
'@nuxtjs/tailwindcss':
specifier: 6.14.0
version: 6.14.0(magicast@0.3.5)
+ '@pinia/nuxt':
+ specifier: 0.11.2
+ version: 0.11.2(magicast@0.3.5)(pinia@3.0.3(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)))
atropos:
specifier: ^2.0.2
version: 2.0.2
@@ -23,6 +26,9 @@ importers:
nuxt:
specifier: ^4.0.3
version: 4.0.3(@netlify/blobs@9.1.2)(@parcel/watcher@2.5.1)(@types/node@24.3.0)(@vue/compiler-sfc@3.5.18)(db0@0.3.2)(eslint@9.33.0(jiti@2.5.1))(ioredis@5.7.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.46.3)(terser@5.43.1)(typescript@5.9.2)(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(terser@5.43.1)(yaml@2.8.1))(yaml@2.8.1)
+ pinia:
+ specifier: ^3.0.3
+ version: 3.0.3(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
vue:
specifier: ^3.5.18
version: 3.5.18(typescript@5.9.2)
@@ -1142,6 +1148,11 @@ packages:
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
engines: {node: '>= 10.0.0'}
+ '@pinia/nuxt@0.11.2':
+ resolution: {integrity: sha512-CgvSWpbktxxWBV7ModhAcsExsQZqpPq6vMYEe9DexmmY6959ev8ukL4iFhr/qov2Nb9cQAWd7niFDnaWkN+FHg==}
+ peerDependencies:
+ pinia: ^3.0.3
+
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -1608,6 +1619,9 @@ packages:
'@vue/devtools-api@6.6.4':
resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
+ '@vue/devtools-api@7.7.7':
+ resolution: {integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==}
+
'@vue/devtools-core@7.7.7':
resolution: {integrity: sha512-9z9TLbfC+AjAi1PQyWX+OErjIaJmdFlbDHcD+cAMYKY6Bh5VlsAtCeGyRMrXwIlMEQPukvnWt3gZBLwTAIMKzQ==}
peerDependencies:
@@ -3690,6 +3704,15 @@ packages:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
+ pinia@3.0.3:
+ resolution: {integrity: sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==}
+ peerDependencies:
+ typescript: '>=4.4.4'
+ vue: ^2.7.0 || ^3.5.11
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
pirates@4.0.7:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
engines: {node: '>= 6'}
@@ -6106,6 +6129,13 @@ snapshots:
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
+ '@pinia/nuxt@0.11.2(magicast@0.3.5)(pinia@3.0.3(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)))':
+ dependencies:
+ '@nuxt/kit': 3.18.1(magicast@0.3.5)
+ pinia: 3.0.3(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
+ transitivePeerDependencies:
+ - magicast
+
'@pkgjs/parseargs@0.11.0':
optional: true
@@ -6571,6 +6601,10 @@ snapshots:
'@vue/devtools-api@6.6.4': {}
+ '@vue/devtools-api@7.7.7':
+ dependencies:
+ '@vue/devtools-kit': 7.7.7
+
'@vue/devtools-core@7.7.7(vite@7.1.2(@types/node@24.3.0)(jiti@2.5.1)(terser@5.43.1)(yaml@2.8.1))(vue@3.5.18(typescript@5.9.2))':
dependencies:
'@vue/devtools-kit': 7.7.7
@@ -8923,6 +8957,13 @@ snapshots:
pify@2.3.0: {}
+ pinia@3.0.3(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)):
+ dependencies:
+ '@vue/devtools-api': 7.7.7
+ vue: 3.5.18(typescript@5.9.2)
+ optionalDependencies:
+ typescript: 5.9.2
+
pirates@4.0.7: {}
pkg-types@1.3.1:
diff --git a/public/ES00A/cover.jpg b/public/ES00A/cover.jpg
new file mode 100644
index 0000000..9d5297b
Binary files /dev/null and b/public/ES00A/cover.jpg differ
diff --git a/public/ES00A/title.svg b/public/ES00A/title.svg
new file mode 100644
index 0000000..778c972
--- /dev/null
+++ b/public/ES00A/title.svg
@@ -0,0 +1,59 @@
+
+
+
+
diff --git a/public/ES00B/cover.jpg b/public/ES00B/cover.jpg
new file mode 100644
index 0000000..e9b7bdf
Binary files /dev/null and b/public/ES00B/cover.jpg differ
diff --git a/public/ES00B/title.svg b/public/ES00B/title.svg
new file mode 100644
index 0000000..4ef177f
--- /dev/null
+++ b/public/ES00B/title.svg
@@ -0,0 +1,59 @@
+
+
+
+
diff --git a/public/ES01A/cover.jpg b/public/ES01A/cover.jpg
new file mode 100644
index 0000000..bdb21bc
Binary files /dev/null and b/public/ES01A/cover.jpg differ
diff --git a/public/ES01A/number1.svg b/public/ES01A/number1.svg
deleted file mode 100644
index 292c723..0000000
--- a/public/ES01A/number1.svg
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
diff --git a/public/ES01A/title.svg b/public/ES01A/title.svg
new file mode 100644
index 0000000..bc691f6
--- /dev/null
+++ b/public/ES01A/title.svg
@@ -0,0 +1,50 @@
+
+
+
+
diff --git a/public/ES01B/cover.jpg b/public/ES01B/cover.jpg
new file mode 100644
index 0000000..036b8bd
Binary files /dev/null and b/public/ES01B/cover.jpg differ
diff --git a/public/ES01B/title.svg b/public/ES01B/title.svg
new file mode 100644
index 0000000..e4818f2
--- /dev/null
+++ b/public/ES01B/title.svg
@@ -0,0 +1,50 @@
+
+
+
+
diff --git a/server/api/artists.ts b/server/api/artists.ts
new file mode 100644
index 0000000..7e1e6d2
--- /dev/null
+++ b/server/api/artists.ts
@@ -0,0 +1,70 @@
+export default eventHandler(() => {
+ return [
+ {
+ id: 0,
+ name: "L'efondras",
+ url: "https://leffondras.bandcamp.com/music",
+ coverId: "0024705317"
+ },
+ {
+ id: 1,
+ name: "The kundalini genie",
+ url: "https://the-kundalini-genie.bandcamp.com",
+ coverId: "0012045550"
+ },
+ {
+ id: 2,
+ name: "Fontaines D.C.",
+ url: "https://fontainesdc.bandcamp.com",
+ coverId: "0027327090"
+ },
+ {
+ id: 3,
+ name: "Fontanarosa",
+ url: "https://fontanarosa.bandcamp.com",
+ coverId: "0035380235",
+ },
+ {
+ id: 4,
+ name: "Johnny mafia",
+ url: "https://johnnymafia.bandcamp.com",
+ coverId: "0035009392",
+ },
+ {
+ id: 5,
+ name: "New candys",
+ url: "https://newcandys.bandcamp.com",
+ coverId: "0033518637",
+ },
+ {
+ id: 6,
+ name: "Magic shoppe",
+ url: "https://magicshoppe.bandcamp.com",
+ coverId: "0030748374"
+ },
+ {
+ id: 7,
+ name: "Les jaguars",
+ url: "https://radiomartiko.bandcamp.com/album/surf-qu-b-cois",
+ coverId: "0016551336",
+ },
+ {
+ id: 8,
+ name: "TRAAMS",
+ url: "https://traams.bandcamp.com",
+ coverId: "0028348410",
+ },
+ {
+ id: 9,
+ name: "Blue orchid",
+ url: "https://blue-orchid.bandcamp.com",
+ coverId: "0034796193",
+ },
+ {
+ id: 10,
+ name: "I love UFO",
+ url: "https://bruitblanc.bandcamp.com",
+ coverId: "a2203158939",
+ }
+ ]
+})
diff --git a/server/api/compilations.ts b/server/api/compilations.ts
new file mode 100644
index 0000000..90b6aea
--- /dev/null
+++ b/server/api/compilations.ts
@@ -0,0 +1,36 @@
+export default eventHandler(() => {
+ return [
+ {
+ id: 'ES00A',
+ name: 'zero',
+ duration: 2794,
+ description: 'Zero is for manifesto ... ;)',
+ colorFrom: '#ffffff',
+ colorTo: '#48959d',
+ },
+ {
+ id: 'ES00B',
+ name: 'zero b-side',
+ duration: 2470,
+ description: 'Even Zero has a b-side',
+ colorFrom: '#0d01b9',
+ colorTo: '#3b7589',
+ },
+ {
+ id: 'ES01A',
+ name: 'first',
+ duration: 3487,
+ description: '...',
+ colorFrom: '#c7b3aa',
+ colorTo: '#000100',
+ },
+ {
+ id: 'ES01B',
+ name: 'first b-side',
+ duration: 3773,
+ description: '...',
+ colorFrom: '#f7dd01',
+ colorTo: '#010103',
+ }
+ ]
+})
diff --git a/server/api/playlists/[id].ts b/server/api/playlists/[id].ts
new file mode 100644
index 0000000..c72f80d
--- /dev/null
+++ b/server/api/playlists/[id].ts
@@ -0,0 +1,23 @@
+import fs from 'fs'
+import path from 'path'
+
+export default eventHandler(async (event) => {
+ const id = event.context.params?.id || ''
+
+ const directoryPath = path.join(process.cwd(), 'media/files/music/' + id) // replace 'your-folder' with the folder you want to list
+
+ try {
+ // Read the directory contents
+ const files = await fs.promises.readdir(directoryPath)
+
+ return {
+ success: true,
+ files: files.filter(file => !file.startsWith('.')) // optional: exclude unwanted files
+ }
+ } catch (error) {
+ return {
+ success: false,
+ error: error.message
+ }
+ }
+})
diff --git a/server/api/playlists/index.ts b/server/api/playlists/index.ts
new file mode 100644
index 0000000..20ef77f
--- /dev/null
+++ b/server/api/playlists/index.ts
@@ -0,0 +1,21 @@
+import fs from 'fs'
+import path from 'path'
+
+export default eventHandler(async (event) => {
+ const directoryPath = path.join(process.cwd(), 'media/files/music')
+
+ try {
+ // Read the directory contents
+ const files = await fs.promises.readdir(directoryPath)
+
+ return {
+ success: true,
+ files: files.filter(file => !file.startsWith('.')).reverse() // exclude unwanted files
+ }
+ } catch (error) {
+ return {
+ success: false,
+ error: error.message
+ }
+ }
+})
diff --git a/server/api/tracks.ts b/server/api/tracks.ts
new file mode 100644
index 0000000..a7bb894
--- /dev/null
+++ b/server/api/tracks.ts
@@ -0,0 +1,224 @@
+export default eventHandler(() => {
+ return [
+ {
+ id: 1,
+ compilationId: 'ES00A',
+ title: 'The grinding wheel',
+ artist: 0,
+ start: 0,
+ bpm: 0,
+ url: 'https://arakirecords.bandcamp.com/track/the-grinding-wheel',
+ coverId: 'a3236746052',
+ },
+ {
+ id: 2,
+ compilationId: 'ES00A',
+ title: 'Bleach',
+ artist: 1,
+ start: 393,
+ bpm: 0,
+ url: 'https://the-kundalini-genie.bandcamp.com/track/bleach-2',
+ coverId: 'a1714786533',
+ },
+ {
+ id: 3,
+ compilationId: 'ES00A',
+ title: 'Televised mind',
+ artist: 2,
+ start: 892,
+ bpm: 0,
+ url: 'https://fontainesdc.bandcamp.com/track/televised-mind',
+ coverId: 'a3772806156'
+ },
+ {
+ id: 4,
+ compilationId: 'ES00A',
+ title: 'In it',
+ artist: 3,
+ start: 1138,
+ bpm: 0,
+ url: 'https://howlinbananarecords.bandcamp.com/track/in-it',
+ coverId: 'a1720372066',
+ },
+ {
+ id: 5,
+ compilationId: 'ES00A',
+ title: 'Bad michel',
+ artist: 4,
+ start: 1245,
+ bpm: 0,
+ url: 'https://johnnymafia.bandcamp.com/track/bad-michel-3',
+ coverId: 'a0984622869',
+ },
+ {
+ id: 6,
+ compilationId: 'ES00A',
+ title: 'Overall',
+ artist: 5,
+ start: 1394,
+ bpm: 0,
+ url: 'https://newcandys.bandcamp.com/track/overall',
+ coverId: 'a0559661270',
+ },
+ {
+ id: 7,
+ compilationId: 'ES00A',
+ title: 'Blowup',
+ artist: 6,
+ start: 1674,
+ bpm: 0,
+ url: 'https://magicshoppe.bandcamp.com/track/blowup',
+ coverId: 'a1444895293',
+ },
+ {
+ id: 8,
+ compilationId: 'ES00A',
+ title: 'Guitar jet',
+ artist: 7,
+ start: 1880,
+ bpm: 0,
+ url: 'https://radiomartiko.bandcamp.com/track/guitare-jet',
+ coverId: 'a1494681687',
+ },
+ {
+ id: 9,
+ compilationId: 'ES00A',
+ title: 'Intercontinental radio waves',
+ artist: 8,
+ start: 2024,
+ bpm: 0,
+ url: 'https://traams.bandcamp.com/track/intercontinental-radio-waves',
+ coverId: 'a0046738552',
+ },
+ {
+ id: 10,
+ compilationId: 'ES00A',
+ title: 'Here comes the sun',
+ artist: 9,
+ start: 2211,
+ bpm: 0,
+ url: 'https://blue-orchid.bandcamp.com/track/here-come-the-sun',
+ coverId: 'a4102567047',
+ },
+ {
+ id: 11,
+ compilationId: 'ES00A',
+ title: 'Like in the movies',
+ artist: 10,
+ start: 2559,
+ bpm: 0,
+ url: 'https://bruitblanc.bandcamp.com/track/like-in-the-movies-2',
+ coverId: 'a2203158939',
+ },
+ {
+ id: 21,
+ compilationId: 'ES00B',
+ title: 'Ce que révèle l\'éclipse',
+ artist: 0,
+ start: 0,
+ bpm: 0,
+ url: 'https://arakirecords.bandcamp.com/track/ce-que-r-v-le-l-clipse',
+ coverId: 'a3236746052',
+ },
+ {
+ id: 22,
+ compilationId: 'ES00B',
+ title: 'Bleedin\' Gums Mushrool',
+ artist: 1,
+ start: 263,
+ bpm: 0,
+ url: 'https://the-kundalini-genie.bandcamp.com/track/bleedin-gums-mushroom',
+ coverId: 'a1714786533',
+ },
+ {
+ id: 23,
+ compilationId: 'ES00B',
+ title: 'A lucid dream',
+ artist: 2,
+ start: 554,
+ bpm: 0,
+ url: 'https://fontainesdc.bandcamp.com/track/a-lucid-dream',
+ coverId: 'a3772806156',
+ },
+ {
+ id: 24,
+ compilationId: 'ES00B',
+ title: 'Lights off',
+ artist: 3,
+ start: 781,
+ bpm: 0,
+ url: 'https://howlinbananarecords.bandcamp.com/track/lights-off',
+ coverId: 'a1720372066',
+ },
+ {
+ id: 25,
+ compilationId: 'ES00B',
+ title: 'I\'m sentimental',
+ artist: 4,
+ start: 969,
+ bpm: 0,
+ url: 'https://johnnymafia.bandcamp.com/track/im-sentimental-2',
+ coverId: 'a2333676849',
+ },
+ {
+ id: 26,
+ compilationId: 'ES00B',
+ title: 'Thrill or trip',
+ artist: 5,
+ start: 1128,
+ bpm: 0,
+ url: 'https://newcandys.bandcamp.com/track/thrill-or-trip',
+ coverId: 'a0559661270',
+ },
+ {
+ id: 27,
+ compilationId: 'ES00B',
+ title: 'Redhead',
+ artist: 6,
+ start: 1303,
+ bpm: 0,
+ url: 'https://magicshoppe.bandcamp.com/track/redhead',
+ coverId: 'a0594426943',
+ },
+ {
+ id: 28,
+ compilationId: 'ES00B',
+ title: 'Supersonic twist',
+ artist: 7,
+ start: 1584,
+ bpm: 0,
+ url: 'https://open.spotify.com/track/66voQIZAJ3zD3Eju2qtNjF',
+ coverId: 'a1494681687',
+ },
+ {
+ id: 29,
+ compilationId: 'ES00B',
+ title: 'Flowers',
+ artist: 8,
+ start: 1749,
+ bpm: 0,
+ url: 'https://traams.bandcamp.com/track/flowers',
+ coverId: 'a3644668199',
+ },
+ {
+ id: 30,
+ compilationId: 'ES00B',
+ title: 'The shade',
+ artist: 9,
+ start: 1924,
+ bpm: 0,
+ url: 'https://blue-orchid.bandcamp.com/track/the-shade',
+ coverId: 'a0804204790',
+ },
+ {
+ id: 31,
+ compilationId: 'ES00B',
+ title: 'Like in the movies',
+ artist: 10,
+ start: 2185,
+ bpm: 0,
+ url: 'https://bruitblanc.bandcamp.com/track/like-in-the-movies',
+ coverId: 'a3647322740',
+ },
+ ]
+})
diff --git a/server/tsconfig.json b/server/tsconfig.json
new file mode 100644
index 0000000..b9ed69c
--- /dev/null
+++ b/server/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../.nuxt/tsconfig.server.json"
+}
diff --git a/types/types.ts b/types/types.ts
new file mode 100644
index 0000000..0c966e0
--- /dev/null
+++ b/types/types.ts
@@ -0,0 +1,28 @@
+// types.ts
+export interface Compilation {
+ id: string
+ name: string
+ duration: number
+ tracks?: Track[]
+ description: string
+ colorFrom: string
+ colorTo: string
+}
+
+export interface Artist {
+ id: number
+ name: string
+ url: string
+ coverId: string
+}
+
+export interface Track {
+ id: string
+ compilationId: string
+ title: string
+ artistId: number
+ artist?: Artist
+ start: number
+ link: string
+ coverId: string
+}