Compare commits
10 Commits
8d3586f4d4
...
7a1cdf2178
Author | SHA1 | Date | |
---|---|---|---|
|
7a1cdf2178 | ||
|
d013e62fcf | ||
|
9c1204b46b | ||
|
8541050011 | ||
|
480e8f008c | ||
|
7f8eb7bbb9 | ||
|
7e9c0d3caf | ||
|
f972137389 | ||
|
7f8ed0e8a0 | ||
|
0ca4cc3bfe |
16
.drone.yml
@@ -1,16 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: default
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: deploy
|
|
||||||
image: docker:dind
|
|
||||||
commands:
|
|
||||||
- apk add --upgrade npm bash findutils rsync sed
|
|
||||||
- WORKDIR="/var/docker-web/apps/$DRONE_REPO_NAME"
|
|
||||||
- rm -rf $WORKDIR
|
|
||||||
- mkdir $WORKDIR
|
|
||||||
- rsync -av --exclude ./node_modules /drone/src/ $WORKDIR
|
|
||||||
- cd $WORKDIR
|
|
||||||
- npm ci
|
|
||||||
- bash /var/docker-web/src/cli.sh up $DRONE_REPO_NAME
|
|
21
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
name: Deploy App
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
container:
|
||||||
|
volumes:
|
||||||
|
- /var/docker-web:/var/docker-web
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: install
|
||||||
|
run: |
|
||||||
|
APP_DIR=/var/docker-web/apps/${GITHUB_REPOSITORY##*/}
|
||||||
|
mkdir -p $APP_DIR
|
||||||
|
cp -a $(find . -mindepth 1 -maxdepth 1 ! -name '.git' ! -name 'node_modules') "$APP_DIR/"
|
||||||
|
- name: up
|
||||||
|
run: |
|
||||||
|
export COMPOSE_BAKE=false
|
||||||
|
bash /var/docker-web/src/cli.sh up ${GITHUB_REPOSITORY##*/}
|
5
.gitignore
vendored
@@ -17,3 +17,8 @@ logs
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.fleet
|
.fleet
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
37
Dockerfile
@@ -1,19 +1,30 @@
|
|||||||
# INSTALL
|
# Stage de build
|
||||||
FROM node:18-alpine as builder
|
FROM node:20-alpine AS build
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Installer pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# Copier package.json et lockfile pour cache pnpm
|
||||||
|
COPY package.json pnpm-lock.yaml* ./
|
||||||
|
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# Copier tout le projet
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm ci && npm cache clean --force
|
|
||||||
ADD . .
|
|
||||||
|
|
||||||
# BUILD
|
# Build Nuxt
|
||||||
RUN npm run build
|
RUN pnpm build
|
||||||
|
|
||||||
|
# Stage production
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
# PROD
|
|
||||||
FROM node:18-alpine
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /app/.output /app/.output
|
|
||||||
COPY --from=builder /app/.nuxt /app/.nuxt
|
COPY --from=build /app/.output .output
|
||||||
COPY --from=builder /app/.env /app/.env
|
COPY --from=build /app/package.json ./
|
||||||
ENV HOST 0.0.0.0
|
COPY --from=build /app/node_modules ./node_modules
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
CMD source .env && node .output/server/index.mjs
|
CMD ["node", ".output/server/index.mjs"]
|
||||||
|
76
README.md
@@ -1 +1,75 @@
|
|||||||
# evilSpins
|
# Nuxt Minimal Starter
|
||||||
|
|
||||||
|
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||||
|
11
app.vue
@@ -1,11 +0,0 @@
|
|||||||
<template>
|
|
||||||
<NuxtPage />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
// @todo : laod datas as plugin/middleware (cant load pinia in plugin/middleware) ?
|
|
||||||
onMounted(async ()=>{
|
|
||||||
const dataStore = await useDataStore()
|
|
||||||
await dataStore.loadData()
|
|
||||||
})
|
|
||||||
</script>
|
|
6
app/app.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<NuxtLayout>
|
||||||
|
<NuxtPage />
|
||||||
|
<NuxtRouteAnnouncer />
|
||||||
|
</NuxtLayout>
|
||||||
|
</template>
|
8
app/components/atropos.vue
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center justify-center min-h-screen">
|
||||||
|
<atropos-component class="h-72 w-60" active-offset="80" shadow-scale="1.05">
|
||||||
|
<img src="/logo.svg">
|
||||||
|
<img src="/ES01A/object.png">
|
||||||
|
</atropos-component>
|
||||||
|
</div>
|
||||||
|
</template>
|
96
app/pages/index.vue
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="background fixed w-full h-full">
|
||||||
|
<video class="animation screen" loop autoplay muted ref="animation">
|
||||||
|
<source src="https://files.erudi.fr/evilspins/sloughi-run-loop-big.webm" type="video/webm">
|
||||||
|
<source src="https://files.erudi.fr/evilspins/sloughi-run-loop-small.webm" type="video/webm"
|
||||||
|
media="all and (max-width: 640px)">
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
<section class="splash-screen flex items-center flex-col">
|
||||||
|
<figure class="ui">
|
||||||
|
<img class="logo" src="/logo.svg">
|
||||||
|
</figure>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo,
|
||||||
|
.button,
|
||||||
|
.shadow,
|
||||||
|
.animation,
|
||||||
|
.mix {
|
||||||
|
transition: .7s opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screen {
|
||||||
|
position: absolute;
|
||||||
|
height: 100vh;
|
||||||
|
min-width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.splash-screen {
|
||||||
|
position: relative;
|
||||||
|
height: 100vh;
|
||||||
|
box-shadow: inset black 0px 1px 800px 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animation {
|
||||||
|
z-index: 1;
|
||||||
|
object-fit: cover;
|
||||||
|
opacity: .8;
|
||||||
|
/* opacity: 0; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.mix {
|
||||||
|
z-index: 4;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow {
|
||||||
|
z-index: 3;
|
||||||
|
box-shadow: rgb(0, 0, 0) 0px 0px 170px 70px inset;
|
||||||
|
opacity: .9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui {
|
||||||
|
z-index: 4;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
max-width: 80%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
filter: drop-shadow(8px 8px 0 rgb(0 0 0 / 0.8));
|
||||||
|
}
|
||||||
|
|
||||||
|
.mixPlayer {
|
||||||
|
background: black;
|
||||||
|
max-height: 70vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-shadow {
|
||||||
|
text-shadow: 3px 2px 8px black;
|
||||||
|
}
|
||||||
|
</style>
|
3
app/pages/wait.vue
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<atropos />
|
||||||
|
</template>
|
@@ -1,45 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
body {
|
|
||||||
@apply bg-black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
text-decoration: none;
|
|
||||||
box-shadow: 0 8px 0 0 black;
|
|
||||||
transition: all .3s;
|
|
||||||
border: 8px black solid;
|
|
||||||
line-height: 100%;
|
|
||||||
border-width: 2px;
|
|
||||||
border-radius: 100px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: black;
|
|
||||||
font-size: 26px;
|
|
||||||
background-color: #ffffff59;
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
|
|
||||||
@media (min-width: 780px) {
|
|
||||||
height: 70px;
|
|
||||||
width: 70px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover {
|
|
||||||
background-color: #fdec50ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:active {
|
|
||||||
box-shadow: 0 0 0 0 black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button--screened {
|
|
||||||
top: 74px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.compilation {
|
|
||||||
cursor: pointer;
|
|
||||||
max-width: 420px;
|
|
||||||
}
|
|
@@ -1,22 +0,0 @@
|
|||||||
<template>
|
|
||||||
<NuxtLink :to="'/compilations/' + props.data.id" class="compilation mx-auto p-4 inline-flex">
|
|
||||||
<atropos-component class="my-atropos" active-offset="80" shadow-scale="1.05">
|
|
||||||
<img :src="props.data.id + '/bkg.jpg'" data-atropos-offset="-8" />
|
|
||||||
<img :src="props.data.id + '/object.png'" data-atropos-offset="-3" class="absolute inset-0 object-cover" />
|
|
||||||
<img :src="props.data.id + '/name.png'" data-atropos-offset="0" class="absolute inset-0 object-cover" />
|
|
||||||
<img src="/logo.svg" data-atropos-offset="0" width="70%" class="logo absolute inset-0" />
|
|
||||||
</atropos-component>
|
|
||||||
</NuxtLink>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const props = defineProps(['data', 'template'])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.logo {
|
|
||||||
filter: drop-shadow(4px 4px 0 rgb(0 0 0 / 0.5));
|
|
||||||
left: 14%;
|
|
||||||
top: 10%;
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -1,11 +0,0 @@
|
|||||||
<template>
|
|
||||||
<section>
|
|
||||||
<div v-for="compilation in store.getAllCompilations" class="text-white">
|
|
||||||
<compilationObject :data="compilation" template="full" />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const store = useDataStore()
|
|
||||||
</script>
|
|
@@ -1,31 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
const isLoaded = ref(false)
|
|
||||||
const isPlaying = ref(false)
|
|
||||||
const video = ref()
|
|
||||||
async function play() {
|
|
||||||
await video.value.player.playVideo()
|
|
||||||
}
|
|
||||||
function stateChange(event) {
|
|
||||||
isPlaying.value = event.data === 1
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="flex items-center justify-center p-5">
|
|
||||||
<ScriptYouTubePlayer ref="video" video-id="iyPiiZly864" class="group" @ready="isLoaded = true" @state-change="stateChange">
|
|
||||||
<template #awaitingLoad>
|
|
||||||
<div class="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 h-[48px] w-[68px]">
|
|
||||||
<svg height="100%" version="1.1" viewBox="0 0 68 48" width="100%"><path d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f00" /><path d="M 45,24 27,14 27,34" fill="#fff" /></svg>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</ScriptYouTubePlayer>
|
|
||||||
</div>
|
|
||||||
<div class="text-center">
|
|
||||||
<div v-if="!isLoaded" class="mb-5" size="sm" color="blue" variant="soft" title="Click to load" description="Clicking the video will load the Vimeo iframe and start the video." />
|
|
||||||
<button v-if="isLoaded && !isPlaying" @click="play">
|
|
||||||
Play Video
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
@@ -1,28 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="compilation mx-auto p-4 inline-flex">
|
|
||||||
<atropos-component ref="atropos" class="my-atropos" active-offset="80" shadow-scale="1.05">
|
|
||||||
<img src="/zero/sky-b.jpg" data-atropos-offset="-8" />
|
|
||||||
<img src="/zero/propeller-b.png" data-atropos-offset="-3" class="absolute inset-0 object-cover" />
|
|
||||||
<img src="/zero/zero-b.png" data-atropos-offset="0" class="absolute inset-0 object-cover" />
|
|
||||||
<img src="/logo.svg" data-atropos-offset="0" width="70%" class="logo absolute inset-0" />
|
|
||||||
</atropos-component>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { onMounted, ref } from 'vue'
|
|
||||||
|
|
||||||
const atropos = ref(null)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
/* .my-atropos {
|
|
||||||
width: 320px;
|
|
||||||
height: 160px;
|
|
||||||
} */
|
|
||||||
.logo {
|
|
||||||
filter: drop-shadow(4px 4px 0 rgb(0 0 0 / 0.5));
|
|
||||||
left: 14%;
|
|
||||||
top: 10%;
|
|
||||||
}
|
|
||||||
</style>
|
|
5
config.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
export REPO_NAME="evilspins"
|
||||||
|
export DOMAIN="evilspins.$MAIN_DOMAIN"
|
||||||
|
export PORT="7901"
|
||||||
|
export PORT_EXPOSED="3000"
|
||||||
|
export REDIRECTIONS="" # example.$MAIN_DOMAIN->/route $MAIN_DOMAIN->url /route->/another-route /route->url
|
@@ -1,20 +1,23 @@
|
|||||||
services:
|
services:
|
||||||
|
|
||||||
evilspins:
|
evilspins:
|
||||||
build: .
|
image: local/evilspins
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
container_name: evilspins
|
container_name: evilspins
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
working_dir: /app
|
||||||
ports:
|
ports:
|
||||||
- $PORT:3000
|
- "${PORT}:${PORT_EXPOSED}"
|
||||||
|
volumes:
|
||||||
|
- "${MEDIA_DIR}:/mnt/media"
|
||||||
environment:
|
environment:
|
||||||
VIRTUAL_HOST: "${DOMAIN}"
|
VIRTUAL_HOST: "${DOMAIN}"
|
||||||
LETSENCRYPT_HOST: "${DOMAIN}"
|
LETSENCRYPT_HOST: "${DOMAIN}"
|
||||||
PUID: "${PUID}"
|
PUID: "${PUID}"
|
||||||
PGID: "${PGID}"
|
PGID: "${PGID}"
|
||||||
volumes:
|
|
||||||
- "${MEDIA_DIR}:/app/media"
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
name: dockerweb
|
name: dockerweb
|
||||||
external: true
|
external: true
|
||||||
|
6
eslint.config.mjs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// @ts-check
|
||||||
|
import withNuxt from './.nuxt/eslint.config.mjs'
|
||||||
|
|
||||||
|
export default withNuxt(
|
||||||
|
// Your custom configs here
|
||||||
|
)
|
125
logo.svg
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -1,24 +1,11 @@
|
|||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
ssr: true,
|
compatibilityDate: '2025-07-15',
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
css: ['~/assets/css/main.css'],
|
modules: ['@nuxt/eslint', '@nuxtjs/tailwindcss', '@pinia/nuxt'],
|
||||||
|
vue: {
|
||||||
postcss: {
|
compilerOptions: {
|
||||||
plugins: {
|
isCustomElement: (tag) => ['atropos-component'].includes(tag)
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
app: {
|
|
||||||
head: {
|
|
||||||
charset: 'utf-8',
|
|
||||||
viewport: 'width=device-width, initial-scale=1',
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
compatibilityDate: '2024-07-10',
|
|
||||||
modules: ['@pinia/nuxt']
|
|
||||||
})
|
})
|
8186
package-lock.json
generated
25
package.json
@@ -1,27 +1,28 @@
|
|||||||
{
|
{
|
||||||
"name": "nuxt-app",
|
"name": "nuxt-app",
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
"dev": "nuxt dev --host",
|
"dev": "nuxt dev",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"preview": "nuxt preview",
|
"preview": "nuxt preview",
|
||||||
"postinstall": "nuxt prepare"
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pinia/nuxt": "^0.5.5",
|
"@nuxt/eslint": "1.9.0",
|
||||||
|
"@nuxtjs/tailwindcss": "6.14.0",
|
||||||
"atropos": "^2.0.2",
|
"atropos": "^2.0.2",
|
||||||
"nuxt": "^3.12.3",
|
"eslint": "^9.33.0",
|
||||||
"pinia": "^2.2.4",
|
"nuxt": "^4.0.3",
|
||||||
"unhead": "^1.9.15",
|
"vue": "^3.5.18",
|
||||||
"vue": "^3.4.31",
|
"vue-router": "^4.5.1"
|
||||||
"vue-router": "^4.4.0"
|
|
||||||
},
|
},
|
||||||
|
"engines": {
|
||||||
|
"pnpm": ">=10 <11"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^10.4.19",
|
"@pinia/nuxt": "^0.11.2"
|
||||||
"postcss": "^8.4.39",
|
|
||||||
"sass": "^1.77.6",
|
|
||||||
"tailwindcss": "^3.4.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
137
pages/about.vue
@@ -1,137 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="text-white p-12 text-lg flex flex-col items-center">
|
|
||||||
<a href="/" class="mb-12">
|
|
||||||
<img class="logo" src="/logo.svg">
|
|
||||||
</a>
|
|
||||||
<div class="max-w-4xl">
|
|
||||||
<h1 class="text-esyellow text-6xl mb-8">About evilSpins ...</h1>
|
|
||||||
<pre>
|
|
||||||
Rather than explaining the "artistic" approach of evilspins in too formal a manner, I prefer to freely share the notes and sketches as a testament to the project's long genesis (2019 -> 2024) :
|
|
||||||
</pre>
|
|
||||||
<pre>
|
|
||||||
"The idea of the name comes from Anton Newcombe, who defines music as something that must remain independent,
|
|
||||||
hence his quote "keep music evil", from which 'evil' and 'spins' refer to music as an object that turns (cassette,
|
|
||||||
vinyl, CD...), music is a living object in perpetual motion and it's 'evil' / independent / unmanageable because
|
|
||||||
it makes you dance, it takes the listener without even realizing it.
|
|
||||||
</pre>
|
|
||||||
<img src="https://files.erudi.fr/evilspins/ABOUT-1.jpg">
|
|
||||||
<pre>
|
|
||||||
Each compilation is the original soundtrack of a non-existent film. It must leave room for imagination and
|
|
||||||
reflection.
|
|
||||||
A compilation tries to produce the effect of a film, to provoke imagination.
|
|
||||||
It's an opportunity to decontextualize forgotten, outdated, or unconsciously caricatured musical genres
|
|
||||||
(bluegrass,
|
|
||||||
punk, folk, hip-hop...) or simply to discover new genres.
|
|
||||||
Approach music without thinking about the stylistic references of the piece, like in a film.
|
|
||||||
</pre>
|
|
||||||
<img src="https://files.erudi.fr/evilspins/ABOUT-2.jpg">
|
|
||||||
<pre>
|
|
||||||
A compilation can therefore offer several readings,
|
|
||||||
- a panel of characters,
|
|
||||||
- several versions (short, long like a director's cut, side A/B (side B could be a parallel version with the same
|
|
||||||
artists in the same order but with different titles very close))
|
|
||||||
- several possible reading modes (mode 1: only the mixed sound and artworks (only play/pause is available),
|
|
||||||
mode 2: portraits and names of the protagonists, anecdotes, quotes, and web links (possibility to go to the
|
|
||||||
next/previous track and to 'seek'))
|
|
||||||
- an artwork (square format (vinyl) or 16/9 + black band (cinema)) - vocal samples to make characters speak?
|
|
||||||
(samples of artists in interviews, for example)
|
|
||||||
- a mix must follow this order:
|
|
||||||
List of quintessence sound :
|
|
||||||
1. accessible but instrumental
|
|
||||||
2. more researched and instrumental
|
|
||||||
3. more rhythmic instrumental
|
|
||||||
4->7. rhythmic sung
|
|
||||||
8. rhythmic instrumental
|
|
||||||
9. Instrumental
|
|
||||||
10. bluegrass final Evils spins from the idea that music needs the imagination of its listener.
|
|
||||||
11. hidden track
|
|
||||||
</pre>
|
|
||||||
<img src="https://files.erudi.fr/evilspins/ABOUT-3.jpg">
|
|
||||||
<pre>
|
|
||||||
Design: timeline of the player like the itinerary of a journey on a map OR like a display board at a train
|
|
||||||
station/airport "A problem created cannot be solved by thinking in the same way it was created." "God only depends
|
|
||||||
on the imagination of men" Drawing situations where you meet someone you think you know well but who doesn't have
|
|
||||||
the same vision of things as you. Example: discussion about music and completely divergent points of view, (Nick
|
|
||||||
Waterhouse = completely inaccessible jazz) Going to see local labels inventing a religion and therefore a god, is
|
|
||||||
only a way to personify one's conscience. The projects converge on the concept of a "cyber residence of artists"
|
|
||||||
drawing a face to one's morality. Dreams are nightmares, nightmares are dreams. Starting from reflections on the
|
|
||||||
use
|
|
||||||
of new technologies; questioning one's use of the internet on one's computer, phone, etc., allows one to wonder
|
|
||||||
what? when? why do I need the internet, to watch a movie, to listen to music... In my case, the answers to these
|
|
||||||
questions propose a use that mixes tools and methods from different eras. TOOLS & METHODS FROM DIFFERENT
|
|
||||||
ERAS/CONTEXTS Just like in the film 'La fille du 14 juillet', it can be very interesting to play on the contrasts
|
|
||||||
between different eras by mixing them in the same visual and sound realization. Idea of realization graphic novel
|
|
||||||
or
|
|
||||||
comic book: Observation: with the revolution of the internet and new technologies, cinema has become a major art
|
|
||||||
that everyone masters more or less. The public's gaze is sharpened and everyone knows how to apprehend
|
|
||||||
cinematographic realization. The plans, camera movements, sound effects are a language that everyone knows how to
|
|
||||||
read (cinema is carried by all through downloading & streaming) ... and even write (I can make a film with my
|
|
||||||
phone,
|
|
||||||
reflex cameras have become affordable). How to draw cinema? Try to take key scenes from cinema, draw/paint them
|
|
||||||
and
|
|
||||||
animate them. fixed plan? traveling? zoom? panoramic? plunge? counter-plunge? wide-angle? long focal? work on the
|
|
||||||
Wikipedia of 'film noir' re-watch film noir link with the polar noir? film noir has a pretentious approach at
|
|
||||||
first
|
|
||||||
glance. so we need to find a technique (visual? sound?) to disarm this bad image. to do this we need to start by
|
|
||||||
isolating and understanding the possible pretentious aspect of film noir.
|
|
||||||
</pre>
|
|
||||||
<img src="https://files.erudi.fr/evilspins/ABOUT-4.jpg">
|
|
||||||
<pre>
|
|
||||||
The solitude of the character? The
|
|
||||||
voice-overs that narrate the thoughts? The appearance of the protagonist? The cliché (visual & script) of the
|
|
||||||
polar
|
|
||||||
noir too worn out? (the detective alone in his thoughts, in his apartment smoking a cigarette on the balcony) the
|
|
||||||
cigarette can still be a more powerful visual element than a cliché transition with animation of the cigarette?
|
|
||||||
cigarette = huge filmographic symbol == we find it in most films especially in the era of film noir == commercial
|
|
||||||
influence tool == influence of American culture (cowboy), == symbol of the ephemeral, like life, like the
|
|
||||||
characters
|
|
||||||
of a film, like a film. the 2 mega clichés: Nicholson/Polansky in Chinatown & Ridley Scott in Blade Runner How to
|
|
||||||
integrate the cigarette? = 3D animation? (often ugly, technically very difficult, aesthetically difficult) =
|
|
||||||
hand-drawn animation? (long... very long to do but good pretext to train) = vector-drawn animation? (technically
|
|
||||||
moderately difficult but aesthetically difficult) = film excerpts? (technically easy & aesthetically very easy BUT
|
|
||||||
not really creation (montage), and illegal... to check) = animation of the spin (film zoom in Cassette, CD, Vinyl,
|
|
||||||
the plates of a hard drive (joke -> why not make a montage effect), find an equivalent for digital (server bays,
|
|
||||||
server fan? (joke))) why not call the box to meet at Slift to turn it properly and start a collaboration?
|
|
||||||
otherwise,
|
|
||||||
a lot of material to Bellecours photo + ... Fnac? no, much more interesting to go through a collaboration. Take
|
|
||||||
out
|
|
||||||
the rushes of films.
|
|
||||||
</pre>
|
|
||||||
<img src="https://files.erudi.fr/evilspins/ABOUT-5.jpg">
|
|
||||||
<pre>
|
|
||||||
|
|
||||||
The thinking of Jack Nicholson in Chinatown No visual drawing during the reading of the piece,
|
|
||||||
only why not the log / cover / artwork of the album the reading should not look like a PowerPoint, the
|
|
||||||
counter-example is everywhere on YouTube. On the other hand, a drawn and animated artwork in parallax why not. See
|
|
||||||
3D js cover -> at the mouse movement: preview with animation -> At the click fade of the box zoom on the cover the
|
|
||||||
animation is no longer manual but automatic (linear movement? random?) after the cigarette... the smoke... too
|
|
||||||
cliché? possible but the smoke can make a transition between 2 listens / animations. the listening ends the smoke
|
|
||||||
arrives brings us to the cigarette which brings us to a protagonist who brings us to a film excerpt. why
|
|
||||||
evilspins?
|
|
||||||
The spin obviously refers to the movement of music both by its format (cassette, vinyl, CD) and by its effect
|
|
||||||
(membrane, air movement, dance) possible sound effect: end of the piece Purple Mercy - Purple -> the end of the
|
|
||||||
piece ends with an abrupt snare with a subtle reverb -> effect felt: conclusion on an impression of grand space ->
|
|
||||||
effect analyzed / symbolic: grandeur of the proposal but above all empty room -> no public -> therefore call to
|
|
||||||
the
|
|
||||||
public -> idea expressible: maybe too pretentious again. film noir has a pretentious image at first glance. we
|
|
||||||
need
|
|
||||||
to find a technique (visual? sound?) to disarm this bad image. to do this we need to start by isolating and
|
|
||||||
understanding the possible pretentious aspect of film noir. The solitude of the character? The voice-overs that
|
|
||||||
narrate the thoughts? The appearance of the protagonist? The cliché (visual & script) of the polar noir too worn
|
|
||||||
out? (the detective alone in his thoughts, in his apartment smoking a cigarette on the balcony)"
|
|
||||||
</pre>
|
|
||||||
<img src="https://files.erudi.fr/evilspins/ABOUT-6.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
img {
|
|
||||||
margin: 32px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
white-space: pre-line;
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -1,154 +0,0 @@
|
|||||||
<template @keydown.esc="closePlayer()">
|
|
||||||
<div class="text-white w-full flex items-center flex-col">
|
|
||||||
<button class="text-sm md:text-5xl leading-none button button--close m-3 flex justify-center items-center z-50"
|
|
||||||
@click="closePlayer()">
|
|
||||||
</button>
|
|
||||||
<video class="mixPlayer w-full" controls ref="mixPlayer">
|
|
||||||
<source :src="videoSD" type="video/mp4">
|
|
||||||
</video>
|
|
||||||
<nav class="text-esyellow w-full flex" v-if="currentTrack">
|
|
||||||
<button v-for="(track, index) in tracks" @click="listenTo(track.start)" :index="track.id"
|
|
||||||
class="border-l-wihte-400 border-l-2 p-2 flex-grow hover:bg-esyellow hover:text-black"
|
|
||||||
:class="{ 'border-l-0': index === 0, 'bg-esyellow text-black': track.id === currentTrack.id }">
|
|
||||||
<span class="block">
|
|
||||||
{{ index + 1 }}
|
|
||||||
</span>
|
|
||||||
<span class="hidden 2xl:block">
|
|
||||||
{{ track.title }}
|
|
||||||
</span>
|
|
||||||
<span class="hidden lg:block">
|
|
||||||
{{ getArtistName(track.artist) }}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<article class="text-white p-8 max-w-5xl" v-if="currentTrack">
|
|
||||||
<div class="flex flex-col sm:flex-row items-center ">
|
|
||||||
<a :href="currentTrack.url" target="_blank" class="mr-4">
|
|
||||||
<atropos-component>
|
|
||||||
<img class="flex-grow-0" :src="'https://f4.bcbits.com/img/' + currentTrack.cover + '_8.jpg'" />
|
|
||||||
</atropos-component>
|
|
||||||
</a>
|
|
||||||
<div>
|
|
||||||
<a :href="currentTrack.url" target="_blank" rel="noopener noreferrer">
|
|
||||||
<h3 class="text-5xl">
|
|
||||||
{{ currentTrack.title }}
|
|
||||||
</h3>
|
|
||||||
</a>
|
|
||||||
<a v-if="currentArtist" :href="currentArtist.url" target="_blank" rel="noopener noreferrer">
|
|
||||||
<h2 class="font-bold text-6xl text-esyellow">
|
|
||||||
{{ currentArtist.name }}
|
|
||||||
</h2>
|
|
||||||
</a>
|
|
||||||
<h4 class="text-xl text-slate-200">
|
|
||||||
{{ compilation.name }}
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="block mt-10">
|
|
||||||
see artist page:<br>
|
|
||||||
<a v-if="currentArtist" target="_blank" class="underline text-orange-500 hover:text-orange-400"
|
|
||||||
:href="currentArtist.url">
|
|
||||||
{{ currentArtist.name }}
|
|
||||||
</a><br>
|
|
||||||
purchase the track:<br>
|
|
||||||
<a target="_blank" class="underline text-orange-500 hover:text-orange-400" :href="currentTrack.url">
|
|
||||||
{{ currentTrack.title }}
|
|
||||||
</a><br>
|
|
||||||
<br>
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
const route = useRoute()
|
|
||||||
const store = useDataStore()
|
|
||||||
|
|
||||||
const compilation = ref()
|
|
||||||
const tracks = ref()
|
|
||||||
const mixPlayer = ref()
|
|
||||||
const videoSD = ref()
|
|
||||||
const currentTrack = ref()
|
|
||||||
const { isLoaded } = storeToRefs(store)
|
|
||||||
const currentArtist = computed(() => {
|
|
||||||
return store.getArtistById(currentTrack.value.artist)
|
|
||||||
})
|
|
||||||
const getArtistName = (id: number) => {
|
|
||||||
return store.getArtistById(id)?.name
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOAD DATAs
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
loadCompilation() // if user arrive directly on compilation page
|
|
||||||
})
|
|
||||||
watch(isLoaded, () => {
|
|
||||||
loadCompilation() // if the user came from another page
|
|
||||||
})
|
|
||||||
|
|
||||||
const watchPlayingTrack = () => {
|
|
||||||
setInterval(() => {
|
|
||||||
if (mixPlayer.value && compilation.value.id) {
|
|
||||||
currentTrack.value = tracks.value.find((track: { start: number; }, index: number) => {
|
|
||||||
const nextTrackStart = tracks.value[index + 1]?.start ?? Infinity
|
|
||||||
return track.start <= mixPlayer.value.currentTime && mixPlayer.value.currentTime < nextTrackStart
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadCompilation = () => {
|
|
||||||
if (isLoaded.value) {
|
|
||||||
compilation.value = store.getCompilationById(route.params.id as string)
|
|
||||||
tracks.value = store.getTracksByCompilationId(route.params.id as string)
|
|
||||||
videoSD.value = 'https://files.erudi.fr/evilspins/' + compilation.value.id + '-SD.mp4'
|
|
||||||
mixPlayer.value.load()
|
|
||||||
mixPlayer.value.play()
|
|
||||||
mixPlayer.value.focus()
|
|
||||||
watchPlayingTrack()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const listenTo = (start: number) => {
|
|
||||||
mixPlayer.value.currentTime = start
|
|
||||||
mixPlayer.value.play()
|
|
||||||
}
|
|
||||||
|
|
||||||
const closePlayer = async () => {
|
|
||||||
await navigateTo('/')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
filter: drop-shadow(8px 8px 0 rgb(0 0 0 / 0.8));
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mixPlayer {
|
|
||||||
background: black;
|
|
||||||
max-height: 70vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav>button:first-child {
|
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button--close {
|
|
||||||
position: fixed;
|
|
||||||
right: 2vw;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: "\00d7";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
127
pages/index.vue
@@ -1,127 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="w-full flex justify-center">
|
|
||||||
<nav class="[&>*]:p-2 text-white bottom-0 right-0 fixed flex justify-center z-50">
|
|
||||||
<a href="https://www.youtube.com/channel/UCATtFHnOLDCv8qroi2KW3ZA" target="about:blank" class="mt-1">
|
|
||||||
<img src="/youtube.svg" alt="youtube channel" />
|
|
||||||
</a>
|
|
||||||
<a href="mailto:contact@evilspins.com">📬</a>
|
|
||||||
<a href="/about">❓</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
<section class="splash-screen flex items-center flex-col">
|
|
||||||
<figure class="ui">
|
|
||||||
<img class="logo" src="/logo.svg">
|
|
||||||
<h1 class="text-white pt-6 text-sm md:text-md lg:text-lg text-center font-bold tracking-widest">Compilations
|
|
||||||
Indépendantes
|
|
||||||
</h1>
|
|
||||||
<button class="button button--screened relative top-16 flex justify-center items-center" @click="scrollDown()">
|
|
||||||
↓
|
|
||||||
</button>
|
|
||||||
</figure>
|
|
||||||
<div class="shadow screen" />
|
|
||||||
<video class="animation screen" loop autoplay muted ref="animation">
|
|
||||||
<source src="https://files.erudi.fr/evilspins/sloughi-run-loop-big.webm" type="video/webm">
|
|
||||||
<source src="https://files.erudi.fr/evilspins/sloughi-run-loop-small.webm" type="video/webm"
|
|
||||||
media="all and (max-width: 640px)">
|
|
||||||
</video>
|
|
||||||
</section>
|
|
||||||
<section class="flex justify-center">
|
|
||||||
<div class="flex max-w-2xl">
|
|
||||||
<compilationsList />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup lang="ts">
|
|
||||||
// SEO
|
|
||||||
useSeoMeta({
|
|
||||||
title: 'evilSpins - compilations indépendantes',
|
|
||||||
ogTitle: 'evilSpins - compilations indépendantes',
|
|
||||||
description: 'evilSpins - compilations indépendantes, la bande originale d\'un film qui n\'existe pas',
|
|
||||||
ogDescription: 'evilSpins - compilations indépendantes, la bande originale d\'un film qui n\'existe pas',
|
|
||||||
ogImage: 'https://evilspins.com/logo.svg'
|
|
||||||
})
|
|
||||||
|
|
||||||
const dataStore = useDataStore()
|
|
||||||
|
|
||||||
const scrollDown = function () {
|
|
||||||
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo,
|
|
||||||
.button,
|
|
||||||
.shadow,
|
|
||||||
.animation,
|
|
||||||
.mix {
|
|
||||||
transition: .7s opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screen {
|
|
||||||
position: absolute;
|
|
||||||
height: 100vh;
|
|
||||||
min-width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.splash-screen {
|
|
||||||
position: relative;
|
|
||||||
height: 100vh;
|
|
||||||
background-color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.animation {
|
|
||||||
z-index: 1;
|
|
||||||
object-fit: cover;
|
|
||||||
opacity: .8;
|
|
||||||
/* opacity: 0; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.mix {
|
|
||||||
z-index: 4;
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shadow {
|
|
||||||
z-index: 3;
|
|
||||||
box-shadow: rgb(0, 0, 0) 0px 0px 170px 70px inset;
|
|
||||||
opacity: .9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui {
|
|
||||||
z-index: 4;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
max-width: 80%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
filter: drop-shadow(8px 8px 0 rgb(0 0 0 / 0.8));
|
|
||||||
}
|
|
||||||
|
|
||||||
.mixPlayer {
|
|
||||||
background: black;
|
|
||||||
max-height: 70vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide {
|
|
||||||
opacity: 0;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -1,5 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="h-screen w-full flex justify-center p-16">
|
|
||||||
<img src="/logo.svg">
|
|
||||||
</div>
|
|
||||||
</template>
|
|
10234
pnpm-lock.yaml
generated
Normal file
BIN
public/ES01A/bkg.jpg
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
public/ES01A/name.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
50
public/ES01A/number1.svg
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
public/ES01A/object.png
Normal file
After Width: | Height: | Size: 4.4 MiB |
BIN
public/ES01B/B.jpg
Normal file
After Width: | Height: | Size: 2.8 MiB |
BIN
public/ES01B/bkg.jpg
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
public/ES01B/name.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
22
public/ES01B/name.svg
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
public/ES01B/object.png
Executable file
After Width: | Height: | Size: 4.5 MiB |
BIN
public/ESPLAYLISTS/bkg.jpg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
public/ESPLAYLISTS/name.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
public/ESPLAYLISTS/object.png
Normal file
After Width: | Height: | Size: 84 KiB |
163
public/logo.svg
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
@@ -1,38 +1,50 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
|
fill="#000000"
|
||||||
|
height="800px"
|
||||||
|
width="800px"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg1"
|
id="Capa_1"
|
||||||
|
viewBox="0 0 60 60"
|
||||||
|
xml:space="preserve"
|
||||||
sodipodi:docname="play.svg"
|
sodipodi:docname="play.svg"
|
||||||
width="25.177818"
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
height="31.875"
|
|
||||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||||
<defs
|
id="defs2">
|
||||||
id="defs1" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
</defs><sodipodi:namedview
|
||||||
pagecolor="#505050"
|
id="namedview2"
|
||||||
bordercolor="#eeeeee"
|
pagecolor="#505050"
|
||||||
borderopacity="1"
|
bordercolor="#eeeeee"
|
||||||
inkscape:showpageshadow="0"
|
borderopacity="1"
|
||||||
inkscape:pageopacity="0"
|
inkscape:showpageshadow="0"
|
||||||
inkscape:pagecheckerboard="0"
|
inkscape:pageopacity="0"
|
||||||
inkscape:deskcolor="#505050"
|
inkscape:pagecheckerboard="0"
|
||||||
inkscape:zoom="1.9448516"
|
inkscape:deskcolor="#505050"
|
||||||
inkscape:cx="202.07197"
|
inkscape:zoom="0.94997202"
|
||||||
inkscape:cy="136.00009"
|
inkscape:cx="340.01001"
|
||||||
inkscape:window-width="1920"
|
inkscape:cy="397.38012"
|
||||||
inkscape:window-height="1011"
|
inkscape:window-width="1920"
|
||||||
inkscape:window-x="0"
|
inkscape:window-height="1132"
|
||||||
inkscape:window-y="0"
|
inkscape:window-x="0"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-y="0"
|
||||||
inkscape:current-layer="svg1" />
|
inkscape:window-maximized="1"
|
||||||
<path
|
inkscape:current-layer="path4" />
|
||||||
style="font-size:64px;line-height:0.6;font-family:'Noto Sans Rejang';-inkscape-font-specification:'Noto Sans Rejang';letter-spacing:0.03px;word-spacing:0.16px;stroke-width:5.38174;stroke-miterlimit:2.3;stroke-dasharray:1.07635, 5.91989"
|
|
||||||
d="M 0,31.875 V 0 l 25.177818,15.9375 z"
|
<g
|
||||||
id="text1"
|
id="g4"
|
||||||
aria-label="▸" />
|
transform="translate(9.7969913,-22.06049)"><g
|
||||||
</svg>
|
id="path4"
|
||||||
|
inkscape:transform-center-x="-3.1076416"
|
||||||
|
inkscape:transform-center-y="0.031482236"
|
||||||
|
style="opacity:1"
|
||||||
|
transform="matrix(0.16696126,-0.60372499,0.52316491,0.19267096,25.039308,35.922386)"><path
|
||||||
|
id="path1"
|
||||||
|
style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:2.3;paint-order:fill markers stroke;enable-background:accumulate;stop-color:#000000;stop-opacity:1"
|
||||||
|
d="m -9.5847112,-19.414681 a 2.4868138,2.4868138 0 0 0 -3.1047968,-1.516874 l -18.788944,6.087811 -18.791084,6.0858648 a 2.4868138,2.4868138 0 0 0 -0.900333,4.2129952 L -36.501957,8.6836742 -21.835903,21.91414 a 2.4868138,2.4868138 0 0 0 4.097569,-1.326305 l 4.124976,-19.3182854 4.1231169,-19.3163776 a 2.4868138,2.4868138 0 0 0 -0.09447,-1.367853 z m -0.7440438,70.809953 a 54.628808,47.339229 72.300195 0 1 -61.707096,-37.65028 54.628808,47.339229 72.300195 0 1 28.489522,-66.435356 54.628808,47.339229 72.300195 0 1 61.707096,37.650281 54.628808,47.339229 72.300195 0 1 -28.489522,66.435355 z" /></g></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
2
public/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
User-Agent: *
|
||||||
|
Disallow:
|
@@ -1,81 +0,0 @@
|
|||||||
export default eventHandler(() => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
name: "L'efondras",
|
|
||||||
url: "https://leffondras.bandcamp.com/music",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0024705317"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "The kundalini genie",
|
|
||||||
url: "https://the-kundalini-genie.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0012045550"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: "Fontaines D.C.",
|
|
||||||
url: "https://fontainesdc.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0027327090"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: "Fontanarosa",
|
|
||||||
url: "https://fontanarosa.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0035380235",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: "Johnny mafia",
|
|
||||||
url: "https://johnnymafia.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0035009392",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
name: "New candys",
|
|
||||||
url: "https://newcandys.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0033518637",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
name: "Magic shoppe",
|
|
||||||
url: "https://magicshoppe.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0030748374"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
name: "Les jaguars",
|
|
||||||
url: "https://radiomartiko.bandcamp.com/album/surf-qu-b-cois",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0016551336",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
name: "TRAAMS",
|
|
||||||
url: "https://traams.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0028348410",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
name: "Blue orchid",
|
|
||||||
url: "https://blue-orchid.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "0034796193",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
name: "I love UFO",
|
|
||||||
url: "https://bruitblanc.bandcamp.com",
|
|
||||||
style: [0, 1, 2],
|
|
||||||
cover: "a2203158939",
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
@@ -1,16 +0,0 @@
|
|||||||
export default eventHandler(() => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 'ES00A',
|
|
||||||
name: 'zero',
|
|
||||||
duration: 2794,
|
|
||||||
description: '...',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ES00B',
|
|
||||||
name: 'zero b-sides',
|
|
||||||
duration: 2470,
|
|
||||||
description: '...',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
@@ -1,21 +0,0 @@
|
|||||||
import fs from 'fs'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
export default eventHandler(async (event) => {
|
|
||||||
const directoryPath = path.join(process.cwd(), 'media/files/music') // 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@@ -1,16 +0,0 @@
|
|||||||
export default eventHandler(() => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
"id": 0,
|
|
||||||
"name": "post-rock"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "math-rock"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"name": "indie-pop"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
@@ -1,224 +0,0 @@
|
|||||||
export default eventHandler(() => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'The grinding wheel',
|
|
||||||
artist: 0,
|
|
||||||
start: 0,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://arakirecords.bandcamp.com/track/the-grinding-wheel',
|
|
||||||
cover: 'a3236746052',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Bleach',
|
|
||||||
artist: 1,
|
|
||||||
start: 393,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://the-kundalini-genie.bandcamp.com/track/bleach-2',
|
|
||||||
cover: 'a1714786533',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Televised mind',
|
|
||||||
artist: 2,
|
|
||||||
start: 892,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://fontainesdc.bandcamp.com/track/televised-mind',
|
|
||||||
cover: 'a3772806156'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'In it',
|
|
||||||
artist: 3,
|
|
||||||
start: 1138,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://howlinbananarecords.bandcamp.com/track/in-it',
|
|
||||||
cover: 'a1720372066',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Bad michel',
|
|
||||||
artist: 4,
|
|
||||||
start: 1245,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://johnnymafia.bandcamp.com/track/bad-michel-3',
|
|
||||||
cover: 'a0984622869',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Overall',
|
|
||||||
artist: 5,
|
|
||||||
start: 1394,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://newcandys.bandcamp.com/track/overall',
|
|
||||||
cover: 'a0559661270',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Blowup',
|
|
||||||
artist: 6,
|
|
||||||
start: 1674,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://magicshoppe.bandcamp.com/track/blowup',
|
|
||||||
cover: 'a1444895293',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Guitar jet',
|
|
||||||
artist: 7,
|
|
||||||
start: 1880,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://radiomartiko.bandcamp.com/track/guitare-jet',
|
|
||||||
cover: 'a1494681687',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 9,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Intercontinental radio waves',
|
|
||||||
artist: 8,
|
|
||||||
start: 2024,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://traams.bandcamp.com/track/intercontinental-radio-waves',
|
|
||||||
cover: 'a0046738552',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 10,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Here comes the sun',
|
|
||||||
artist: 9,
|
|
||||||
start: 2211,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://blue-orchid.bandcamp.com/track/here-come-the-sun',
|
|
||||||
cover: 'a4102567047',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
compilation: 'ES00A',
|
|
||||||
title: 'Like in the movies',
|
|
||||||
artist: 10,
|
|
||||||
start: 2559,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://bruitblanc.bandcamp.com/track/like-in-the-movies-2',
|
|
||||||
cover: 'a2203158939',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 21,
|
|
||||||
compilation: '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',
|
|
||||||
cover: 'a3236746052',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 22,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Bleedin\' Gums Mushrool',
|
|
||||||
artist: 1,
|
|
||||||
start: 263,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://the-kundalini-genie.bandcamp.com/track/bleedin-gums-mushroom',
|
|
||||||
cover: 'a1714786533',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 23,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'A lucid dream',
|
|
||||||
artist: 2,
|
|
||||||
start: 554,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://fontainesdc.bandcamp.com/track/a-lucid-dream',
|
|
||||||
cover: 'a3772806156',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 24,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Lights off',
|
|
||||||
artist: 3,
|
|
||||||
start: 781,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://howlinbananarecords.bandcamp.com/track/lights-off',
|
|
||||||
cover: 'a1720372066',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 25,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'I\'m sentimental',
|
|
||||||
artist: 4,
|
|
||||||
start: 969,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://johnnymafia.bandcamp.com/track/im-sentimental-2',
|
|
||||||
cover: 'a2333676849',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 26,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Thrill or trip',
|
|
||||||
artist: 5,
|
|
||||||
start: 1128,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://newcandys.bandcamp.com/track/thrill-or-trip',
|
|
||||||
cover: 'a0559661270',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 27,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Redhead',
|
|
||||||
artist: 6,
|
|
||||||
start: 1303,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://magicshoppe.bandcamp.com/track/redhead',
|
|
||||||
cover: 'a0594426943',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 28,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Supersonic twist',
|
|
||||||
artist: 7,
|
|
||||||
start: 1584,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://open.spotify.com/track/66voQIZAJ3zD3Eju2qtNjF',
|
|
||||||
cover: 'a1494681687',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 29,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Flowers',
|
|
||||||
artist: 8,
|
|
||||||
start: 1749,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://traams.bandcamp.com/track/flowers',
|
|
||||||
cover: 'a3644668199',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 30,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'The shade',
|
|
||||||
artist: 9,
|
|
||||||
start: 1924,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://blue-orchid.bandcamp.com/track/the-shade',
|
|
||||||
cover: 'a0804204790',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 31,
|
|
||||||
compilation: 'ES00B',
|
|
||||||
title: 'Like in the movies',
|
|
||||||
artist: 10,
|
|
||||||
start: 2185,
|
|
||||||
bpm: 0,
|
|
||||||
url: 'https://bruitblanc.bandcamp.com/track/like-in-the-movies',
|
|
||||||
cover: 'a3647322740',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
})
|
|
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../.nuxt/tsconfig.server.json"
|
|
||||||
}
|
|
@@ -1,51 +0,0 @@
|
|||||||
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, // To track 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.compilation === 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)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
@@ -11,12 +11,12 @@ module.exports = {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
esyellow: '#fdec50ff',
|
esyellow: "#fdec50ff",
|
||||||
},
|
},
|
||||||
screens: {
|
screens: {
|
||||||
'2sm': '320px',
|
"2sm": "320px",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
};
|
||||||
|
@@ -1,4 +1,18 @@
|
|||||||
{
|
{
|
||||||
// https://nuxt.com/docs/guide/concepts/typescript
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
"extends": "./.nuxt/tsconfig.json"
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.server.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.shared.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./.nuxt/tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
// types.ts
|
|
||||||
export interface Compilation {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
duration: number
|
|
||||||
tracks?: Track[]
|
|
||||||
description: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Artist {
|
|
||||||
id: number
|
|
||||||
name: string
|
|
||||||
url: string
|
|
||||||
style: Array<number>
|
|
||||||
cover: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Track {
|
|
||||||
id: string
|
|
||||||
compilationId: string
|
|
||||||
title: string
|
|
||||||
artistId: number
|
|
||||||
artist?: Artist
|
|
||||||
start: number
|
|
||||||
link: string
|
|
||||||
cover: string
|
|
||||||
}
|
|