Movie Games
Um jogo de filmes multiplayer em tempo real. Os jogadores entram em salas e competem para identificar filmes em vários modos de jogo.
Bomb-It · demo
Modos de jogo
Trailer Quiz
Um trecho de trailer é reproduzido para todos na sala no mesmo instante. O primeiro a digitar o título correto vence a rodada.
Bomb-It
Um modo de sobrevivência contra o tempo: nomeie um filme que se encaixe no tema antes que o tempo acabe. Se o tempo esgotar, você perde uma vida.
Mais modos
Modos adicionais estão em desenvolvimento, incluindo jogos personalizados a partir do histórico do Letterboxd do jogador.
Funcionalidades
Salas e acesso
- Lobbies públicos
- Salas privadas com senha
- Filtros de gênero e dificuldade (1–10)
- Sessões de convidado com um clique
Social
- Lista de amigos com status online
- Mensagens diretas
- Chat da sala em tempo real
- Tabela de classificação global
Progressão
- XP, níveis e conquistas
- Pipoca (moeda do jogo)
- Loja de cosméticos — avatares, títulos, fundos
- Perfil persistente entre jogos
Pontuação
- Escala com a dificuldade e o combo de respostas
- Pontos de consolação para palpites de gêneros adjacentes
Classificação e perfis
Recreated from the in-game leaderboard — real cards, live ranking and stats. Click the card to open the profile.
Um desenvolvedor. Toda a stack.
Frontend, backend, banco de dados, pagamentos, segurança e deploy — tudo construído e publicado sozinho.
Construído com
- React
- TypeScript
- Vite
- Tailwind CSS
- react-youtube
- Node.js
- Express
- Supabase
- PostgreSQL
- JWT
- bcrypt
- node-cron
- Cloudflare
- Render
Engenharia
Salas com autoridade no servidor
A lógica do jogo roda no servidor, não no navegador. Cada sala bate em um pulso de um segundo que diz a todos os jogadores o que está acontecendo no mesmo instante — assim ninguém consegue trapacear alterando a tela e todos assistem ao mesmo ponto do trailer.
O GameManager mantém cada sala em memória e avança uma máquina de estados LOBBY → STARTING → IN_ROUND → BETWEEN_ROUNDS → FINISHED em um ciclo de setInterval de 1 segundo. Os clientes são apenas para renderização: realizam polling do estado a cada segundo e se alinham à transmissão, impedindo que um cliente adulterado altere o resultado; a resposta é omitida do payload até a fase BETWEEN_ROUNDS.
Tempo real além do polling
O modo Trailer Quiz se mantém atualizado com atualizações rápidas do servidor, mas as partes mais dinâmicas — como o chat, o envio de tomates nos outros jogadores e todo o modo Bomb-It — rodam em uma conexão direta instantânea, sem atrasos.
O Trailer Quiz em estado estável sincroniza no ciclo de 1 segundo, mas eventos sensíveis a latência usam WebSocket persistente em vez de polling: chat do lobby, reações (lançamento de tomates) e toda a dinâmica de Bomb-It (passagem de turno e cronômetro compartilhado) enviam atualizações no instante em que ocorrem.
Pipeline de middleware segregado
Toda requisição passa por uma sequência organizada de validações antes de executar — cookies e CORS, proteção contra CSRF, limites de requisições por rota, validação de formato e depois a autenticação — isolando as preocupações e bloqueando acessos inválidos logo no início.
Cada requisição percorre uma cadeia Express ordenada: cors e cookie-parser, verificação de Origin/CSRF, express-rate-limit por rota (cinco limitadores atrelados ao IP real, agrupando IPv6 em sub-redes /56), validação de schemas com sanitização contra prototype-pollution e XSS, e autenticação final. As responsabilidades são isoladas, rejeitando requisições inválidas no início da esteira.
Catálogo de filmes pré-carregado
Os trailers em vídeo não ficam salvos no servidor — o que é carregado em memória na inicialização são as informações dos filmes e os links do YouTube. Durante o jogo, o vídeo roda direto do YouTube no navegador do jogador, de forma que o servidor não gasta banda de vídeo e o jogo nunca trava esperando dados externos. A dificuldade apenas define a profundidade da busca na lista de filmes ordenados por popularidade.
Metadados de cerca de 55.000 filmes (títulos, infos e ids de trailers do YouTube) são lidos de um JSONL para a memória na inicialização e ordenados por popularidade, sem armazenamento de vídeo no servidor. A seleção por gênero filtra a base e a dificuldade delimita a busca (do top 100 no nível 1 até a base inteira no nível 10) antes de um sorteio aleatório sem repetição. O trailer é reproduzido via player do YouTube no cliente, eliminando chamadas à API do TMDB em partida.
Trailers resilientes
Se um trailer estiver fora do ar ou bloqueado para a região de alguém, o jogo não trava. O reporte de um jogador (or a troca feita pelo host) substitui o vídeo por um reserva na hora e reinicia o tempo, garantindo que ninguém perca pontos por vídeos quebrados.
Um trailer reportado ou trocado pelo host é validado contra a rodada ativa. O vídeo problemático entra em uma blacklist em memória para nunca mais ser sorteado, um trailer reserva é extraído do catálogo, a sala atualiza para ele, o tempo reinicia e os palpites feitos na rodada são limpos para não acumular no novo vídeo.
Identidade real através do proxy
O aplicativo roda por trás de camadas de hospedagem que ocultariam a origem do visitante. Um proxy inteligente preserva a identidade real de cada um, garantindo que limites de acessos e banimentos funcionem corretamente no IP certo.
Uma Cloudflare Pages Function atua como fachada para a API e encaminha cada chamada contendo o IP de conexão no cabeçalho assinado x-mtq-client-ip; o Express confia no IP encaminhado somente se a assinatura HMAC for válida. A identidade real do cliente sobrevive de forma íntegra e não-falsificável à cadeia de proxies.
Autorização imposta no servidor
O servidor é o único guardião das regras. Ele trata todas as requisições como não confiáveis: valida cada informação, verifica as origens e pode cancelar uma sessão na mesma hora. Silenciamentos, banimentos e logs de auditoria rodam no topo do sistema.
O backend conecta ao PostgreSQL usando a chave service_role do Supabase e ignora RLS, centralizando a segurança no Express. Os tokens JWT trafegam em cookies httpOnly e o middleware de autenticação verifica o session_version e o deletion_requested_at em cada rota, possibilitando a revogação instantânea de sessões ativas.
Manutenção agendada
Tarefas em segundo plano mantêm o servidor limpo e organizado por conta própria — por exemplo, limpando dados de sessões de convidados expiradas para não acumular lixo no banco.
Tarefas agendadas via node-cron executam rotinas de limpeza fora do fluxo de requisições do usuário, apagando registros de convidados com mais de 3 dias de inatividade e mantendo o consumo de memória do banco de dados otimizado.
Painel administrativo com permissões por papel
Por trás do jogo, há um painel de controle interno para a equipe gerenciar a aplicação: monitorar custos e acessos, moderar jogadores, analisar denúncias de trailers, gerenciar tarefas automáticas e ligar/desligar chaves globais (como modo de manutenção ou novas salas). O visual do painel se adapta ao cargo da pessoa — moderadores veem apenas auditorias e denúncias, enquanto administradores têm controle total, sendo cada ação registrada em log.
Console de duas colunas com abas dinâmicas (Métricas, Fila de Eventos, Usuários, Denúncias, Contatos, Logs de Chat, Controles, Logs de Acesso) cujo layout é gerado conforme as permissões do usuário, ocultando abas administrativas de moderadores simples. Os controles ativam flags globais de execução (Manutenção, Bloqueio de Cadastro, Acesso Beta, Pausar Partidas, Desativar Pagamentos, Desconectar Backend) aplicadas nas rotas do Express e conexões WebSocket; a fila gerencia eventos futuros (desbanimentos temporários, exclusões agendadas) fora do fluxo de requisição; e dados moderados são compilados lado a lado. Ações administrativas geram logs auditáveis em JSON ou CSV.
Social
Movie Games is a social game too — identity, friends, rivalry, and live in-room expression. The two panels below are real and interactive — try them.
You
You Profiles & cosmetics
Every player is a recognizable identity — a portrait, a level, an equipped title, a background and a bio that follow them across every screen.
Friends & DMs
Send and accept requests, see who’s online, and chat one-to-one in lightweight popups — friends become collectible player cards, not address-book rows.
Global leaderboard
Ranked by level with the top three highlighted gold/silver/bronze; your own row stays pinned even when you're off the visible page. Tap a row to open the profile.
Store & inventory
Earn Popcorn from matches and level-ups, then spend it on cosmetics. Rarity drives both price and prestige; equip anything you own straight from the inventory.
Achievements
Proof-of-play with progress bars and rarity badges. Unlocks grant titles, cosmetics and Popcorn — and surface as the trophy strip on your profile.
Safety & staff
Calm, visible safety tools live next to the person they affect, with separate staff controls and an official Mod Team roster so players know who represents the game.
Tem um projeto dos sonhos?
Fale-me sobre sua ideia e eu lhe enviarei um orçamento.