O ProgrideMine é uma aplicação web para acompanhar uma jornada de progressão no Minecraft. Os objetivos são organizados em fases, desde a exploração inicial até atividades de pós-jogo, com recursos para marcar tarefas, personalizar conteúdos e acompanhar o progresso total.
O projeto começou como uma aplicação front-end com persistência exclusiva no localStorage. Posteriormente, foi evoluído para usar autenticação, autorização e persistência remota com Supabase, mantendo o funcionamento original da interface e adicionando acesso público somente para leitura.
Aplicação publicada:
https://progridemine.vercel.app
Repositório:
https://github.com/feefsan/ProgrideMine
O projeto foi desenvolvido para resolver três necessidades principais:
- Organizar uma jornada de progressão no Minecraft em etapas compreensíveis.
- Permitir que usuários autorizados personalizem e sincronizem a própria jornada.
- Disponibilizar uma versão pública da jornada sem conceder permissões de alteração aos visitantes.
Além do uso prático, o projeto serviu como exercício de evolução arquitetural, integração entre front-end e Backend as a Service, autenticação, autorização, segurança de dados e publicação contínua.
- Organização dos objetivos em cinco fases.
- Marcação de objetivos como concluídos.
- Cálculo automático do percentual de progresso.
- Contagem de objetivos concluídos, totais, personalizados e editados.
- Indicador visual de conclusão por fase.
- Reinicialização do progresso sem excluir personalizações.
- Criação de objetivos personalizados.
- Edição de objetivos padrão e personalizados.
- Exclusão de objetivos personalizados.
- Criação de subtópicos a partir de linhas iniciadas por
-,*ou•. - Reordenação de objetivos por drag-and-drop dentro de cada fase.
- Login por e-mail e senha com Supabase Auth.
- Persistência da sessão no navegador.
- Restauração automática de uma sessão válida.
- Logout pela interface.
- Autorização adicional por UUID na tabela
app_users. - Limite de dois usuários autorizados por instalação.
- Cadastro público desabilitado.
- Login anônimo do Supabase desabilitado.
- Entrada sem login.
- Visualização da jornada marcada como pública.
- Ausência de conta anônima no Supabase.
- Bloqueio dos controles de edição.
- Checkboxes desabilitados.
- Alças de reordenação ocultas.
- Botões de adicionar, editar, excluir e reiniciar ocultos.
- Proteção real contra escrita por meio de Row Level Security.
- Persistência remota no PostgreSQL do Supabase.
- Indicador de estado da sincronização.
- Salvamento com debounce para agrupar alterações rápidas.
- Uso de
upsertpara criar ou atualizar o estado do usuário. - Migração inicial dos dados existentes no
localStoragequando ainda não há estado remoto. - Controle para publicar ou ocultar a jornada.
- HTML5
- CSS3
- JavaScript com ES Modules
- SVG para os ícones da interface
- Web Storage API para migração e compatibilidade com a versão local
- Drag and Drop API
- Supabase Auth
- PostgreSQL gerenciado pelo Supabase
- Supabase JavaScript Client
- Row Level Security
- Funções SQL
- Triggers PostgreSQL
- Colunas JSONB para armazenamento do estado
- GitHub para versionamento
- Vercel para hospedagem e deploy contínuo
A aplicação utiliza módulos JavaScript com responsabilidades separadas:
Navegador
|
|-- index.html
| Estrutura global, tela de acesso e barra de progresso
|
|-- css/styles.css
| Identidade visual, responsividade e estados da interface
|
|-- js/main.js
| Eventos, autenticação e coordenação do fluxo
|
|-- js/ui.js
| Renderização das fases, objetivos e estatísticas
|
|-- js/state.js
| Estado em memória e regras de alteração
|
|-- js/storage.js
| Persistência local e remota
|
|-- js/supabase.js
| Cliente, sessão, login, logout e autorização
|
|-- js/data.js
| Fases e objetivos padrão
|
`-- Supabase
|-- Auth
|-- PostgreSQL
`-- Row Level Security
Login
-> Supabase Auth
-> verificação em app_users
-> carregamento do estado do proprietário
-> edição habilitada
-> persistência no Supabase
Continuar sem login
-> consulta da jornada pública
-> modo somente leitura
-> edição desabilitada
-> RLS bloqueia operações de escrita
O estado principal é dividido em quatro objetos:
{
progress: {},
custom: {},
order: {},
overrides: {}
}progress: registra os identificadores dos objetivos concluídos.custom: armazena objetivos criados pelo usuário, agrupados por fase.order: armazena a ordem personalizada dos objetivos de cada fase.overrides: armazena alterações realizadas em objetivos padrão.
Essa estrutura preserva os dados estáticos no código e grava no banco apenas o progresso e as diferenças criadas por cada usuário.
Controla quais usuários autenticados podem editar a aplicação.
Campos principais:
user_id: UUID correspondente aauth.users.id.display_name: nome de exibição.created_at: data de autorização.
Um trigger impede que mais de dois usuários sejam adicionados à tabela.
Armazena o estado individual da jornada.
Campos principais:
user_id: proprietário do estado.progress: progresso em JSONB.custom: objetivos personalizados em JSONB.item_order: ordem dos objetivos em JSONB.overrides: alterações dos objetivos padrão em JSONB.is_public: define se visitantes podem consultar a jornada.updated_at: data da última atualização.
A aplicação aplica segurança em duas camadas.
O modo visitante define a aplicação como somente leitura e remove ou desabilita os controles responsáveis por alterações.
As políticas de Row Level Security garantem que:
- Visitantes consultem apenas registros com
is_public = true. - Visitantes não possam inserir, editar ou excluir dados.
- Usuários autenticados leiam e alterem somente o próprio estado.
- Um usuário autenticado também precise estar presente em
app_users. - O
user_idde uma operação de escrita corresponda aauth.uid().
A aplicação utiliza somente a chave pública do Supabase no navegador. A chave service_role nunca deve ser inserida no código front-end.
O Supabase foi escolhido para adicionar autenticação e PostgreSQL sem a necessidade inicial de manter um servidor próprio. A plataforma fornece autenticação, API de dados e políticas de segurança integradas ao banco.
O projeto original já representava o estado em objetos JavaScript armazenados no localStorage. O uso de JSONB permitiu migrar para persistência remota sem reescrever toda a lógica de domínio e renderização.
Em uma aplicação maior, uma possível evolução seria normalizar objetivos, conclusões e participantes em tabelas separadas, facilitando relatórios, auditoria, filtros e atualizações concorrentes.
O acesso público não cria um usuário anônimo no Supabase. O visitante utiliza o papel público para consultar somente o estado explicitamente publicado. Essa abordagem evita o crescimento desnecessário de contas anônimas e mantém o fluxo de leitura separado do fluxo autenticado.
Quando um usuário autorizado entra e ainda não possui estado remoto, a aplicação verifica os dados locais existentes. Caso encontre progresso ou personalizações, o estado local é enviado ao Supabase.
ProgrideMine/
├── assets/
│ `-- favicon.svg
├── css/
│ `-- styles.css
├── js/
│ ├── config.js
│ ├── data.js
│ ├── main.js
│ ├── state.js
│ ├── storage.js
│ ├── supabase.js
│ `-- ui.js
├── supabase/
│ ├── setup.sql
│ `-- authorize-users.sql.example
├── .editorconfig
├── .gitignore
├── index.html
├── LICENSE
`-- README.md
- Acesse o painel do Supabase.
- Crie um projeto.
- Aguarde a inicialização do banco.
- Guarde a Project URL e a chave pública.
Abra o SQL Editor e execute o arquivo:
supabase/setup.sql
O script cria:
- Tabela
app_users. - Tabela
user_state. - Índice para jornadas públicas.
- Função
is_allowed_user(). - Trigger que limita a autorização a dois usuários.
- Políticas de Row Level Security.
- Permissões para os papéis
anoneauthenticated.
No painel de autenticação:
- Mantenha o provedor de e-mail habilitado.
- Desabilite novos cadastros públicos.
- Desabilite login anônimo.
- Para usuários criados manualmente, desabilite a confirmação obrigatória ou marque cada conta como confirmada.
Crie manualmente os dois usuários em Authentication > Users.
Copie o UUID de cada conta e use como base o arquivo:
supabase/authorize-users.sql.example
Exemplo:
insert into public.app_users (user_id, display_name) values
('UUID_DO_USUARIO_1', 'Usuario 1'),
('UUID_DO_USUARIO_2', 'Usuario 2');Preencha js/config.js:
export const SUPABASE_URL = 'https://SEU-PROJETO.supabase.co';
export const SUPABASE_PUBLISHABLE_KEY =
'SUA_CHAVE_PUBLICA';
export const SUPABASE_ENABLED = Boolean(
SUPABASE_URL && SUPABASE_PUBLISHABLE_KEY
);Não use a senha do banco, uma chave secreta ou a chave service_role.
Como o projeto usa módulos JavaScript, execute por meio de um servidor HTTP local.
python -m http.server 8000Abra:
http://localhost:8000
npx serve .Use o endereço exibido no terminal.
Abrir o index.html diretamente com o protocolo file:// pode impedir o carregamento correto dos módulos.
O projeto é estático e pode ser publicado sem etapa de build.
- Envie os arquivos para um repositório no GitHub.
- Importe o repositório na Vercel.
- Mantenha o diretório raiz como a pasta que contém
index.html. - Não defina comando de build, salvo se a configuração do projeto exigir.
- Publique o projeto.
Quando o repositório já está conectado à Vercel, cada push no branch de produção gera um novo deployment.
Exemplo:
git add .
git commit -m "Atualiza funcionalidades do ProgrideMine"
git push- Abra a aplicação.
- Informe e-mail e senha.
- Aguarde o carregamento do estado.
- Marque, crie, edite, exclua ou reordene objetivos.
- Observe o indicador de sincronização.
- Ative
Jornada públicapara liberar a leitura por visitantes.
- Abra a aplicação.
- Clique em
Continuar sem login. - Consulte a jornada pública.
- Use o botão
Entrarcaso queira acessar uma conta autorizada.
- Login com credenciais válidas.
- Login com senha incorreta.
- Login com conta existente, mas ausente de
app_users. - Restauração de sessão após atualizar a página.
- Logout.
- Tentativa de escrita sem sessão.
- Tentativa de acessar o estado de outro usuário.
- Tentativa de inserir um terceiro usuário em
app_users. - Visualização pública quando
is_public = true. - Ausência de dados públicos quando
is_public = false.
- Marcar e desmarcar objetivos.
- Criar objetivo personalizado.
- Editar objetivo padrão.
- Editar objetivo personalizado.
- Excluir objetivo personalizado.
- Reordenar objetivos.
- Reiniciar o progresso.
- Atualizar a página e confirmar a persistência.
- Migrar dados existentes do
localStorage.
O projeto inicialmente dependia exclusivamente do localStorage. A evolução exigiu criar uma camada de armazenamento capaz de manter compatibilidade com dados locais e, ao mesmo tempo, usar o Supabase como persistência remota.
Autenticação confirma a identidade do usuário. Autorização define o que o usuário pode fazer. No ProgrideMine, uma conta válida no Supabase Auth ainda precisa estar registrada em app_users para obter acesso de edição.
Ocultar botões não impede chamadas diretas à API. Por esse motivo, o modo somente leitura no front-end é complementado por políticas RLS no PostgreSQL.
Durante a evolução do projeto, foram investigados problemas como:
- HTML e JavaScript publicados em versões incompatíveis.
- Elementos esperados pelo JavaScript ausentes no HTML.
- Chave pública e URL do Supabase configuradas incorretamente.
- Conta confirmada, mas não autorizada em
app_users. - Checkbox alterando visualmente sem persistir por falta de importação da função responsável pelo estado.
- Diferença entre horários UTC do banco e o horário local exibido pelo navegador.
Esses problemas foram diagnosticados com o console do navegador, Network, respostas da API, consultas SQL e inspeção do deployment.
- O projeto usa Supabase como Backend as a Service e não possui uma API própria.
- O estado é armazenado em JSONB, o que reduz a flexibilidade para relatórios mais complexos.
- Os testes atuais são principalmente manuais.
- O modo público exibe a jornada pública atualizada mais recentemente quando mais de uma estiver disponível.
- Não existe colaboração simultânea na mesma jornada.
- Não existe controle de versão para detectar alterações concorrentes.
- A configuração pública do Supabase fica em um módulo JavaScript versionado.
- Adicionar testes unitários para os mutadores de estado.
- Adicionar testes end-to-end para login, visitante e persistência.
- Normalizar objetivos e conclusões em tabelas relacionais.
- Implementar uma API própria para praticar controllers, services e validação no servidor.
- Adicionar validação centralizada dos dados antes da persistência.
- Melhorar o tratamento de erros de rede e sincronização.
- Implementar retentativa de salvamento.
- Adicionar recuperação de senha.
- Adicionar controle de conflitos por versão ou
updated_at. - Mover configurações para variáveis de ambiente em um processo de build.
- Adicionar auditoria de alterações.
- Criar uma página de seleção quando houver mais de uma jornada pública.
Uma descrição curta e objetiva:
O ProgrideMine é uma aplicação web para acompanhar uma jornada no Minecraft. O projeto começou com persistência no navegador e foi evoluído para usar autenticação, autorização e PostgreSQL pelo Supabase. Usuários autorizados podem editar e sincronizar a própria jornada, enquanto visitantes têm acesso somente à leitura do conteúdo publicado. A aplicação usa Row Level Security para proteger os dados e está publicada na Vercel com deploy integrado ao GitHub.
Destaque:
- Modelagem no PostgreSQL.
- Autenticação e autorização.
- Políticas RLS.
- Associação entre registro e
auth.uid(). - Migração de persistência local para remota.
- Uso de JSONB e suas limitações.
- Segurança da chave pública.
- Diferença entre BaaS e uma API própria.
Uma forma honesta de apresentar:
Eu não desenvolvi um servidor próprio nesta versão. Usei o Supabase como Backend as a Service e fiquei responsável pela modelagem, pelas políticas de acesso, pela integração com o front-end e pela validação dos fluxos. Como evolução, eu implementaria uma API própria para aprofundar organização em camadas, testes e validação no servidor.
Destaque:
- Interface responsiva.
- Estado e renderização separados.
- Eventos e formulários.
- Drag-and-drop.
- Autenticação e sessão.
- Persistência assíncrona.
- Segurança no banco.
- Deploy contínuo.
- Debugging em produção.
- Abra a aplicação em janela anônima.
- Entre como visitante.
- Mostre a jornada e os controles bloqueados.
- Faça login com uma conta autorizada.
- Marque um objetivo.
- Crie e edite um objetivo personalizado.
- Reordene uma tarefa.
- Atualize a página e mostre a persistência.
- Publique a jornada.
- Saia e mostre novamente o acesso de visitante.
O objetivo era adicionar autenticação e PostgreSQL sem manter inicialmente um servidor próprio, permitindo concentrar o desenvolvimento nas regras da aplicação e aprender autorização com RLS.
A estrutura original já utilizava objetos JavaScript. JSONB permitiu uma migração incremental com menor risco de regressão. Para uma aplicação maior, uma modelagem relacional seria mais adequada para consultas e relatórios.
A chave pública identifica o projeto, mas não concede acesso administrativo. A segurança depende das permissões e políticas RLS. A chave service_role nunca deve ser enviada ao navegador.
O localStorage permite migrar dados de usuários da versão anterior. Quando não existe um estado remoto, a aplicação pode aproveitar o estado local e enviá-lo ao Supabase.
Cada usuário possui atualmente o próprio registro. O projeto não implementa colaboração sobre a mesma jornada. Uma evolução poderia usar controle de versão, processamento em tempo real ou validação de updated_at.
Ferramentas de inteligência artificial foram utilizadas como apoio para discussão de requisitos, revisão de alternativas e investigação de problemas. As decisões, configurações, testes, correções e validações do fluxo foram realizadas com entendimento da arquitetura e do código utilizado.
Este projeto está licenciado sob os termos presentes no arquivo LICENSE.