Caution
Este projeto está em desenvolvimento ativo e não é utilizável em produção. A reescrita está em andamento in-place: funcionalidades descritas abaixo podem estar parcialmente implementadas, atrás de stubs, ou ainda não existirem. Veja Estado atual antes de assumir qualquer comportamento.
- Introdução
- Estado atual
- Stack
- Rodando
- Como usar o Hub — operação, Planilha, mídia e atalhos
- Estrutura do projeto
- Contribuir
O FORJA Hub é o launcher desktop de jogos da FORJA Game Studio para estações de eventos ao estilo Steam Big Picture, pensado para funcionar em estações com múltiplos periféricos e sem depender de internet estável.
Este README documenta o que existe e funciona agora, não a visão final do produto.
Para operar o Hub numa estação de evento (configuração, Planilha de Catálogo, mídia no Drive e atalhos), veja Como usar o FORJA Hub.
O que já está implementado e testado:
- Catálogo sincronizado com Google Sheets + Drive: no boot, o main lê a
aba
JOGOSda Planilha de Catálogo, valida cada linha com Zod e baixa a mídia de cada Jogo da pasta do Drive. - Cache offline: o catálogo validado (
catalog.json+ mídia) é gravado emuserData/catalog/current/por troca atômica de diretório. - Setup de estação: na primeira execução, a
SetupScreenlista os Jogos do catálogo para escolher quais a estação exibe, e gravastation.jsoncom escrita atômica. Se nenhum Jogo selecionado existir mais no catálogo, o Hub volta para o setup. - Tela de catálogo (kiosk): vitrine com arte-herói do Jogo em foco, logo com fallback para o título, chips de ano, guilda e gênero, e uma fileira rolável de cards com navegação circular (o foco dá a volta), por controle, teclado ou mouse, com faíscas e um clique sonoro sintetizado a cada troca de foco. Só os Jogos selecionados na estação aparecem.
- Base de input: captura de teclado e gamepad (XInput) no renderer, com guarda para não interceptar teclas quando um elemento editável está focado, e cursor que some quando fica parado.
- Launcher de processo: módulo no main para abrir executáveis locais e monitorar o fechamento (evento de saída do processo ou polling por nome do processo alvo).
- JOGAR: o renderer pede
game:launch, o main resolve o executável emuserData/games/<id>/, abre pelo launcher de processo, recolhe a janela ~1,5s depois e a recria quando o Jogo fecha, voltando ao card jogado. O selo QR das redes do Jogo é gerado no main (qrcode) e servido porforja://media/<id>/qr.
O que ainda não existe:
- Download e extração do
.zipdo Jogo: o build entra à mão, em<userData>/games/<id>/(veja Instalando um Jogo à mão). - Modo atração, painel do operador (
Ctrl+Shift+Osó troca para um placeholder), busca e filtros. - Analytics de sessão (tempo de jogo, visualizações).
- Empacotamento e instalador testados para Windows (alvo principal).
O Hub não baixa builds (no momento): coloque os arquivos do Jogo em games/<id>/ dentro do userData da estação — ~/.config/forja-hub/games/<id>/ no Linux e
%APPDATA%\forja-hub\games\<id>\ no Windows, sendo <id> o id do Jogo na
Planilha.
Com exe_relativo preenchido na Planilha, é esse o executável aberto, sempre
confinado à pasta do Jogo (aceita sub/pasta/Jogo.exe, com / ou \).
Vazio, o Hub procura sozinho até 2 níveis abaixo da pasta do Jogo: no Windows,
o único .exe; nas outras plataformas, o único arquivo com permissão de
execução (fora bibliotecas .so, .so.N e .dylib). Auxiliares conhecidos
(unins000, UnityCrashHandler*, crashpad_handler, notification_helper,
vc_redist*, dxsetup, UE4PrereqSetup* e o *.console do Godot) são
ignorados. Sem candidato ou com mais de um, o JOGAR falha e o motivo vai para o
log do main; o exe_relativo é quem desempata.
- Electron + electron-vite
- React 19 + TypeScript
- Tailwind CSS v4
- googleapis (Sheets + Drive via Service Account) e Zod para validar o catálogo
- Vitest para os testes
- electron-builder — empacotamento (ainda não validado em Windows)
Pré-requisitos: Node.js 20.19+ ou 22.12+ (exigência do Vite 7; a CI usa Node 22).
npm install
cp .env.example .env # preencha os IDs, veja docs/USO.md
npm run devSem essa configuração o Hub abre, mas o sync aborta e a tela mostra o erro
(CATALOGO_NAO_CONFIGURADO ou CREDENCIAL_AUSENTE). É configuração faltando,
não bug.
Important
npm run dev não roda typecheck — só npm run build roda. Rode lint
e typecheck manualmente antes de abrir um PR:
npm run lint
npm run typecheckIsso também roda automaticamente: um git hook local (.githooks/pre-push,
ativado via npm install) bloqueia o push se lint ou typecheck
falharem, e o CI no GitHub Actions roda a
mesma verificação em cada push de branch e PR para a main.
Outros scripts úteis:
npm test: roda os testes (Vitest). O hookpre-pushe a CI não rodam os testes, então rode antes de abrir um PR.npm run build: typecheck + build de produção via electron-vite.npm start: abre o build de produção (electron-vite preview).npm run build:unpack: build + app desempacotado (sem instalador).npm run build:win/build:mac/build:linux: empacotamento via electron-builder (Windows é o alvo real; os demais não foram validados em estação de evento).
O desenvolvimento acontece em Linux, mas o alvo principal é Windows, pois a
maioria dos jogos distribuídos pela FORJA é Windows-only. No Windows o
launcher detecta o processo do Jogo com tasklist; no Linux usa pgrep -x
só para permitir rodar em dev. Detecção de fechamento do executável e tempo
de sessão só valem como validados depois de testados numa estação Windows.
ForjaHUB/
├── src/
│ ├── main/
│ │ ├── catalog/ # Sync Sheets/Drive, schema, cache, boot, protocolo forja://
│ │ ├── config/ # IDs da Planilha/Drive e handlers IPC de setup/hydrate
│ │ ├── store/ # station.json e escrita atômica (arquivo e diretório)
│ │ ├── launcher/ # Spawn e monitoramento de processo do Jogo
│ │ └── index.ts # Janela kiosk, protocolo, IPC e atalhos
│ ├── preload/ # contextBridge / ponte forjaAPI
│ ├── renderer/src/
│ │ ├── design/ # Tokens, fontes e primitivos visuais
│ │ ├── screens/ # setup, catalog, detail
│ │ ├── input/ # Teclado, gamepad e foco
│ │ └── state/ # Reducer da aplicação
│ └── shared/ # Tipos, canais IPC, forjaAPI e mediaUrl
├── public/ # Assets do renderer (logo, favicon)
├── resources/ # Assets fora do build do renderer (hoje não referenciados no código)
└── build/ # Ícones e configuração de empacotamento
Assets do renderer ficam em public/ e são referenciados via
import.meta.env.BASE_URL (o build empacotado abre via file://).
- Nunca commitamos direto na
main. Todo trabalho vai em branches. - Commits são atômicos (um por mudança lógica).
- Rode
npm run lint,npm run typecheckenpm testantes de abrir um PR. Lint e typecheck são reforçados automaticamente: o hookpre-pushbloqueia o push se algum dos dois falhar, e a CI roda a mesma checagem em cada push de branch e PR para amain. Os testes não rodam em nenhum dos dois.
Uso interno — FORJA Game Studio / CESAR.