DOCS: Atualizado Readme
This commit is contained in:
parent
cfa99a4881
commit
08eea51d5a
547
README.md
547
README.md
@ -1,29 +1,544 @@
|
||||
# Omnichannel Sothis - Deploy
|
||||
# Omnichannel Sothis
|
||||
|
||||
Este repositorio e o **deploy** do ecossistema. Ele **nao** contem o codigo do frontend nem do backend em producao. Esses dois sao repositorios separados e devem ser clonados ao lado deste deploy para subir o ambiente completo.
|
||||
Plataforma omnichannel para atendimento com foco inicial em WhatsApp, autenticação corporativa, controle de acesso por perfil, filas por especialidade, agenda de contatos, templates de mensagens e painéis operacionais para agente, supervisor e administrador.
|
||||
|
||||
## Estrutura esperada (3 repositorios)
|
||||
Este repositório é a raiz do ambiente local/deploy. Ele contém o `docker-compose.yml`, as migrations de banco em `database/` e espera os projetos `frontend/` e `backend/` clonados ou presentes na mesma pasta.
|
||||
|
||||
- `deploy/` (este repo): `docker-compose.yml`, `database/`, `.gitignore`, `README.md`
|
||||
- `frontend/`: interface do produto
|
||||
- `backend/`: API e regras de negocio
|
||||
## Estado Atual do Produto
|
||||
|
||||
## Como subir tudo localmente
|
||||
O produto hoje permite:
|
||||
|
||||
Passo a passo (na mesma pasta raiz):
|
||||
- Login via Active Directory/LDAP e Microsoft OAuth.
|
||||
- Redirecionamento da Home conforme perfil do usuário.
|
||||
- Atendimento WhatsApp em tempo real com socket.
|
||||
- Triagem automática inicial pelo Omnino.
|
||||
- Fila de atendimento por especialidade.
|
||||
- Assumir, liberar e transferir atendimentos.
|
||||
- Controle da janela de 24 horas do WhatsApp.
|
||||
- Envio e recebimento de texto, imagem, vídeo, áudio e documentos.
|
||||
- Lazy loading de mídias históricas.
|
||||
- Agenda geral de contatos.
|
||||
- Novo atendimento ativo via templates aprovados.
|
||||
- Notas pessoais do atendente.
|
||||
- Administração de usuários, perfis e especialidades.
|
||||
- Workflow de criação, aprovação, reprovação e exclusão de templates.
|
||||
- Painel mensal do admin e painel operacional do supervisor.
|
||||
|
||||
1. Clonar o repo de deploy na raiz (.)
|
||||
2. Clonar o repo de frontend na pasta `frontend`
|
||||
3. Clonar o repo de backend na pasta `backend`
|
||||
4. Subir tudo:
|
||||
## Perfis e Acesso
|
||||
|
||||
### Usuário sem perfil
|
||||
|
||||
Quando um usuário autentica pela primeira vez e ainda não tem perfil/especialidade definida, ele cai em uma tela vazia informando que não está atribuído a uma área/perfil.
|
||||
|
||||
A liberação desse usuário é feita no painel do admin em `Usuários & Acessos`.
|
||||
|
||||
### Agente
|
||||
|
||||
O agente:
|
||||
|
||||
- Vê somente atendimentos das especialidades em que está vinculado.
|
||||
- Pode ver chamados da especialidade enquanto estão na fila.
|
||||
- Só pode responder depois de assumir o atendimento.
|
||||
- Pode liberar um atendimento para voltar para a fila.
|
||||
- Pode transferir atendimento somente depois de assumir.
|
||||
- Pode transferir para outra especialidade ou para outro usuário elegível.
|
||||
- Pode editar/salvar contato na agenda.
|
||||
- Pode criar notas pessoais.
|
||||
- Pode abrir novo atendimento usando template aprovado.
|
||||
|
||||
### Supervisor
|
||||
|
||||
O supervisor:
|
||||
|
||||
- Acessa a Home operacional da supervisão.
|
||||
- Vê indicadores e filas das especialidades que supervisiona.
|
||||
- Pode usar templates, base de conhecimento, auditoria, atendimento, abrir atendimento, disparo em massa e contatos.
|
||||
- Pode solicitar novos templates, mas eles entram primeiro em aprovação do admin.
|
||||
|
||||
### Admin
|
||||
|
||||
O admin:
|
||||
|
||||
- Não precisa pertencer a uma especialidade.
|
||||
- Vê todas as filas e todos os atendimentos já roteados/classificados.
|
||||
- Não vê conversas ainda em triagem automática do Omnino (`bot_triage`).
|
||||
- Cria e gerencia especialidades.
|
||||
- Define perfis de usuários.
|
||||
- Pode tornar outro usuário admin.
|
||||
- Pode definir se um usuário atua como agente ou supervisor em especialidades.
|
||||
- Pode aprovar, reprovar e excluir templates.
|
||||
- Acessa a visão mensal administrativa.
|
||||
- Também pode atender, usando o menu administrativo.
|
||||
|
||||
## Regras de Atendimento WhatsApp
|
||||
|
||||
### Triagem automática pelo Omnino
|
||||
|
||||
Toda primeira mensagem recebida no WhatsApp passa pela triagem automática do Omnino quando ainda não existe atendimento classificado.
|
||||
|
||||
Regras atuais:
|
||||
|
||||
- Mensagens vazias são registradas, mas não disparam triagem.
|
||||
- Mídia sem legenda é registrada, mas não aciona o Omnino automaticamente.
|
||||
- A triagem é serializada por conversa para evitar respostas duplicadas quando o WhatsApp dispara eventos quase simultâneos.
|
||||
- O backend guarda `last_routed_message_id` para evitar processar a mesma mensagem mais de uma vez.
|
||||
|
||||
Fluxo de decisão:
|
||||
|
||||
1. Se a mensagem já contém uma intenção clara, o Omnino roteia direto para a especialidade.
|
||||
2. Se a primeira mensagem é genérica, o Omnino envia a saudação completa e mantém a conversa em `bot_triage`.
|
||||
3. Se a segunda mensagem ainda não identifica intenção, o Omnino pede explicitamente: suporte, financeiro ou comercial.
|
||||
4. Se a terceira mensagem ainda for inválida, a conversa cai automaticamente em Suporte.
|
||||
|
||||
Exemplos de intenção:
|
||||
|
||||
- Suporte: suporte, bug, problema, técnico.
|
||||
- Financeiro: boleto, dinheiro, cartão, atraso, fatura.
|
||||
- Comercial: produto, novo, contratar, proposta.
|
||||
|
||||
### Estados do atendimento
|
||||
|
||||
A tabela `whatsapp_chat_atribuicoes` representa o estado do atendimento:
|
||||
|
||||
- `bot_triage`: conversa ainda está com o Omnino.
|
||||
- `queued`: conversa está na fila da especialidade, sem atendente.
|
||||
- `assigned`: conversa foi assumida ou atribuída diretamente a um atendente.
|
||||
|
||||
Regras:
|
||||
|
||||
- Conversas em `bot_triage` não aparecem para agentes.
|
||||
- Conversas em `queued` aparecem para usuários da especialidade.
|
||||
- Conversas em `assigned` continuam visíveis para a especialidade, mas só o responsável responde.
|
||||
- Admin vê todas as conversas roteadas, exceto `bot_triage`.
|
||||
|
||||
### Assumir, liberar e transferir
|
||||
|
||||
Para responder um chamado, o usuário precisa assumir o atendimento.
|
||||
|
||||
- Ao assumir, `user_id` passa a ser o usuário atual.
|
||||
- Ao liberar, o atendimento volta para fila da especialidade.
|
||||
- Transferência só fica disponível depois que o usuário assume.
|
||||
- Transferência para a mesma especialidade pode apontar para outro usuário.
|
||||
- Transferência para outra especialidade cai na fila da nova especialidade.
|
||||
- A observação da transferência fica visível para o próximo atendente e é limpa depois que o atendimento é respondido.
|
||||
|
||||
### Janela de 24 horas
|
||||
|
||||
O produto respeita a regra operacional do WhatsApp:
|
||||
|
||||
- Conversas têm uma janela de 24 horas representada por `conversation_started_at` e `expires_at`.
|
||||
- Ao abrir atendimento ativo para um cliente, o atendente deve usar template aprovado.
|
||||
- Depois do primeiro contato ativo, o atendimento fica bloqueado para novas mensagens livres até o cliente responder.
|
||||
- Quando o cliente responde, o bloqueio `awaiting_customer_reply` é removido e o atendente pode seguir a conversa.
|
||||
|
||||
## Mensagens e Mídias
|
||||
|
||||
### Envio de mensagens
|
||||
|
||||
Mensagens enviadas por atendente são formatadas com identificação:
|
||||
|
||||
```text
|
||||
Atendente: Nome do Usuário
|
||||
|
||||
Mensagem
|
||||
```
|
||||
|
||||
No WhatsApp, essa identificação é enviada usando negrito:
|
||||
|
||||
```text
|
||||
*Atendente: Nome do Usuário*
|
||||
|
||||
Mensagem
|
||||
```
|
||||
|
||||
Se uma mídia for enviada sem texto, o backend não envia cabeçalho solto. A mídia segue sem legenda.
|
||||
|
||||
### Recebimento de mídias
|
||||
|
||||
Tipos suportados:
|
||||
|
||||
- Imagens: PNG, JPG, JPEG, WEBP.
|
||||
- Vídeos: MP4, WEBM.
|
||||
- Áudios: MP3, OGG, WAV.
|
||||
- Documentos: exibidos como card de arquivo.
|
||||
|
||||
Para preservar performance, o histórico de mensagens não carrega Base64 de mídia diretamente. O frontend busca a mídia sob demanda pelo endpoint:
|
||||
|
||||
```http
|
||||
GET /whatsapp/media/:chatId/:messageId
|
||||
```
|
||||
|
||||
### Limites de upload
|
||||
|
||||
O backend aceita JSON até `25mb` por padrão, configurável via:
|
||||
|
||||
```env
|
||||
REQUEST_BODY_LIMIT=25mb
|
||||
```
|
||||
|
||||
O frontend bloqueia anexos acima de 15 MB para evitar falhas de payload e degradação da experiência.
|
||||
|
||||
## Chat
|
||||
|
||||
A tela `/chat` exibe somente conversas reais vindas do backend/WhatsApp. Não existe mais fallback de conversas mockadas.
|
||||
|
||||
Recursos atuais:
|
||||
|
||||
- Lista de conversas ativas com scroll.
|
||||
- Chat com altura delimitada e scroll interno.
|
||||
- Separador de datas nas mensagens.
|
||||
- Horário por mensagem.
|
||||
- Deduplicação visual de mensagens enviadas localmente e confirmadas por socket.
|
||||
- Ocultação de mensagens vazias.
|
||||
- Botão para assumir atendimento.
|
||||
- Botão para sair do atendimento.
|
||||
- Transferência de atendimento.
|
||||
- Painel de contato do cliente.
|
||||
- Envio de mídia.
|
||||
|
||||
Indicadores na lista:
|
||||
|
||||
- Bolinha amarela: chamado está na fila da especialidade e ainda não foi atribuído.
|
||||
- Bolinha azul: chamado está atribuído ao usuário atual.
|
||||
- Bolinha vermelha: chamado está atribuído a outra pessoa.
|
||||
- Badge de especialidade: mostra para qual fila o chamado foi roteado.
|
||||
- Ícone de contato: indica que o contato está salvo na agenda.
|
||||
|
||||
## Home do Agente
|
||||
|
||||
A Home do agente usa dados reais do chat quando o WhatsApp está conectado.
|
||||
|
||||
Recursos atuais:
|
||||
|
||||
- Últimos atendimentos.
|
||||
- Preview do chat com scroll automático para a última mensagem.
|
||||
- Respostas sugeridas baseadas no contexto.
|
||||
- Envio da resposta sugerida direto para o chat correto.
|
||||
- Comunicados e notas.
|
||||
- Notas pessoais persistidas por usuário.
|
||||
- Relógio/data em tempo real.
|
||||
- Atalhos para scripts, relatórios pessoais, disparo em massa e base de conhecimento.
|
||||
|
||||
## Novo Atendimento
|
||||
|
||||
A tela `/new-attendance` permite iniciar contato ativo.
|
||||
|
||||
Regras:
|
||||
|
||||
- WhatsApp é o canal funcional.
|
||||
- Email e SMS aparecem bloqueados como funcionalidades em construção.
|
||||
- O atendente pode buscar contatos da agenda.
|
||||
- Também pode digitar novo número, nome, empresa e observação.
|
||||
- O telefone tem máscara e seletor de país.
|
||||
- Países disponíveis atualmente: Brasil, EUA, Argentina, Chile e México.
|
||||
- O primeiro contato ativo exige seleção de template aprovado.
|
||||
- Ao iniciar atendimento, o sistema salva/atualiza o contato na agenda e abre o chat daquela conversa.
|
||||
|
||||
## Agenda de Contatos
|
||||
|
||||
A agenda é geral, não vinculada a uma especialidade específica.
|
||||
|
||||
Tabela principal:
|
||||
|
||||
```text
|
||||
agenda_contatos
|
||||
```
|
||||
|
||||
Campos funcionais:
|
||||
|
||||
- Nome.
|
||||
- Empresa.
|
||||
- Telefone.
|
||||
- Observação.
|
||||
- Chat ID.
|
||||
- Usuário que criou/atualizou.
|
||||
|
||||
Na conversa, o telefone não é editável quando vem do WhatsApp, mas nome, empresa e observação podem ser atualizados.
|
||||
|
||||
## Templates WhatsApp
|
||||
|
||||
Templates ficam na tabela:
|
||||
|
||||
```text
|
||||
whatsapp_templates
|
||||
```
|
||||
|
||||
Campos relevantes:
|
||||
|
||||
- `name`
|
||||
- `content`
|
||||
- `area_id`
|
||||
- `status`
|
||||
- `requested_by_role`
|
||||
- `admin_approved_at`
|
||||
- `meta_submitted_at`
|
||||
- `meta_approved_at`
|
||||
|
||||
Status atuais:
|
||||
|
||||
- `approved`: template aprovado e disponível para uso.
|
||||
- `meta_review`: enviado para aprovação da Meta.
|
||||
- `admin_review`: aguardando aprovação do admin.
|
||||
- `rejected`: reprovado pelo admin.
|
||||
|
||||
Regras:
|
||||
|
||||
- Admin cria template e envia para aprovação.
|
||||
- Supervisor cria template, mas ele entra em aprovação do admin.
|
||||
- Admin pode aprovar e enviar para Meta.
|
||||
- Admin pode reprovar.
|
||||
- Admin pode excluir.
|
||||
- A aprovação da Meta é simulada: templates em análise são aprovados automaticamente depois de um intervalo configurado no código.
|
||||
- A listagem possui filtro por especialidade e scroll para não ocupar a página inteira.
|
||||
|
||||
## Painel Admin
|
||||
|
||||
A Home do admin é uma visão mensal.
|
||||
|
||||
Recursos atuais:
|
||||
|
||||
- Filtro por especialidade no topo.
|
||||
- KPIs mensais.
|
||||
- Total de atendimentos.
|
||||
- Tempo médio.
|
||||
- TME.
|
||||
- TMR.
|
||||
- Satisfação.
|
||||
- Atendentes ativos.
|
||||
- Gráfico de atendimentos por dia.
|
||||
- Donut de distribuição por canal.
|
||||
- Ranking de atendentes.
|
||||
- Painel de avisos.
|
||||
- Menu administrativo lateral.
|
||||
|
||||
Menu atual:
|
||||
|
||||
- Home.
|
||||
- Operação.
|
||||
- Usuários & Acessos.
|
||||
- Templates.
|
||||
- Base de conhecimento IA.
|
||||
- Auditoria.
|
||||
- Canais.
|
||||
- Atendimento.
|
||||
- Abrir Atendimento.
|
||||
- Disparo em Massa.
|
||||
- Contatos.
|
||||
- Configurações.
|
||||
- Sair.
|
||||
|
||||
## Usuários & Acessos
|
||||
|
||||
Tela administrativa para usuários, perfis e especialidades.
|
||||
|
||||
Regras atuais:
|
||||
|
||||
- Usuários vêm do banco/autenticação, não de mock.
|
||||
- Admin Demo, Supervisor Demo e Atendente Demo foram removidos por migration.
|
||||
- Admin pode editar um usuário em modal.
|
||||
- Se o usuário for admin, não há seleção de especialidades.
|
||||
- Se não for admin, é possível vincular múltiplas especialidades.
|
||||
- Para cada especialidade, o usuário pode atuar como agente ou supervisor.
|
||||
- A criação/edição de especialidades é feita pelo admin.
|
||||
- A definição de supervisores agora ocorre no vínculo do usuário, não dentro da especialidade.
|
||||
|
||||
## Painel Supervisor / Operação
|
||||
|
||||
O painel de supervisor também é usado como visão de operação no menu do admin.
|
||||
|
||||
Recursos atuais:
|
||||
|
||||
- Filtro por especialidade.
|
||||
- KPIs do dia.
|
||||
- Atendimentos finalizados.
|
||||
- Atendimentos em aberto.
|
||||
- Conversas na fila.
|
||||
- Tempo médio do dia.
|
||||
- Atendentes online simulados.
|
||||
- Painel do time.
|
||||
- Fila de espera.
|
||||
- Atribuição mockada via modal.
|
||||
- Gráfico do dia por hora.
|
||||
|
||||
Sempre que há dado real disponível, a tendência do produto é substituir mock por dado real. Indicadores sem origem real consolidada ainda usam dados simulados.
|
||||
|
||||
## Autenticação
|
||||
|
||||
Endpoints principais:
|
||||
|
||||
```http
|
||||
GET /auth/config
|
||||
POST /auth/login
|
||||
GET /auth/oauth/microsoft/start
|
||||
GET /auth/oauth/microsoft/callback
|
||||
```
|
||||
|
||||
Providers suportados:
|
||||
|
||||
- LDAP/Active Directory.
|
||||
- Microsoft OAuth.
|
||||
|
||||
Variáveis relevantes:
|
||||
|
||||
```env
|
||||
AUTH_PROVIDERS=ldap,microsoft
|
||||
LDAP_ENABLED=true
|
||||
LDAP_URL=ldaps://...
|
||||
LDAP_DOMAIN=...
|
||||
MICROSOFT_ENABLED=false
|
||||
MICROSOFT_TENANT_ID=common
|
||||
MICROSOFT_CLIENT_ID=
|
||||
MICROSOFT_CLIENT_SECRET=
|
||||
```
|
||||
|
||||
## Endpoints Principais
|
||||
|
||||
### WhatsApp
|
||||
|
||||
```http
|
||||
GET /whatsapp/status
|
||||
GET /whatsapp/chats
|
||||
GET /whatsapp/messages/:chatId
|
||||
GET /whatsapp/media/:chatId/:messageId
|
||||
POST /whatsapp/send
|
||||
POST /whatsapp/start-attendance
|
||||
POST /whatsapp/assign
|
||||
POST /whatsapp/transfer
|
||||
DELETE /whatsapp/release/:chatId
|
||||
GET /whatsapp/assignment/:chatId
|
||||
```
|
||||
|
||||
### Templates
|
||||
|
||||
```http
|
||||
GET /whatsapp/templates
|
||||
POST /whatsapp/templates
|
||||
POST /whatsapp/templates/update/:id
|
||||
POST /whatsapp/templates/approve-admin/:id
|
||||
POST /whatsapp/templates/reject-admin/:id
|
||||
DELETE /whatsapp/templates/:id
|
||||
```
|
||||
|
||||
### Admin / Acessos
|
||||
|
||||
```http
|
||||
GET /admin/access/options
|
||||
GET /admin/access/overview
|
||||
GET /admin/access/areas
|
||||
POST /admin/access/areas
|
||||
PUT /admin/access/areas/:id
|
||||
GET /admin/access/users
|
||||
PUT /admin/access/users/:id
|
||||
```
|
||||
|
||||
## Banco de Dados
|
||||
|
||||
Migrations principais:
|
||||
|
||||
- `005_templates.sql`: criação inicial de templates.
|
||||
- `006_whatsapp_assignment_queue.sql`: fila e atribuição de WhatsApp.
|
||||
- `007_whatsapp_triage_state.sql`: estado de triagem automática.
|
||||
- `008_agent_notes.sql`: notas pessoais do atendente.
|
||||
- `009_customer_contacts.sql`: primeira versão de contatos.
|
||||
- `010_agenda_contatos.sql`: agenda geral consolidada.
|
||||
- `011_whatsapp_opening_templates.sql`: templates de abertura ativa.
|
||||
- `012_whatsapp_awaiting_customer_reply.sql`: bloqueio até resposta do cliente.
|
||||
- `013_remove_demo_access_users.sql`: remoção de usuários demo.
|
||||
- `014_whatsapp_template_workflow.sql`: workflow de aprovação de templates.
|
||||
|
||||
## Estrutura do Repositório
|
||||
|
||||
```text
|
||||
omnichannel/
|
||||
├── backend/ # API NestJS e regras de negócio
|
||||
├── frontend/ # Interface React/Vite
|
||||
├── database/migrations/ # Migrations SQL
|
||||
├── docker-compose.yml # Orquestração local
|
||||
├── .env.example # Exemplo de variáveis
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Como Subir Localmente
|
||||
|
||||
Pré-requisitos:
|
||||
|
||||
- Node.js compatível com os projetos.
|
||||
- Docker e Docker Compose.
|
||||
- PostgreSQL via `docker-compose`.
|
||||
|
||||
Na raiz:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Isso sobe `frontend`, `backend` e `database` em uma unica operacao.
|
||||
Também é possível rodar frontend e backend em modo desenvolvimento:
|
||||
|
||||
## Observacoes
|
||||
```bash
|
||||
cd backend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
URLs locais comuns:
|
||||
|
||||
- Frontend: `http://localhost:5173`
|
||||
- Backend: `http://localhost:3001`
|
||||
- Status WhatsApp: `http://localhost:3001/whatsapp/status`
|
||||
|
||||
## Variáveis de Ambiente
|
||||
|
||||
Principais variáveis da raiz:
|
||||
|
||||
```env
|
||||
POSTGRES_USER=omnichannel
|
||||
POSTGRES_PASSWORD=change-me
|
||||
POSTGRES_DB=omnichannel
|
||||
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
||||
DB_USER=omnichannel
|
||||
DB_PASSWORD=change-me
|
||||
DB_NAME=omnichannel
|
||||
|
||||
PORT=3001
|
||||
FRONTEND_URL=http://localhost:3000
|
||||
JWT_SECRET=change-this-long-random-secret
|
||||
JWT_EXPIRES_IN=8h
|
||||
|
||||
REQUEST_BODY_LIMIT=25mb
|
||||
```
|
||||
|
||||
No frontend, a URL da API deve vir de:
|
||||
|
||||
```env
|
||||
VITE_API_URL=http://localhost:3001
|
||||
```
|
||||
|
||||
## Limitações Conhecidas
|
||||
|
||||
- O WhatsApp Web carrega conversas por lazy loading. Nem sempre todo histórico aparece imediatamente após conectar o QR Code.
|
||||
- O status real de presença do contato foi removido por limitação prática da biblioteca/WhatsApp Web.
|
||||
- O painel de supervisor ainda possui indicadores simulados onde não há métrica real consolidada.
|
||||
- Email, SMS e ligação não estão operacionais como canais de atendimento.
|
||||
- A aprovação da Meta para templates é simulada.
|
||||
- Mídias ainda trafegam via Base64 no JSON; para produção, o ideal é evoluir para upload/armazenamento próprio e envio por referência.
|
||||
|
||||
## Regras Importantes Para Desenvolvimento
|
||||
|
||||
- Não reintroduzir mock de conversas no chat. O `/chat` deve exibir apenas conversas reais vindas do backend/WhatsApp.
|
||||
- Toda alteração de banco deve virar nova migration numerada.
|
||||
- Não permitir resposta sem atendimento assumido.
|
||||
- Não permitir transferência sem atendimento assumido.
|
||||
- Conversas em `bot_triage` não devem aparecer para agentes.
|
||||
- Admin pode ver todas as filas e atendimentos roteados.
|
||||
- Novo atendimento ativo deve usar template aprovado.
|
||||
- Depois de contato ativo, bloquear novas mensagens livres até resposta do cliente.
|
||||
- Mídia sem texto não deve enviar cabeçalho solto de atendente.
|
||||
|
||||
- O `docker-compose.yml` deste repo espera `frontend/` e `backend/` presentes na mesma raiz.
|
||||
- Em producao, o fluxo pode mudar para imagens pre-buildadas, mas para desenvolvimento local esta estrutura funciona bem.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user