Alam Sawame

Desenvolvedor de apps web

JP / EN / PT

Disponível para trabalho

Você já sentiu algo assim no dia a dia?

Registrar cada gasto é cansativo, fica difícil enxergar o total, e quanto mais informação você junta, mais difícil vira decidir. No fim, nada anda.

Para resolver isso, eu criei o Kaimono, um app web focado em planejamento de compras e gestão de orçamento.


Visão Geral do Projeto

  • Tipo de projeto: SaaS pessoal / projeto de portfólio
  • Papel: Engenheiro full-stack solo
  • Estágio: Em desenvolvimento ativo
  • Usuários: Ainda sem usuários em produção
  • Foco principal: arquitetura multi-tenant, fluxos de autenticação, roteamento com i18n
  • Stack (resumo): Next.js, TypeScript, Prisma, PostgreSQL, NextAuth/Auth.js, Zod

Provas (estado atual)

  • Roteamento multi-tenant por subdomínio com isolamento de tenant
  • RBAC aplicado em Server Actions (OWNER / ADMIN / MEMBER)
  • 3 idiomas: EN / JA / PT-BR (roteamento com i18n)
  • Validação no servidor em todas as mutações (Zod)
  • Schema Prisma: 13 modelos / 4 enums (PostgreSQL)
  • Deploy na Vercel com ambientes de preview + migrações Prisma

Funcionalidades Principais

O Kaimono foi desenhado em torno de três funcionalidades centrais:

  1. Gestão de compras do dia a dia
    Uma lista de tarefas simples para itens essenciais.
    Ela permite acompanhar "o que precisa ser comprado" no mesmo lugar em que você controla gastos, funcionando como ponto de entrada do app.

  2. Gestão de itens planejados
    Para itens geralmente mais caros que exigem orçamento e intenção antes da compra.

  3. Gestão de projetos (funcionalidade principal)
    Agrupa itens planejados por objetivo e mostra o orçamento total por projeto.
    Exemplo: redecorar um quarto (tapete, iluminação, plantas etc.).
    Também é possível salvar links por item para voltar rapidamente ao que você estava avaliando.

Além disso, o Kaimono usa uma arquitetura multi-tenant baseada em subdomínio para isolar os dados dos usuários e impedir acesso indevido entre tenants.

team.p0r6iz89.cloud

  • team é o subdomínio
  • p0r6iz89.cloud é o domínio principal.

Se você quiser colaborar, pode convidar pessoas pela página Invitations.


Stack Técnica

Minha prioridade foi manter tudo o mais simples possível enquanto resolvia o problema central: tornar planos e orçamentos visíveis e fáceis de gerenciar.

  • Next.js (full-stack)
  • Server Actions (funções no servidor)
  • Prisma ORM + banco (ex.: PostgreSQL)
  • Zod (validação de schema para Server Actions e inputs de formulário)

Em um projeto anterior usei Django + React, mas em apps menores senti que o custo de "construir o frontend enquanto ajusta APIs do backend o tempo todo" diminuía o ritmo de entrega.

No Kaimono, então, optei por uma estrutura em que Server Actions conversam direto com o banco via Prisma, reduzindo atrito entre frontend e backend.

Isso ajudou a manter CRUD seguro e implementação consistente.


Open Source

O Kaimono é open source e pode ser executado localmente com npm + Docker:

npm install
docker compose up -d db
npx prisma migrate dev
npm run dev

Links:

URLs locais:

  • app principal: http://localhost:3000/en
  • app do tenant: http://team.localhost:3000/en

Nesse setup, o Docker Compose sobe apenas o PostgreSQL (serviço db). O app Next.js roda localmente com npm run dev.


Como Usar

Demo ao vivo: https://p0r6iz89.cloud/home.

O Kaimono foi pensado para tornar decisões de compra mais intencionais, colaborativas e fáceis de executar.


Desafios e Aprendizados

No começo, eu parti do básico: escrever código limpo e manter consistência com o sistema de tipos do TypeScript.

O primeiro grande desafio foi: como introduzir multi-tenancy de um jeito realmente utilizável.

Havia caminhos mais rápidos (por exemplo, usar um serviço como Clerk com recursos prontos de multi-tenant), mas escolhi implementar por conta própria para aprendizado e controle: subdomínios + middleware.

No middleware.ts, o fluxo de requisição é:

  1. Tratamento de locale: se o caminho não está localizado, passa por handleI18nRouting e é normalizado para rotas com prefixo de idioma (/en, /ja, /pt-BR).
  2. Guarda de autenticação: o middleware verifica req.auth?.user e rotas públicas.
    • sem usuário + rota protegida => redireciona para /{locale}/login
    • usuário logado acessando /login => redireciona para /{locale}/
  3. Roteamento por subdomínio: extrai o subdomínio do tenant de hosts como team.localhost ou team.example.com.
  4. Rewrite interno: se a requisição por subdomínio não tiver o prefixo do tenant, reescreve para /{locale}/s/{subdomain}{rest}.

Esse rewrite mantém o roteamento multi-tenant invisível para o usuário, preservando uma estrutura única no App Router. No limite do servidor, uso Zod para validar entradas e retornar estados de erro previsíveis.

middleware.ts Request Flow

Daqui para frente, quero continuar evoluindo o app sem quebrar a arquitetura, principalmente garantindo que fluxos OAuth baseados em URL e i18n não conflitem com o design multi-tenant.


Próximo Passo: Entrada Assistida por IA

Hoje, cadastrar "Essentials" ou "Planned items" ainda exige entrada manual. Autocomplete já ajudaria, mas quero reduzir mais o atrito com um recurso que preenche dados do item a partir de uma foto, por exemplo:

  • nome do produto
  • categoria
  • preço médio estimado
  • URL
  • detalhes do produto