Sistema de cruzadinhas temáticas, open source e 100% client-side. Importe um JSON ou CSV com pares palavra → dica, gere um grid interativo e jogue no browser — sem backend, sem dependências externas além do React.
- Import flexível — JSON ou CSV com
palavra,dica - Gerador de layout — algoritmo de encaixe automático, sem dependência npm
- Grid interativo — navegação por teclado e toque, highlight da palavra ativa
- Revelar palavra aleatória — dica de socorro sem revelar tudo
- Verificação — feedback visual célula a célula (correto / errado / revelado)
- Compartilhamento por link — compressão gzip nativa (
CompressionStream), zero biblioteca - Export —
.ipuz(formato aberto) e.json(wordlist) - Progresso salvo — persiste automaticamente a cruzadinha em andamento
- Bloqueio pós-revelação — ao revelar tudo, o grid fica somente leitura
- Node.js 18+ (recomendado: 20 LTS)
- npm 9+
node -v # ex: v20.11.0
npm -v # ex: 10.2.4# 1. Clone o repositório
git clone https://github.com/seu-usuario/crossforge.git
cd crossforge
# 2. Instale as dependências
npm install
# 3. Rode o servidor de desenvolvimento
npm run devAcesse http://localhost:5173.
npm run dev # servidor de desenvolvimento com HMR
npm run build # build de produção em dist/
npm run preview # preview do build local
npm run test # roda os testes unitários uma vez
npm run test:watch # testes em modo watch
npm run test:coverage # testes com relatório de coberturacrossforge/
├── src/
│ ├── App.jsx # componente principal e telas (Import / Play)
│ ├── crossword.js # funções puras: generateLayout, parseInput,
│ │ # getWordAtCell, exportIpuz
│ └── crossword.test.js # 42 testes unitários (Vitest)
├── wordlists/ # wordlists temáticas prontas para importar
│ ├── 01_distributed_systems.json
│ ├── 02_kafka_avancado.json
│ ├── 03_jvm_internals.json
│ ├── 04_event_driven_cqrs.json
│ ├── 05_microsservicos.json
│ ├── 06_design_patterns.json
│ ├── 07_observabilidade.json
│ └── 08_concorrencia_java.json
├── .github/
│ └── workflows/
│ └── security.yml # CI: npm audit, Trivy, license check, testes
├── public/
├── index.html
├── vite.config.js
└── package.json
[
{ "word": "KAFKA", "clue": "Plataforma de streaming distribuído da Apache" },
{ "word": "BROKER", "clue": "Intermediário que roteia mensagens entre producers e consumers" },
{ "word": "TOPIC", "clue": "Canal lógico para onde as mensagens são publicadas" }
]word,clue
KAFKA,Plataforma de streaming distribuído da Apache
BROKER,Intermediário que roteia mensagens entre producers e consumers
TOPIC,Canal lógico para onde as mensagens são publicadasRegras:
| Regra | Detalhe |
|---|---|
| Caracteres | Apenas A–Z, sem espaços ou acentos |
| Comprimento | 2–18 letras (palavras maiores são ignoradas) |
| Mínimo recomendado | 8 palavras para um grid satisfatório |
| Case | Qualquer — normalizado para maiúsculo automaticamente |
O botão ↗ compartilhar gera uma URL com o puzzle encodado:
https://crossforge.app/?p=H4sIAAAAAAAAA...
O payload é comprimido com CompressionStream("gzip") nativo do browser e encodado em base64 URL-safe — zero dependência npm. Quem abre o link começa direto no jogo.
O .ipuz é um padrão aberto compatível com vários players e editores:
| Player / Editor | Suporte |
|---|---|
| Exet (web) | ✅ |
| Phil (web, open source) | ✅ |
| Crossword Compiler | ✅ |
| Across Lite | Parcial (via plugin) |
{
"ipuz": "http://ipuz.org/v1#1",
"kind": ["http://ipuz.org/crossword#1"],
"title": "Kafka Fundamentals",
"dimensions": { "width": 15, "height": 12 },
"puzzle": [["#", "1", "0", ...], ...],
"clues": {
"Across": [[1, "texto da dica"], ...],
"Down": [[2, "texto da dica"], ...]
}
}npm run test42 testes unitários cobrindo as funções puras do módulo crossword.js:
| Suite | Testes | Cobre |
|---|---|---|
parseInput |
12 | JSON array/objeto, CSV, vírgula na dica, linhas malformadas, erro |
generateLayout |
14 | Casos nulos, normalização, determinismo, grid sem linhas vazias, letras x grid |
getWordAtCell |
9 | Início/meio/fim de palavra, direções, fora do grid |
exportIpuz |
12 | Campos obrigatórios, células #, números, contagem de clues |
Thresholds de cobertura (configurados em vite.config.js):
lines: 80% · functions: 90% · branches: 75%
O workflow .github/workflows/security.yml roda automaticamente:
| Job | Trigger | O que faz |
|---|---|---|
npm-audit |
push / PR | Falha em CVEs high ou critical |
license-check |
push / PR | Bloqueia GPL/LGPL/AGPL em deps de produção |
trivy-scan |
push / PR | Scan do filesystem, sobe resultado ao Security tab |
unit-tests |
push / PR | Roda Vitest com cobertura |
dependency-updates |
toda segunda 08h | Abre/atualiza issue com deps desatualizadas |
docker compose --profile dev upAcesse http://localhost:5173. O volume monta o código local no container — edições refletem em tempo real.
docker compose --profile prod up --buildAcesse http://localhost:8080. Serve o build otimizado via nginx com cache de assets e fallback de SPA (necessário para links compartilhados com ?p=).
# Rebuild sem cache
docker compose --profile prod build --no-cache
# Rodar testes dentro do container
docker compose --profile dev run --rm app-dev npm run test
# Ver logs
docker compose --profile prod logs -fO build gera uma pasta dist/ que pode ser servida por qualquer CDN:
npm run buildGitHub Pages:
npm install --save-dev gh-pages
# package.json → adicione:
# "homepage": "https://seu-usuario.github.io/crossforge"
# "scripts": { "deploy": "gh-pages -d dist" }
npm run build && npm run deployTambém funciona com Vercel, Netlify e Cloudflare Pages sem configuração adicional.
15 pares palavra → dica por tema, focados em senioridade backend/arquitetura:
| # | Tema | Destaques |
|---|---|---|
| 01 | Distributed Systems | CAP, RAFT, PAXOS, QUORUM, BYZANTINE |
| 02 | Kafka Avançado | COMPACTION, EXACTLY-ONCE, KTABLE, SCHEMA REGISTRY |
| 03 | JVM Internals | ZGC, SHENANDOAH, SAFEPOINT, ESCAPE ANALYSIS |
| 04 | Event-Driven / CQRS | EVENTSOURCING, OUTBOX, SAGA, PROJECTION |
| 05 | Microsserviços | SIDECAR, CIRCUITBREAKER, STRANGLER, SERVICEMESH |
| 06 | Design Patterns GoF | Todos os 23 padrões com dicas em PT-BR |
| 07 | Observabilidade | OPENTELEMETRY, SPAN, EXEMPLAR, CARDINALITY |
| 08 | Concorrência Java | VIRTUAL THREADS, STRUCTURED CONCURRENCY, CAS |
- Suporte a acentos e ç (normalização automática)
- AI Theme Wizard — informar tema, IA gera os pares
- Export para PDF imprimível
- Modo estudo — ao errar, exibe a dica expandida
- Timer e pontuação
- Temas visuais (light mode, alto contraste)
- Suporte ao formato
.puz(Across Lite) - Multiplayer / backend opcional
Settings → Pages → Source → GitHub Actions
No workflow .github/workflows/deploy.yml, ajuste a variável conforme seu caso:
VITE_BASE_URL: /crossforge/ # se o repo se chama crossforge
VITE_BASE_URL: / # se usar domínio customizadogit push origin mainO pipeline roda automaticamente:
quality-gate (testes + audit)
↓
build (npm run build + upload artifact)
↓
deploy-pages (GitHub Pages)
↓ (paralelo, se DOCKER_ENABLED=true)
docker (build + push para Docker Hub)
Em Settings → Secrets and variables → Actions:
| Secret | Valor |
|---|---|
DOCKERHUB_USERNAME |
seu usuário no Docker Hub |
DOCKERHUB_TOKEN |
Access Token (não a senha) |
E em Settings → Variables:
| Variable | Valor |
|---|---|
DOCKER_ENABLED |
true |
- Fork o repositório
- Crie uma branch:
git checkout -b feat/minha-feature - Rode os testes:
npm run test - Abra um PR — o CI verifica segurança, licenças e testes automaticamente
MIT — use, fork, contribua.