WebNewsGames é uma aplicação de notícias, artigos e campeonatos do universo de jogos. O repositório é único para frontend e backend, por isso a raiz funciona como documentação geral do projeto e cada pasta mantém a responsabilidade de uma parte da aplicação.
WebNewsGames/
├── backend/ # API, domínio, persistência, IoC e testes em .NET
├── frontend/ # Aplicação web em Next.js
├── README.md # Documentação principal do monorepo
└── LICENSE
O backend está em backend/src/WebGames e foi estruturado em camadas para separar entrada HTTP, orquestração de casos de uso, regras de domínio, persistência e configuração de dependências.
- .NET 10
- ASP.NET Core Web API
- Entity Framework Core 10
- PostgreSQL via
Npgsql.EntityFrameworkCore.PostgreSQL - Swagger/OpenAPI via
Swashbuckle.AspNetCore - NUnit para testes
- Dockerfile para execução da API em container
backend/src/WebGames/
├── WebGames.API/ # Controllers, Program.cs, Swagger, CORS e appsettings
├── WebGames.Application/ # AppServices, requests e responses da API
├── WebGames.Domain/ # Entidades, interfaces e serviços de domínio
├── WebGames.Infra/ # EF Core, DbContext, mappings, migrations e repositories
├── WebGames.CrossCutting.Authentication/ # Identity, JWT Bearer, usuário atual e seed de autenticação
├── WebGames.Infra.CrossCutting/ # Projeto cross-cutting base
├── WebGames.Infra.CrossCutting.IoC/ # Registro de injeção de dependência
├── WebGames.Test/ # Projeto de testes
└── WebGames.slnx
| Camada | Responsabilidade |
|---|---|
WebGames.API |
Expõe endpoints HTTP, configura Swagger, CORS, HTTPS, controllers e pipeline da aplicação. |
WebGames.Application |
Define contratos de entrada e saída e centraliza AppServices que orquestram operações da aplicação. |
WebGames.Domain |
Contém entidades, contratos de repositório, contratos de serviços de domínio e validações de regra de negócio. |
WebGames.Infra |
Implementa acesso a dados com EF Core, DbContext, mapeamentos, migrations e repositories. |
WebGames.CrossCutting.Authentication |
Centraliza configuração do ASP.NET Core Identity, JWT Bearer, serviços de autenticação, usuário atual e seed de roles/manager. |
WebGames.Infra.CrossCutting.IoC |
Registra dependências da aplicação, domínio, repositórios e DbContext. |
WebGames.Test |
Projeto reservado para testes automatizados com NUnit. |
Arquivo principal:
backend/src/WebGames/WebGames.API/appsettings.json
Configuração atual de banco:
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Port=5432;Database=webgames;Username=postgres;Password=1234"
}
}Em desenvolvimento, a API usa os perfis definidos em:
backend/src/WebGames/WebGames.API/Properties/launchSettings.json
URLs locais configuradas:
- HTTP:
http://localhost:5181 - HTTPS:
https://localhost:7261 - Swagger em desenvolvimento:
/swagger
A política DevelopmentCorsPolicy permite chamadas do frontend nas seguintes origens:
http://localhost:3001https://localhost:3001
Se o frontend rodar em outra porta, ajuste a lista em WebGames.API/Program.cs.
O backend usa ASP.NET Core Identity com JWT Bearer.
Papéis:
AdministratorUser
Usuário administrador padrão:
- usuário:
manager - senha:
webnews123
Esse usuário é criado automaticamente na inicialização da API, junto com os papéis necessários.
Endpoints:
| Método | Rota | Autenticação | Descrição |
|---|---|---|---|
POST |
/api/v1/auth/login |
Não | Autentica usuário e retorna token Bearer. |
POST |
/api/v1/auth/users |
Não | Cria usuário comum. |
POST |
/api/v1/auth/admins |
Administrator |
Cria usuário administrador. |
Body de login:
{
"userName": "manager",
"password": "webnews123"
}Body de criação de usuário:
{
"userName": "player1",
"password": "webnews123"
}Use o token retornado no header:
Authorization: Bearer {token}
Regras atuais:
- Consultas
GETpermanecem públicas. - Criação, alteração e exclusão de campeonatos exigem
Administrator. - Criação, alteração e exclusão de notícias exigem
Administrator. - Criação de artigos aceita
AdministratorouUser. - Alteração e exclusão de artigos aceitam
Administratorou o usuário autor do artigo. - Ao criar notícia ou artigo, o backend grava
AuthorUserIdeAuthorName.
O registro central fica em:
backend/src/WebGames/WebGames.Infra.CrossCutting.IoC/DependencyInjectionConfig.cs
Dependências registradas:
WebGamesDbContextusando PostgreSQL e a connection stringDefaultConnection- AppServices:
IArticlesAppService->ArticlesAppServiceIChampionshipAppService->ChampionshipAppServiceINewsAppService->NewsAppService
- Domain Services:
IArticleDomainService->ArticleDomainServiceIChampionshipDomainService->ChampionshipDomainServiceINewsDomainService->NewsDomainService
- Repositories:
IArticleRepository->ArticleRepositoryIChampionshipRepository->ChampionshipRepositoryINewsRepository->NewsRepository
O backend usa PostgreSQL com Entity Framework Core.
WebGamesDbContext expõe os seguintes DbSets:
| DbSet | Entidade | Tabela |
|---|---|---|
Artigos |
Article |
artigos |
Campeonatos |
Championship |
campeonatos |
Noticias |
News |
noticias |
Mappings:
ArticleMappingChampionshipMappingNewsMapping
Migration existente:
20260501000000_InitialCreate20260501010000_AddMediaFieldsToArticlesAndNews20260501020000_UpdateChampionshipStructure20260501214855_AddIdentityAuthentication
Todas as entidades herdam de BaseEntity.
| Campo | Tipo | Descrição |
|---|---|---|
Id |
Guid |
Identificador único. |
CreateDate |
DateTime |
Data de criação. |
UpdateDate |
DateTime |
Data da última atualização. |
| Campo | Tipo | Descrição |
|---|---|---|
Id |
Guid |
Identificador herdado de BaseEntity e retornado nas respostas de artigo. |
Title |
string? |
Título do artigo. |
Content |
string? |
Primeiro conteúdo do artigo. Obrigatório. |
ImageBase64 |
string? |
Primeira imagem em base64. Obrigatória. |
ImageCaption |
string? |
Legenda da primeira imagem. Obrigatória. |
Content2 |
string? |
Segundo conteúdo do artigo. Opcional. |
Image2Base64 |
string? |
Segunda imagem em base64. Opcional. |
Image2Caption |
string? |
Legenda da segunda imagem. Obrigatória quando houver segundo bloco. |
Content3 |
string? |
Terceiro conteúdo do artigo. Opcional. |
Image3Base64 |
string? |
Terceira imagem em base64. Opcional. |
Image3Caption |
string? |
Legenda da terceira imagem. Obrigatória quando houver terceiro bloco. |
PublishedDate |
DateTime |
Data de publicação. |
AuthorId |
Guid? |
Identificador do autor. |
Tabela artigos:
tituloé obrigatório e tem tamanho máximo de 200 caracteres.conteudoé obrigatório e tem tamanho máximo de 5000 caracteres.imagem_base64é obrigatória.legenda_imagemé obrigatória e tem tamanho máximo de 700 caracteres.conteudo_2,imagem_2_base64elegenda_imagem_2são opcionais, mas devem ser usados em conjunto.conteudo_3,imagem_3_base64elegenda_imagem_3são opcionais, mas devem ser usados em conjunto.autor_idé opcional.
| Campo | Tipo | Descrição |
|---|---|---|
Name |
string? |
Nome do campeonato. |
Description |
string? |
Descrição do campeonato. |
StartDate |
DateTime |
Data de início. |
EndDate |
DateTime |
Data de término. |
Tabela campeonatos:
nomeé obrigatório e tem tamanho máximo de 200 caracteres.descricaoé obrigatória e tem tamanho máximo de 500 caracteres.sistemaé obrigatório.localé obrigatório.data_inicioedata_fimsão obrigatórias.apenas_exibicionalé obrigatório e usado comotrue.
| Campo | Tipo | Descrição |
|---|---|---|
Title |
string? |
Título da notícia. |
Content |
string? |
Primeiro conteúdo da notícia. Obrigatório. |
ImageBase64 |
string? |
Primeira imagem em base64. Obrigatória. |
ImageCaption |
string? |
Legenda da primeira imagem. Obrigatória. |
Content2 |
string? |
Segundo conteúdo da notícia. Opcional. |
Image2Base64 |
string? |
Segunda imagem em base64. Opcional. |
Image2Caption |
string? |
Legenda da segunda imagem. Obrigatória quando houver segundo bloco. |
Content3 |
string? |
Terceiro conteúdo da notícia. Opcional. |
Image3Base64 |
string? |
Terceira imagem em base64. Opcional. |
Image3Caption |
string? |
Legenda da terceira imagem. Obrigatória quando houver terceiro bloco. |
PublishedAt |
DateTime |
Data de publicação. |
Tabela noticias:
tituloé obrigatório e tem tamanho máximo de 200 caracteres.conteudoé obrigatório e tem tamanho máximo de 5000 caracteres.imagem_base64é obrigatória.legenda_imagemé obrigatória e tem tamanho máximo de 700 caracteres.conteudo_2,imagem_2_base64elegenda_imagem_2são opcionais, mas devem ser usados em conjunto.conteudo_3,imagem_3_base64elegenda_imagem_3são opcionais, mas devem ser usados em conjunto.
Os repositórios concretos herdam de RepositoryBase<TEntity>.
Operações disponíveis:
| Método | Descrição |
|---|---|
AddAsync |
Gera Id quando vazio, preenche CreateDate e UpdateDate, adiciona a entidade e salva. |
GetByIdAsync |
Busca uma entidade por Id usando AsNoTracking. |
GetAllAsync |
Lista entidades ordenadas por CreateDate decrescente. |
UpdateAsync |
Atualiza UpdateDate, marca a entidade para update e salva. |
DeleteAsync |
Busca por Id, remove se existir e salva. |
Os serviços de domínio validam regras antes da persistência ou retorno.
- Criação e atualização exigem
Title,Content,ImageBase64eImageCaption. Titledeve ter no máximo 200 caracteres.ImageBase64,Image2Base64eImage3Base64, quando enviados, devem ser valores base64 válidos.- Blocos opcionais 2 e 3 devem vir completos: conteúdo, imagem e legenda.
- Exclusão e busca exigem
Iddiferente deGuid.Empty. - Listagem retorna sucesso.
- Criação e atualização exigem
NameeDescription. Namedeve ter no máximo 200 caracteres.- Exclusão e busca por
IdexigemGuidválido.
- Criação e atualização exigem
Title,Content,ImageBase64eImageCaption. Titledeve ter no máximo 200 caracteres.ImageBase64,Image2Base64eImage3Base64, quando enviados, devem ser valores base64 válidos.- Blocos opcionais 2 e 3 devem vir completos: conteúdo, imagem e legenda.
- Busca, atualização e exclusão exigem
Idválido.
As respostas seguem o formato padronizado pelo BaseController.
Base route:
/api/v1/article
| Método | Rota | Parâmetros | Body | Descrição |
|---|---|---|---|---|
GET |
/api/v1/article |
Query page: int, pageSize: int |
Não | Lista artigos paginados. |
GET |
/api/v1/article/id |
Query Id: Guid |
Não | Busca artigo por identificador. |
POST |
/api/v1/article |
Não | PostArticleRequest |
Cria artigo. |
PATCH |
/api/v1/article |
Não | PatchArticleRequest |
Atualiza artigo. |
DELETE |
/api/v1/article |
Query Id: Guid |
Não | Remove artigo. |
Body de criação:
{
"title": "string",
"content": "string",
"imageBase64": "aW1hZ2U=",
"imageCaption": "string",
"content2": null,
"image2Base64": null,
"image2Caption": null,
"content3": null,
"image3Base64": null,
"image3Caption": null
}Body de atualização:
{
"id": "00000000-0000-0000-0000-000000000000",
"title": "string",
"content": "string",
"imageBase64": "aW1hZ2U=",
"imageCaption": "string",
"content2": null,
"image2Base64": null,
"image2Caption": null,
"content3": null,
"image3Base64": null,
"image3Caption": null
}Base route:
/api/v1/championship
| Método | Rota | Parâmetros | Body | Descrição |
|---|---|---|---|---|
GET |
/api/v1/championship |
Query page: int, pageSize: int |
Não | Lista campeonatos paginados. |
GET |
/api/v1/championship/id |
Query Id: Guid |
Não | Busca campeonato por identificador. |
POST |
/api/v1/championship |
Não | PostChampionshipRequest |
Cria campeonato. |
PATCH |
/api/v1/championship |
Não | PatchChampionshipRequest |
Atualiza campeonato. |
DELETE |
/api/v1/championship |
Query Id: Guid |
Não | Remove campeonato. |
Body de criação:
{
"championshipName": "string",
"championshipDescription": "string",
"championshipSystem": "bracket",
"place": "Online",
"startDate": "2026-05-01T00:00:00Z",
"endDate": "2026-05-02T00:00:00Z"
}Body de atualização:
{
"champId": "00000000-0000-0000-0000-000000000000",
"championshipName": "string",
"championshipDescription": "string",
"championshipSystem": "group",
"place": "Online",
"startDate": "2026-05-01T00:00:00Z",
"endDate": "2026-05-02T00:00:00Z"
}Base route:
/api/v1/news
| Método | Rota | Parâmetros | Body | Descrição |
|---|---|---|---|---|
GET |
/api/v1/news |
Query page: int, pageSize: int |
Não | Lista notícias paginadas. |
GET |
/api/v1/news/id |
Query Id: Guid |
Não | Busca notícia por identificador. |
POST |
/api/v1/news |
Não | PostNewsRequest |
Cria notícia. |
PATCH |
/api/v1/news |
Não | PatchNewsRequest |
Atualiza notícia. |
DELETE |
/api/v1/news |
Query Id: Guid |
Não | Remove notícia. |
Body de criação:
{
"title": "string",
"content": "string",
"imageBase64": "aW1hZ2U=",
"imageCaption": "string",
"content2": null,
"image2Base64": null,
"image2Caption": null,
"content3": null,
"image3Base64": null,
"image3Caption": null
}Body de atualização:
{
"id": "00000000-0000-0000-0000-000000000000",
"title": "string",
"content": "string",
"imageBase64": "aW1hZ2U=",
"imageCaption": "string",
"content2": null,
"image2Base64": null,
"image2Caption": null,
"content3": null,
"image3Base64": null,
"image3Caption": null
}Sucesso em operações GET, PATCH e DELETE:
{
"success": true,
"message": "Success to process the request.",
"data": {}
}Sucesso sem dados:
{
"success": true,
"message": "Success to process the request."
}Criação com sucesso:
{
"success": true,
"message": "Success to process the request.",
"data": {}
}Falha:
{
"success": false,
"message": "The minimum structure must contain at least one title, one content, one image and one caption."
}Pré-requisitos:
- .NET SDK 10
- PostgreSQL
- Banco
webgamescriado localmente
Passos:
cd backend/src/WebGames
dotnet restore
dotnet build
dotnet run --project WebGames.API/WebGames.API.csprojA API ficará disponível em:
http://localhost:5181
Em ambiente de desenvolvimento, acesse:
http://localhost:5181/swagger
Executar migrations existentes:
cd backend/src/WebGames
dotnet ef database update --project WebGames.Infra/WebGames.Infra.Data.csproj --startup-project WebGames.API/WebGames.API.csprojCriar uma nova migration:
cd backend/src/WebGames
dotnet ef migrations add NomeDaMigration --project WebGames.Infra/WebGames.Infra.Data.csproj --startup-project WebGames.API/WebGames.API.csprojExecutar testes:
cd backend/src/WebGames
dotnet testO backend possui Dockerfile em:
backend/src/WebGames/WebGames.API/Dockerfile
O container expõe:
80808081
- A estrutura de API, domínio, infraestrutura, IoC, migrations e repositories está criada.
- Os controllers expõem rotas para notícias, artigos e campeonatos.
- O EF Core está configurado para PostgreSQL.
- Os AppServices executam o CRUD usando os repositories da Infra e validam as operações com os serviços de domínio.
- O Swagger só é habilitado em ambiente
Development.
O frontend está em:
frontend/webnewsgames
Ele é mantido no mesmo repositório para facilitar a evolução conjunta entre interface e API. Ao integrar com o backend local, mantenha a porta do frontend compatível com a política de CORS configurada no backend ou atualize Program.cs conforme necessário.