Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

Desafio técnico Doti

Vaga de dev sênior. R$ 5.000 no primeiro mês, R$ 7.500 do segundo em diante.

Este desafio existe por um motivo só: eu quero ver como você pensa a fronteira entre as partes de um sistema, e quero te ouvir defender isso depois. O código importa menos do que a explicação.

Tempo máximo: 2 dias. Se passou disso, você fez a mais.


O produto

Um mini "Studio" de conteúdo. O usuário digita um tema e o sistema gera três coisas:

  1. Roteiro (texto): um roteiro curto de 30 segundos sobre o tema
  2. Narração (áudio): o roteiro falado
  3. Capa (imagem ou vídeo, escolha sua): o visual do post

Cada geração custa crédito. O usuário compra crédito antes de gerar.

É isso. Não é pra ser um produto, é pra ser um esqueleto honesto de um.


As regras que importam

1. Arquitetura hexagonal (ports and adapters)

O domínio não pode conhecer HTTP, SDK de provider, banco de dados nem framework. Se o seu caso de uso importa next/server ou o SDK da OpenAI, a fronteira está no lugar errado.

2. Três módulos independentes de provider

texto, áudio e imagem são módulos separados. Cada um tem a sua porta e os seus adapters. O módulo de áudio não sabe que existe um módulo de texto.

Providers sugeridos (você não precisa gastar dinheiro, veja o item 3):

Módulo Providers
Texto OpenRouter
Áudio ElevenLabs, Fish Audio
Imagem/vídeo livre escolha

3. Cada módulo precisa de pelo menos 2 adapters, sendo 1 fake

Um adapter real e um fake determinístico. O fake é o que faz o projeto rodar sem chave de API nenhuma e é o que os testes usam.

Trocar de provider tem que ser variável de ambiente. Sem tocar em domínio, sem tocar em caso de uso, sem if provider === 'x' espalhado.

Bônus real (não obrigatório): dois adapters reais no mesmo módulo, para eu ver como você lida com dois SDKs que discordam sobre o formato da resposta.

4. Créditos e pagamento

  • Um usuário com saldo de créditos. Pode ser um usuário fixo hardcoded, não quero auth completa.
  • Cada operação tem um custo. Gerar texto custa X, áudio custa Y, imagem custa Z.
  • Saldo insuficiente é erro de domínio, e o provider não pode ser chamado.
  • Compra de crédito: Stripe em test mode, ou um endpoint fake que simula o webhook. Tanto faz. O que eu olho é a fronteira: pagamento é adapter, crédito é domínio.
  • O webhook precisa ser idempotente. Mesmo evento entregue duas vezes não credita duas vezes.

5. Front

  • LP: uma página. O que é o produto, quanto custa, um CTA.
  • App: input do tema, botão gerar, o resultado (texto na tela, player de áudio, imagem), saldo de créditos visível, botão de comprar crédito.

Não precisa ser design de agência. Precisa ter cuidado. UI/UX entra na avaliação e eu vou reparar em espaçamento, hierarquia, estado de loading e o que acontece quando dá erro.

6. Testes

Domínio e casos de uso testados sem rede, usando os adapters fake.

Não quero cobertura alta. Quero os testes que provam que a fronteira é real, ou seja, aqueles que passariam mesmo se todo provider do mundo saísse do ar.


Stack

TypeScript é obrigatório no núcleo. Framework, banco, ORM, gerenciador de pacote e libs: escolha sua, e eu vou te perguntar o porquê de cada uma.

Se quiser usar Python em alguma parte (um pipeline, um worker), pode. Aqui na Doti o backend de análise é Python e a aplicação é TypeScript, então esse tipo de mistura é o nosso dia a dia.


O que NÃO fazer

Cortei essas coisas de propósito. Se você fizer, eu vou considerar sinal ruim de priorização:

  • Autenticação completa, cadastro, recuperação de senha
  • Multi-tenant, times, permissões
  • Deploy, CI/CD, Terraform, Kubernetes
  • Internacionalização
  • Painel admin
  • Testes E2E
  • docker-compose com seis serviços

Se algo do escopo principal não couber nos 2 dias, corte e escreva no README o que você cortou e por quê. Cortar bem é parte da avaliação. Entregar tudo pela metade é pior do que entregar menos coisa inteira.


Usar IA é esperado

A gente trabalha com Claude Code o dia inteiro. Use o que você quiser: Claude, Cursor, Codex, o que for.

Só existe uma condição: você precisa conseguir defender cada linha. Na conversa eu vou apontar para um arquivo aleatório e perguntar por que está daquele jeito. "A IA escreveu" encerra a entrevista.


Entrega

  1. Repo público seu. Se preferir privado, dá acesso para @coelho-doti.
  2. README respondendo, em texto corrido mesmo:
    • Como rodar do zero, com e sem chaves de API
    • Quais são as fronteiras do sistema e por que cada uma existe (diagrama, lista, o que for mais claro)
    • O que você cortou e por quê
    • O que quebraria primeiro se isso fosse para produção com mil usuários
  3. Me manda o link no DM.

A conversa depois

45 minutos, e é aqui que a vaga é decidida. Eu vou te pedir para:

  • Adicionar um provider novo ao vivo, ou me mostrar exatamente onde você tocaria
  • Defender uma decisão que eu vou atacar (e às vezes eu vou estar errado, quero ver se você segura)
  • Dizer o que faria diferente com 2 semanas em vez de 2 dias

Não decore resposta. Eu quero ouvir o raciocínio, inclusive o "isso aqui eu fiz mal feito porque estava sem tempo".


Critérios de avaliação: AVALIACAO.md

Dúvida sobre o enunciado: abre uma issue nesse repo. Eu respondo em público, ajuda todo mundo.

About

Desafio técnico para a vaga de dev sênior na Doti

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors