✦ Sobre o projeto

Feito por humano.
Desenhado com IA.

Um projeto de portfólio para aprender desenvolvimento back-end, construindo, travando e resolvendo problemas reais. O backend e toda a lógica foram escritos à mão. O design, o HTML e os efeitos visuais foram gerados com ajuda de IA.

Desenvolvido à mão
Weder Borges
Backend · Lógica · Arquitetura
  • Rotas, blueprints e views Flask
  • Modelos e migrações (SQLAlchemy + Alembic)
  • Autenticação e proteção CSRF
  • Envio de emails com APScheduler + Resend
  • Deploy com Docker e Railway
Gerado com IA
Claude — Anthropic
Design · HTML · Efeitos visuais
  • Identidade visual, logo e favicon SVG
  • Templates HTML: login, registro, tarefas, perfil
  • Landing page com animações e mockup
  • Template de email HTML (moderno + jornal)
  • Dark theme, gradientes e efeito typewriter
1 Objetivo do projeto

O to-be list é um gerenciador de tarefas simples de propósito. A ideia nunca foi a complexidade da regra de negócio — foi usar uma base simples para estudar a fundo cada camada de uma aplicação web real em produção: autenticação, modelagem de dados, migrações de schema, segurança contra ataques comuns e deploy em infraestrutura de verdade.

Cada decisão técnica relevante aqui — por que Flask-WTF em vez de CSRF manual, por que Alembic em vez de recriar tabelas, por que migrar para PostgreSQL — foi tomada entendendo o porquê, não copiando de um boilerplate.

2 Tecnologias utilizadas
Fl
Flask
Back-end / framework
SQ
SQLAlchemy
ORM
Po
PostgreSQL
Banco de dados
Al
Alembic
Migrações de schema
Fl
Flask-Login
Autenticação / sessão
Fl
Flask-WTF
Proteção CSRF
AP
APScheduler
Agendamento de tarefas
Re
Resend
Envio de email
Do
Docker
Containerização
Gu
Gunicorn
Servidor de produção
Ra
Railway
Deploy e hospedagem
Po
Poetry
Dependências
3 O que aprendi construindo
Segurança — proteção CSRF

Implementei proteção contra CSRF com Flask-WTF, sem migrar todos os formulários para classes FlaskForm — decisão consciente para manter o escopo da tarefa isolado. A parte mais interessante não foi a proteção em si, mas centralizar a injeção do token num único script no template base, em vez de repetir em cada formulário — inclusive os que vêm de partials via {% include %}. Validei testando manualmente: alterar o token no DevTools e confirmar que a requisição cai com 400 Bad Request antes de chegar à view.

Migração de banco — SQLite → PostgreSQL

Migrei o banco local para PostgreSQL gerenciado, com troca de driver (psycopg v3), ajuste de tipos incompatíveis entre os dois bancos, e remoção do create_all() em favor do Alembic como única fonte de verdade do schema. No caminho, diagnostiquei e corrigi manualmente uma migration corrompida, gerada a partir de um estado transitório do banco.

Deploy — Docker e variáveis de ambiente

Resolvi um bug sutil no Dockerfile: a diferença entre exec form e shell form do CMD. A forma array padrão não passa por uma shell, então a variável $PORT (injetada dinamicamente pela hospedagem) nunca era expandida — o servidor sempre subia na porta errada. A correção combina a sintaxe recomendada com uma shell explícita por dentro.

Detalhes que custam caro se ignorados

Como request.form.get() retorna string vazia (não None) quando um campo é deixado em branco — e por que isso quebraria uma constraint de e-mail único no banco se não fosse tratado. Como == None não funciona como esperado numa query do SQLAlchemy, e por que .isnot(None) é a forma correta.

4 Roadmap futuro
Progresso calculado por dia, não só sobre o total histórico
Recuperação de senha ("esqueci minha senha")
Separação entre banco de produção e de testes
Suíte de testes automatizados com pytest
Refatoração orientada a objetos na camada de regras de negócio

Construído por Weder Borges

Ver código no GitHub →