Cronômetro sincronizado em tempo real com painel de admin, tela pública de viewer e visão geral das sessões online.
O projeto permite:
- criar uma sessão de cronômetro
- controlar o tempo por uma tela de admin
- compartilhar um link de viewer para acompanhar a contagem em tempo real
- salvar presets localmente no navegador do admin
- acompanhar e finalizar sessões ativas em um painel geral
- Node.js
- Express
- Socket.IO
- Helmet
- express-rate-limit
- HTML, CSS e JavaScript sem framework
.
|-- public/
| |-- index.html
| |-- admin.html
| |-- overview.html
| |-- viewer.html
| `-- assets/
| |-- audio/
| | `-- trompeta.mp3
| |-- css/
| | |-- index.css
| | |-- admin.css
| | |-- overview.css
| | `-- viewer.css
| `-- js/
| |-- crono-utils.js
| |-- index.js
| |-- admin.js
| |-- finish-sound.js
| |-- overview.js
| `-- viewer.js
|-- scripts/
|-- test/
| |-- security.test.js
| `-- sessions.test.js
| |-- deployer.js
| `-- webhook-deploy.sh
|-- src/
| |-- config.js
| |-- deploy-client.js
| |-- logger.js
| |-- security.js
| `-- sessions.js
|-- server.js
|-- Dockerfile
|-- docker-compose.yml
|-- .env.example
|-- .gitignore
|-- .dockerignore
|-- package.json
`-- package-lock.json
server.js: configura Express, segurança, rotas HTTP, Socket.IO e CSP.src/config.js: centraliza variáveis de ambiente e valores padrão.src/sessions.js: guarda sessões em memória e concentra regras do cronômetro.src/security.js: valida origem, tokens e assinatura do webhook.src/logger.js: registra acessos e eventos do app.src/deploy-client.js: dispara o serviço opcional de deploy.
public/index.html+assets/js/index.js: cria uma nova sessão.public/admin.html+assets/js/admin.js: controla tempo, presets, fullscreen e link do viewer.public/viewer.html+assets/js/viewer.js: mostra a contagem sincronizada sem controles.public/overview.html+assets/js/overview.js: lista sessões ativas e permite finalizar sessões.assets/js/finish-sound.js: encapsula o som final do cronômetro.assets/js/crono-utils.js: utilidades compartilhadas (window.CronoUtils) de formatação de tempo, sanitização e validação, usadas por admin, viewer e overview.
Cada tela possui um CSS próprio para evitar acoplamento visual excessivo:
index.css: tela inicial.admin.css: painel de controle e drawer mobile.viewer.css: tela pública de contagem.overview.css: painel geral de sessões.
O padrão visual atual é dark glass: fundos escuros, bordas translúcidas, blur e acentos em verde/azul.
- Node.js 20+
- npm
- Instale as dependencias:
npm ci- Crie um arquivo
.enva partir do exemplo:
cp .env.example .envNo Windows PowerShell:
Copy-Item .env.example .env- Inicie o servidor:
npm start- Acesse:
http://localhost:3000
Build da imagem:
docker build -t cronometro-sync .Subindo com Compose:
docker compose up --buildPor padrão, o docker-compose.yml expõe a aplicação apenas em:
http://127.0.0.1:3000
- Abra a página inicial.
- Clique em
Criar cronômetro. - Você será redirecionado para a URL de admin da sessão.
- Use o link de viewer exibido no painel para compartilhar a visualização.
- Abra
/overviewpara ver e finalizar sessões ativas.
Observação:
- a URL de admin inclui um token no hash para autenticar a sessão de controle
- a URL de viewer não inclui permissão de admin
- o arquivo de som final deve ficar em
public/assets/audio/trompeta.mp3
As variáveis atuais são:
| Variável | Obrigatória | Descrição |
|---|---|---|
PORT |
não | Porta HTTP da aplicação |
NODE_ENV |
não | Ambiente de execução |
APP_ORIGIN |
recomendado | Origem permitida para conexões e uso do app |
HOST_REPO_PATH |
sim, se auto-deploy ativado | Caminho absoluto do repo no host |
ENABLE_WEBHOOK |
não | Ativa o endpoint /webhook |
WEBHOOK_SECRET |
sim, se webhook ativado | Segredo para validar assinatura do webhook |
WEBHOOK_DEPLOY_BRANCH |
não | Branch aceito para o auto-deploy |
DEPLOYER_TIMEOUT_MS |
não | Timeout para disparar o serviço de deploy |
SESSION_TTL_MINUTES |
não | Tempo de vida das sessões em memória |
SESSION_CLEANUP_MINUTES |
não | Intervalo de limpeza das sessões expiradas |
TRUST_PROXY |
não | Ativa trust proxy no Express |
| Método | Rota | Descrição |
|---|---|---|
GET |
/ |
Página inicial |
POST |
/api/session/new |
Cria uma nova sessão |
GET |
/api/sessions/active |
Lista sessões ativas |
DELETE |
/api/sessions/:id |
Finaliza uma sessão |
GET |
/admin/:id |
Painel de admin |
GET |
/overview |
Painel com todos os cronômetros ativos |
GET |
/view/:id |
Tela de viewer |
GET |
/health |
Healthcheck simples |
POST |
/webhook |
Endpoint opcional de webhook |
npm run check
npm test
npm audit --audit-level=moderateOs testes usam o runner nativo do Node (node --test), sem dependências
extras, e cobrem src/security.js e src/sessions.js.
O projeto já inclui algumas medidas de endurecimento:
- token de admin por sessão
- validação de
sessionId, token e payloads recebidos Helmetcom CSP e headers de segurança- rate limit global, para criação de sessão e para webhook
- validação de assinatura no webhook
- restrição de origem para conexões do Socket.IO
- expiração automática de sessões em memória
- limite máximo de tempo configurável no servidor
- frontend sem
onclickinline nem scripts embutidos, o que permite CSP mais forte - serviço principal do app rodando como usuário não-root no Compose
docker-compose.ymlcomread_only,tmpfs,cap_dropeno-new-privileges
Alguns pontos importantes para considerar antes de produção mais séria:
- as sessões ficam apenas em memória e somem ao reiniciar o processo
- os presets ficam em
localStorageno navegador do admin - não existe banco de dados
- não existe painel de usuários nem autenticação tradicional
- o deploy automatico continua exigindo um sidecar com acesso ao Docker socket do host
- não commitar
.env - não remover
.gitignorenem.dockerignore - prefira
npm ciem vez denpm install - use
APP_ORIGINcorretamente no ambiente onde for publicar - deixe
ENABLE_WEBHOOK=falsese você não estiver usando webhook
- mover sessão para Redis ou banco
- ampliar a cobertura de testes (eventos de socket e fluxo de deploy)
- criar pipeline de deploy fora da aplicação
- adicionar observabilidade e logs estruturados