Backend NestJS + TypeScript do Carti Visual Archive.
Este projeto faz parte de um site de fa em homenagem ao Playboi Carti. Ele nao e oficial, nao representa o artista, gravadora ou equipe, e existe como experimento visual, tecnico e musical.
Frontend: https://github.com/teuzowebdeveloper9/carti-front
Backend: https://github.com/teuzowebdeveloper9/carti-back
O backend e a camada de dados e sincronizacao musical da experiencia:
- le as musicas locais durante o script de sync;
- envia audio para a Mistral para transcricao;
- estrutura letras sincronizadas no formato usado pelo front;
- salva o acervo no Supabase;
- expoe
GET /api/musicspara o front; - monta URLs publicas de audio via
MUSIC_PUBLIC_BASE_URL; - serve
/media/musicapenas como fallback local.
No deploy atual, os MP3 ficam como assets estaticos no frontend. O backend retorna as URLs publicas desses assets para o player.
O modulo de musicas segue Ports and Adapters:
src/musics/
musics.controller.ts # adapter HTTP NestJS
musics.module.ts # composition root do modulo
application/
musics.service.ts # caso de uso: listar musicas prontas
ports/
audio-url.port.ts # porta para resolver URL de audio
music-repository.port.ts # porta para buscar musicas
adapters/
supabase-music.repository.ts # adapter Supabase
env-audio-url.resolver.ts # adapter de URL publica/fallback localRegras:
- controller nao instancia service manualmente;
- service depende de interfaces/ports, nao de Supabase diretamente;
- adapters conhecem detalhes de infra;
- mapeamento de resposta fica centralizado no caso de uso;
- variaveis de ambiente ficam isoladas em adapters/config.
GET /api/health
GET /api/musicsResposta principal:
{
"musics": [
{
"id": "uuid",
"title": "Playboi Carti - Magnolia",
"duration": "3:24",
"durationSeconds": 204,
"audioUrl": "https://carti-front.vercel.app/musics-carti/...",
"lyrics": [
{
"time": "0:05",
"phrase": "..."
}
]
}
]
}Local:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
MISTRAL_API_KEY=your-mistral-key
MISTRAL_TRANSCRIPTION_MODEL=voxtral-mini-latest
MISTRAL_STRUCTURING_MODEL=mistral-small-latest
PORT=3000
CORS_ORIGIN=http://localhost:5173
CORS_CREDENTIALS=false
MUSIC_DIR=../musics-carti
MUSIC_PUBLIC_BASE_URL=http://localhost:5173/musics-cartiVercel:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
CORS_ORIGIN=https://carti-front.vercel.app
CORS_CREDENTIALS=false
MUSIC_PUBLIC_BASE_URL=https://carti-front.vercel.app/musics-cartiUse as variaveis da Mistral no deploy apenas se for rodar sync/transcricao nesse ambiente.
npm install
npm run start:dev
npm run sync:musics
npm run typecheck
npm run build
npm run start:prodsync:musics le MP3 locais, transcreve/estrutura com Mistral e grava no Supabase.
Antes do primeiro sync, rode a migration:
supabase/migrations/202605140001_create_musics.sqlOu defina SUPABASE_DB_URL e rode npm run sync:musics; o script tenta garantir o schema automaticamente.
- Configure as envs do backend na Vercel.
- Garanta que o frontend ja esta deployado com os MP3 em
/musics-carti. - Defina
MUSIC_PUBLIC_BASE_URL=https://carti-front.vercel.app/musics-carti. - Redeploy do backend.
- Teste
https://carti-back.vercel.app/api/musics.
Se audioUrl vier como /media/music/..., a env MUSIC_PUBLIC_BASE_URL nao foi aplicada no backend.