Site oficial do Mais Dezoito Cult Club & Swing (Florianópolis/SC).
- Astro 6 (build estático) —
npm run build→dist/ - Vue 3.5 em ilhas (
client:visible) para galeria e modais - Tailwind CSS 4 (via
@tailwindcss/vite) - Content Collections com schema Zod
- TypeScript strict
npm install # uma vez
npm run dev # http://localhost:4321
npm run build # gera ./dist (estático, pronto para upload)
npm run preview # serve ./dist em http://localhost:4321
npm run check # type check + diagnosticssrc/
├── pages/ → rotas (Home, A Casa, Eventos, Regras&Valores, Contato, 404)
├── layouts/ → BaseLayout (head, header, footer, FAB WhatsApp)
├── components/ → Astro + Vue (HeroVideo, EventCard, RoomGallery.vue, etc.)
├── content/ → markdown (events/, rooms/) + pricing.json
├── content.config.ts → schemas Zod das collections
├── lib/ → site (constantes), whatsapp (helpers wa.me)
└── styles/ → global.css com tokens Tailwind v4 (@theme)
public/
└── images/ → placeholders SVG (substituir por fotos reais antes do go-live)
Cada evento tem capa + vídeo + descrição. Convenções:
- Arquivo:
src/content/events/AAAA-MM-DD-slug.md - Capa:
public/images/eventos/AAAA-MM-DD-slug.jpeg(versionada) - Vídeo:
public/videos/<slug>.mp4(gitignored, só dev local; em produção é hospedado no servidor)
Use src/content/events/2026-04-25-sabado-xeque-mate.md como template completo (lineup, tickets agrupados por tier, videoUrl).
---
title: Nome do Evento
subtitle: Subtítulo opcional
date: 2026-05-17
time: 23:00 às 06:00
cover: /images/eventos/2026-05-17-meu-evento.jpeg
excerpt: Descrição curta para card e meta description.
featured: true
ctaText: Garantir ingresso
videoUrl: /videos/meu-evento.mp4
lineup:
- "DJ Fulano"
tags: ["destaque"]
tickets:
- label: "Ingressos · Loja oficial"
url: "https://loja.infinitepay.io/karoline-wiggers"
description: "Garanta seu ingresso na loja oficial."
---
Conteúdo livre em markdown.Quando o usuário coloca um .mp4 na raiz do projeto (ex: WhatsApp):
# 1) Inspecionar frames (1 por segundo)
ffmpeg -y -i "video.mp4" -vf "fps=1" /tmp/frames/f%02d.jpg
# 2) Salvar capa definitiva (geralmente o primeiro frame tem o flyer)
ffmpeg -y -ss 0 -i "video.mp4" -frames:v 1 -q:v 2 \
"public/images/eventos/AAAA-MM-DD-slug.jpeg"
# 3) Copiar o vídeo para public/videos/ (gitignored, dev local)
cp "video.mp4" "public/videos/<slug>.mp4"O auto-deploy via GitHub reescreve public_html/ no Hostinger a cada push em main. Por isso public/videos/*.mp4 não é versionado — os arquivos vivem no servidor e são enviados manualmente após cada deploy:
git push # dispara o deploy
# ... aguardar o deploy concluir em hpanel.hostinger.com ...
npm run upload-video -- public/videos/<slug>.mp4 <slug> # SCP do .mp4Entre o deploy e o upload o vídeo retorna 404 — comportamento aceito.
Vídeos têm TTL de 20 dias (configurado em src/lib/video.ts). Após o TTL:
- O componente da página de evento para de renderizar o
<video>automaticamente (não fica link quebrado). - Para apagar os arquivos do servidor:
npm run prune-videos # default = VIDEO_TTL_DAYS dias
npm run prune-videos -- 30 # passa explicitamente
npm run prune-videos -- 20 --dry-runssh -p 65002 u755580152@147.79.94.37 # chave já configuradaDiretório dos vídeos no servidor: domains/mdcultclub.com.br/public_html/videos/.
Depois npm run build valida o schema.
Editar src/content/pricing.json.
Editar src/lib/site.ts.
- Logo final em SVG/PNG →
public/images/logo.svg - Foto poster do hero (jpg, 1920×1080) →
public/images/hero-poster.jpge atualizarsite.ts - URL real do vídeo YouTube →
site.ts > heroVideo.youtubeId - Nº WhatsApp oficial →
site.ts > whatsapp.number - Imagem OG padrão (1200×630) →
public/images/og-default.jpg - Fotos reais dos ambientes → substituir
/images/placeholder-room-*.svg - Cartazes reais dos eventos → substituir
/images/placeholder-event-*.svg - Definir e comprar domínio → atualizar
site.urlemsrc/lib/site.tseastro.config.mjs - Configurar deploy GitHub Actions → Hostinger