Criando Aplicativos Web

Um projeto raramente é composto apenas de backend. Com o Lino, é possível criar também aplicativos web para consumir as APIs geradas, oferecendo interfaces para usuários finais ou equipes internas.


Atualmente, o framework oferece suporte nativo ao Blazor Web App (modo de renderização interactive auto). No entanto, a arquitetura foi projetada para permitir a adição de múltiplos frontends na mesma solução, atendendo diferentes cenários e públicos.

Arquitetura de frontend com Blazor Web App

Aplicações web geradas pelo Lino conectam usuários aos casos de uso do backend por meio de uma interface real, não apenas por chamadas feitas em ferramentas de API. O tipo de frontend nativo atual é Blazor Web App, preparado para aplicações administrativas, portais públicos, backoffices, áreas de parceiros e interfaces específicas de domínio.

lino web-app new --name <WebAppName>

O comando deve ser executado dentro de um projeto Lino. Ele solicita o nome da Web App, utiliza o template Blazor Web App, confirma os dados selecionados, cria os arquivos necessários e executa os comandos que conectam o frontend à solução. A forma canônica é web-app. Os aliases webapp e web existem para produtividade, mas a documentação e os exemplos devem preferir lino web-app new para manter consistência.

O que é gerado

Uma Blazor Web App gerada pelo Lino não é apenas uma pasta solta de telas. Ela entra na mesma solução .NET e acompanha a organização modular usada pelo backend, separando responsabilidades entre host, cliente, componentes compartilhados e projetos de UI por serviço ou módulo.

  • Projeto Server: hospeda a Blazor Web App, mapeia os componentes raiz, configura service defaults, assets estáticos, antiforgery, HTTPS, serviços do MudBlazor e modos de renderização interativos.
  • Projeto Client: concentra componentes executados no lado WebAssembly, roteamento, layout, estrutura de menu, configurações de navegador, recursos de localização e integração com MudBlazor.
  • Projeto WebApps compartilhado: centraliza recursos comuns de UI, notificações, diálogos, modelos de query string, resultados de cliente, serviços de cultura/fuso horário e componentes reutilizáveis.
  • Projetos de UI por serviço e módulo: quando a solução possui serviços e módulos, o Lino cria projetos de frontend dentro da estrutura da Web App para manter páginas, menus e resources isolados por contexto.

O host gerado registra AddInteractiveServerComponents e AddInteractiveWebAssemblyComponents. Os componentes raiz HeadOutlet e Routes usam InteractiveAuto, permitindo que a aplicação comece com interatividade via servidor e migre para WebAssembly quando o runtime do cliente estiver disponível.

Integração com APIs do backend

Quando uma Web App existe, o Lino mantém o backend preparado para consumo tipado pelo frontend. Serviços e módulos podem receber projetos Api.Contracts e Api.Client, expondo contratos de request/response e clientes tipados para os endpoints gerados.

  • A UI não precisa montar chamadas HTTP brutas manualmente para cada funcionalidade.
  • Páginas geradas chamam clientes de API tipados e trabalham com modelos de request e response criados junto com o backend.
  • Modelos compartilhados como ClientResult, QueryParams e PagedQueryParams padronizam tratamento de resultado, filtros, paginação e feedback visual.
  • A integração via HttpClient tipado mantém o frontend alinhado aos contratos, permissões, mensagens de validação e culturas usadas pelo restante da solução.

O fluxo prático fica:

Página Blazor -> cliente de API tipado -> endpoint Minimal API -> Command/Query -> banco de dados

Esse caminho preserva a consistência full-stack: o modelo de domínio, os casos de uso, os endpoints, os contratos, a interface localizada, a navegação e as permissões seguem as mesmas convenções do projeto.

Recursos de UI incluídos

A Web App gerada já nasce preparada para preocupações comuns de aplicações reais:

  • Roteamento por componentes Routes.razor gerados.
  • Layout, navegação e componentes visuais baseados em MudBlazor.
  • Geração de menus a partir das páginas disponíveis em cada serviço ou módulo.
  • Arquivos .resx para localização dos textos nas culturas configuradas no projeto.
  • Suporte a autenticação, armazenamento de token, rotas protegidas e serviços de permissão quando a feature de autenticação está habilitada.
  • Menus sensíveis a autorização, exibindo entradas apenas quando o usuário atual possui a permissão necessária.

Múltiplos frontends

Um único backend pode sustentar mais de uma Web App. Isso é útil quando públicos diferentes precisam de navegação, segurança, experiência e deploy distintos, mas devem continuar compartilhando os mesmos serviços, módulos, casos de uso e APIs.

  • Site público: páginas acessíveis a clientes, visitantes ou usuários ainda não autenticados.
  • Backoffice/Admin: painel interno de gestão para operadores, suporte e equipes administrativas.
  • Portal de parceiros: acesso restrito para parceiros, revendedores, fornecedores ou integrações operacionais.
  • Área de autoatendimento: experiência focada em clientes finais, com menus e permissões próprias.

Cada frontend pode evoluir com seus próprios layouts, resources, menus e regras de acesso, enquanto o backend permanece organizado por serviços, módulos, casos de uso e contratos.

Gerando páginas web

Depois de modelar a entidade, definir os casos de uso e gerar commands, queries, endpoints e persistência, o próximo passo costuma ser expor a funcionalidade na interface. O Lino automatiza essa etapa com o gerador de páginas:

lino page new --service <ServiceName> --module <ModuleName> --entity <EntityName> --webapp <WebAppName>
lino page edit --service <ServiceName> --module <ModuleName> --entity <EntityName> --webapp <WebAppName>
lino page list --service <ServiceName> --module <ModuleName> --entity <EntityName> --webapp <WebAppName>

As opções também podem ser informadas de forma interativa. O comando pergunta o serviço, o módulo, a entidade, a Web App de destino, o tipo de página e as propriedades que devem aparecer no grid. O tipo mais comum é CRUD; quando a entidade suporta apenas consulta, o Lino pode gerar uma página do tipo DataGrid.

Use page new para criar a primeira versão da tela, page edit quando a página precisa acompanhar mudanças de campos, contratos ou comportamento, e page list para entender o que já foi gerado para uma entidade.

Fluxo recomendado

  1. Crie ou selecione a Web App com lino web-app new.
  2. Modele a entidade e gere os casos de uso, queries, commands, endpoints, contratos de API e artefatos de persistência.
  3. Execute lino page new e selecione a entidade que receberá interface.
  4. Escolha cuidadosamente os campos do grid. Eles viram colunas visíveis e ajudam a montar os parâmetros de consulta, filtros e paginação.
  5. Rode a solução pelo AppHost para validar UI, APIs, autenticação, permissões e integração com banco de dados em conjunto.

Estrutura gerada

Para uma página CRUD, o Lino cria um pacote completo de página Blazor em vez de um único arquivo Razor:

  • Página de registro ou índice coordenando listagem, criação, edição, detalhes e exclusão.
  • Componente de grid baseado em MudBlazor, com carregamento server-side, paginação, filtros e mapeamento para query params.
  • Componente de formulário com ViewModel tipado e extensions para mapear create, update e get-by-id requests.
  • Resources para títulos, labels, botões, mensagens de validação e textos localizados da interface.
  • Verificações de permissão quando autenticação está habilitada, incluindo validação de acesso à página e botões condicionais.

Criando uma página CRUD para a entidade Vehicle, por exemplo, no serviço Fleet, módulo Operations e Web App Backoffice, a estrutura segue este formato:

src/WebApps/Backoffice/Services/Fleet/Operations/Pages/Vehicles/Registration/
├── Vehicle.razor
├── Vehicle.razor.cs
├── Resources/
│   ├── VehicleResources.resx
│   └── VehicleResources.Designer.cs
└── Components/
    ├── Form/
    │   ├── VehicleForm.razor
    │   ├── VehicleForm.razor.cs
    │   ├── VehicleFormExtensions.cs
    │   ├── VehicleViewModel.cs
    │   └── Resources/
    │       ├── VehicleFormResources.resx
    │       └── VehicleFormResources.Designer.cs
    └── Grid/
        ├── VehicleGrid.razor
        ├── VehicleGrid.razor.cs
        ├── VehicleGridExtensions.cs
        ├── VehiclePagedQueryParams.cs
        └── Resources/
            ├── VehicleGridResources.resx
            └── VehicleGridResources.Designer.cs

A ideia preserva a estrutura anterior usada em exemplos como Order: página principal, code-behind, componentes de formulário, componentes de grid, extensions e parâmetros paginados. A versão atual acrescenta resources e integração explícita com a organização por Web App, serviço e módulo.

Como a página gerada funciona

A página usa os mesmos contratos gerados para a API. O grid transforma filtros e paginação em uma request de listagem; o formulário transforma o ViewModel em requests de criação ou atualização; o cliente de API tipado envia a chamada ao endpoint correspondente. O endpoint executa o Command ou Query gerado e devolve uma resposta tipada para a UI.

Frontend -> API -> Commands/Queries -> banco de dados

Quando autorização existe, o código gerado também verifica permissões como listagem, criação, edição, exclusão e consulta por identificador. Isso afeta tanto o acesso à página quanto a visibilidade das ações para o usuário.

O resultado é um fluxo full-stack consistente: modelo de domínio, caso de uso, endpoint, cliente tipado, UI localizada, navegação e permissões seguem as mesmas convenções do projeto. O gerador reduz repetição, mas os componentes continuam editáveis para ajustes de produto, usabilidade e regras específicas.

Interface multi-idioma

Aplicações web geradas pelo Lino usam arquivos .resx para textos localizados. Isso permite manter a mesma estrutura Razor e variar títulos, labels, botões, mensagens de erro, textos de validação e descrições conforme a cultura ativa.

A localização não deve ser tratada como acabamento visual. Em páginas administrativas e portais operacionais, termos inconsistentes geram dúvida sobre a regra de negócio. Por isso, os resources fazem parte da arquitetura da UI e devem acompanhar páginas, forms, grids e componentes compartilhados.

  • Mantenha chaves estáveis, descritivas e orientadas ao significado, evitando nomes presos ao layout temporário da tela.
  • Evite texto hard-coded em páginas e componentes; use resources para labels, mensagens, títulos, breadcrumbs, menus e confirmações.
  • Revise termos técnicos para manter consistência entre documentação, CLI, contratos de API e interface.
  • Preserve o mesmo conjunto de chaves entre culturas para impedir fallback inesperado ou telas parcialmente traduzidas.
  • Separe tradução literal de adaptação de produto: quando um termo precisa ser localizado para o usuário final, mantenha o sentido funcional da ação.

Em páginas geradas, normalmente existem resources no nível da página, do formulário e do grid. Essa separação permite que cada parte evolua sem misturar textos de listagem, edição, validação e navegação.

CRUD responsivo e pronto para uso

O CRUD gerado acelera a entrega porque cria a fundação repetitiva da tela: listagem, formulário, integração com API, resources, paginação, filtros, actions e code-behind. Ainda assim, ele deve ser revisado como experiência de produto, não apenas como scaffold técnico.

Uma boa tela CRUD precisa permitir que o usuário encontre registros, entenda o estado atual, execute ações com confiança e recupere-se de falhas. Isso vale tanto para telas internas de backoffice quanto para portais voltados a clientes ou parceiros.

  • Escolha colunas de listagem que ajudem a tomada de decisão; evite grids com campos técnicos que não dizem nada para o operador.
  • Configure filtros e paginação de acordo com o volume esperado de dados e com os principais critérios de busca do usuário.
  • Revise validações e mensagens de erro para explicar o problema em linguagem do domínio, não apenas em termos de implementação.
  • Garanta estados vazios, carregamento e falha para evitar telas silenciosas quando não há dados, a API demora ou uma operação não conclui.
  • Confirme exclusões e operações irreversíveis, deixando claro qual registro será afetado.
  • Mostre feedback claro após salvar, editar, excluir ou falhar, usando notificações e mensagens localizadas.
  • Proteja ações por permissão no backend e no frontend; esconder botões melhora a experiência, mas não substitui autorização real.
  • Verifique responsividade em telas menores, especialmente menus de ação, filtros, campos obrigatórios e grids com muitas colunas.

O ponto de partida gerado pelo Lino deve ser tratado como uma base coerente e integrada. A partir dela, o time ajusta densidade visual, ordem dos campos, regras de exibição, permissões e textos para refletir o processo real do produto.

Ocorreu um erro não tratado. Recarregar 🗙