Produto da operação ialk.com.br. Rede social esportiva onde a reputação competitiva do atleta é real, confiável e portável. Cruza três DNAs: feed social (estilo Strava), rating competitivo confiável (estilo DUPR) e desafios em grupo com prazo (estilo Gym Rats).
Código-fonte: /var/www/src/ranklevel/ · Domínio do produto: ranklevel.app.br
Status: Marco 0 (Fundação) em andamento. Monorepo scaffoldado, infra operacional, blog/admin/APIs rodando em produção.
RankLevel não é "um sistema que ranqueia atletas" — é uma rede onde o número competitivo de cada atleta significa algo e o acompanha aonde quer que ele compita. O produto se sustenta em três pilares, nesta ordem de prioridade para o lançamento:
A dependência é real: o número sustenta o social, que sustenta o desafio. Por isso a construção segue essa ordem.
| Campo | Valor |
|---|---|
| Domínio público | ranklevel.app.br |
| Código-fonte | /var/www/src/ranklevel/ |
| Banco app | Postgres 16 via Docker — porta 5436 — container ranklevel-db |
| Banco blog | MySQL 8 via Docker — porta 3308 — container ranklevel-blog-db |
| Auth | auth.ialk.com.br centralizado (padrão da operação) |
| Storage | storage.ialk.com.br (padrão da operação) |
| Tipo de app | Mobile + Web, offline-first com sincronia + realtime |
| Subdomínio | Tipo | Porta/Diretório |
|---|---|---|
ranklevel.app.br |
Landing page (estática) | /var/www/html/ranklevel |
admin.ranklevel.app.br |
Admin panel (Angular 19) | /var/www/html/ranklevel-admin |
api.ranklevel.app.br |
API principal (Express) | PM2 ranklevel-api porta 3070 |
blog.ranklevel.app.br |
Blog público (Astro 5) | /var/www/html/ranklevel-blog |
blog-admin.ranklevel.app.br |
Blog admin (Angular 19) | /var/www/html/ranklevel-blog-admin |
api.blog.ranklevel.app.br |
Blog API (Express+MySQL) | PM2 ranklevel-blog-api porta 3071 |
vault.ranklevel.app.br |
Vault viewer (ialk-vault) | PM2 ranklevel-vault porta 3072 |
Herda a stack padrão da operação ialk.com.br, com uma exigência específica que pesa na escolha do frontend: offline-first.
| Camada | Tecnologia | Notas |
|---|---|---|
| Runtime | Node 20 | LTS, padrão da operação |
| API principal | Express 4 + Zod | porta 3070, Postgres |
| API blog | Express 5 + MySQL | porta 3071, copiada do CAP |
| ORM (app) | Prisma | migrations versionadas |
| ORM (blog) | queries manuais (mysql2) | padrão herdado do CAP |
| Banco app | Postgres 16 | Docker porta 5436 |
| Banco blog | MySQL 8 | Docker porta 3308 |
| Auth | auth.ialk.com.br |
centralizado + dual-token + RBAC |
| Admin | Angular 19 | copiado do CAP, identidade dark+azul |
| Blog | Astro 5 | copiado do CAP, identidade dark+azul |
| Blog admin | Angular 19 | copiado do CAP, identidade dark+azul |
| App | Mobile + Web | offline-first obrigatório — a construir |
| Monorepo | Nx + pnpm | workspace do produto |
| Deploy | Docker Compose + PM2 + Nginx | padrão da operação |
ranklevel/
├── apps/
│ ├── admin/ # Angular 19 — painel administrativo
│ ├── api/ # Express 4 — API principal (Postgres)
│ ├── api-blog/ # Express 5 — API do blog (MySQL)
│ ├── blog/ # Astro 5 — blog público
│ └── blog-admin/ # Angular 19 — painel do blog
├── packages/
│ ├── prisma-app/ # Schema Prisma (Postgres)
│ └── shared-types/ # Tipos compartilhados
├── docker/
│ └── docker-compose.yml # Postgres 16 + MySQL 8
├── vault/ # Documentação do projeto
├── ecosystem.config.cjs # PM2 (3 processos)
├── package.json
├── nx.json
└── pnpm-workspace.yaml
A escolha exata da tecnologia de frontend/sincronia para o app principal é a primeira decisão técnica pendente, porque offline-first influencia o schema (tipo de ID, estrutura de sync).
O projeto roda como três trilhas paralelas, conectadas por um contrato bem definido.
| Trilha | O que é | DNA dominante |
|---|---|---|
| Plataforma Central | Backend e domínio: dados, regras, validação, API, admin. O coração sem rosto. | — |
| Aplicativo | A experiência: feed, perfil, desafios, offline-first. O que o usuário toca. | Strava / Gym Rats |
| Motor de pontuação | Caixa preta isolada que calcula o número. Plugável, adiado. | DUPR |
O contrato é o que destrava o paralelismo: entra um insumo de avaliação → sai um número (+/-). O núcleo só recebe e acumula; nunca calcula. Ver decisoes/03-motor-caixa-preta.md.
O atleta tem um rating por modalidade (não um número único global). Cada dimensão é uma forma de agregar e exibir os scores já calculados:
| Dimensão | Descrição |
|---|---|
| Global | todos os atletas de uma modalidade |
| Por academia | ranking da instituição |
| Por grupo | criado livremente por usuários |
| Por evento | ranking próprio de cada evento |
Região não é dimensão de ranking nem dado no sistema — é só critério do proprietário para escolher onde firmar parcerias. Ver
decisoes/07-operacional-e-lancamento.md.
| Arquivo | Tema |
|---|---|
decisoes/_index.md |
Visão geral de todas as decisões fechadas |
decisoes/01-visao-e-dnas.md |
Visão de produto e prioridade dos três DNAs |
decisoes/02-entidades-e-ranking.md |
Entidades centrais e as 4 dimensões de ranking |
decisoes/03-motor-caixa-preta.md |
Motor desacoplado, rating por modalidade, contrato |
decisoes/04-validacao-resultados.md |
Os dois mundos: arbitrado e avulso; ciclo de vida do resultado |
decisoes/05-social-desafios-monetizacao.md |
Feed, conexões, desafios, monetização |
decisoes/06-app-offline-realtime.md |
Offline-first, sincronia, realtime |
decisoes/07-operacional-e-lancamento.md |
Perfil vs conta, reversão, admin, importação, lançamento regional |
| Arquivo | Tema |
|---|---|
cronograma/_index.md |
Marcos e frentes com status |
cronograma/frente-plataforma.md |
Trilha 1 — backend, dados, validação, admin |
cronograma/frente-aplicativo.md |
Trilha 2 — feed, perfil, desafios, offline-first |
cronograma/frente-motor.md |
Trilha 3 — contrato e motor (caixa preta) |
cronograma/frente-importacao.md |
Importação de resultados de parceiros |
CHANGELOG.md |
Registro diário de progresso |
| Arquivo | Tema |
|---|---|
docs/specs/ciclo-de-vida-resultado.md |
Especificação do ciclo de validação e reversão |
docs/specs/contrato-motor.md |
Especificação do contrato da caixa preta |
deletedAt), nunca deletar fisicamente — alinhado com a filosofia auditável do score do RankLevel.uuid via @default(uuid()).kebab-case, classes em PascalCase, variáveis em camelCase.feat/*/fix/* → staging → master.auth.ialk.com.br; storage em storage.ialk.com.br.