An internal (intranet) messaging, announcement, technical support and reporting platform for a municipality. Built with ASP.NET Core + React + MongoDB, integrated with Active Directory, fully Dockerized. The UI was ported to production pixel-for-pixel from a glassmorphic design.
More: real Active Directory lab + MongoDB collections
The AD/LDAP integration was also validated end-to-end against a real Windows Server domain controller (belediye.local, LDAPS), not just the mock provider:
Real AD forest (Get-ADForest / Get-ADDomain) |
Real AD OUs — one per directorate (Get-ADOrganizationalUnit) |
![]() |
![]() |
MongoDB collections backing the app (mongosh):
- Real-time messaging (SignalR): groups (General, Managers, 20 departments) + 1-to-1 chat, file/image sharing (GridFS, 20 MB, magic-byte validation), paste-to-attach (Ctrl+V), media tab, unread badges + notification panel.
- Announcements: home carousel (auto-rotate, type badges, detail + shareable link), rich-text news authoring.
- Technical Support (tickets): category/priority, assignment, status, per-ticket isolated chat.
- Reports: weekly IT support report — LLM (Ollama/Llama 3.1) analysis + QuestPDF; falls back to a Turkish template when the LLM is unavailable.
- Active Directory: LDAPS login + automatic user/role sync; bootstrap admin for AD-less setup; AD config from the UI.
- Dynamic department registry: departments/groups are auto-discovered from whatever AD sends (not a hardcoded list) — new directorates get a group automatically, no redeploy needed; which department maps to IT/HR admin roles is configurable from the UI.
- Roles & authorization: GENEL_ADMIN, IK_ADMIN, DEPT_MANAGER, DEPT_MEMBER, SOSYAL_MEDYA (DB-authoritative
[RequireRole]). - Business rules: rate limiting (1 message / 3s), Turkish profanity filter, deactivated-account indicator.
- Dark theme, mobile responsive, global search.
| Layer | Technology |
|---|---|
| Backend | ASP.NET Core Web API (.NET 8), SignalR, Hangfire |
| Frontend | React 19 + TypeScript + Vite, nginx |
| Database | MongoDB (+ GridFS) |
| Identity | LDAP/Active Directory (System.DirectoryServices.Protocols) |
| LLM | Ollama — llama3.1:8b |
| QuestPDF | |
| Containers | Docker Compose |
git clone https://github.com/fuatsimsek/bagchat.git && cd bagchat
docker compose up -d --build- Frontend: http://localhost:3000 · Backend/Swagger: http://localhost:8080/swagger
- First login (AD-less bootstrap admin):
admin@belediye.local/Bootstrap!2025
Run the LLM inside Docker (optional):
docker compose -f docker-compose.yml -f docker-compose.ollama.yml up -d
docker exec -it belediye-ollama ollama pull llama3.1:8bProduction (secrets from .env):
cp .env.example .env # change JWT_KEY and BOOTSTRAP_PASSWORD
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build- Unit tests:
backend/BelediyeIntranet.Tests(xUnit + coverlet) — pure services at 82–100% coverage. - System/integration:
tests/test_system.py(end-to-end against the live stack). - Health/monitoring:
scripts/healthcheck.py. - GitHub Actions: ci.yml (backend test+coverage, frontend lint+build, compose integration), monitoring.yml, deploy.yml (self-hosted runner).
backend/BelediyeIntranet.API ASP.NET Core Web API
backend/BelediyeIntranet.Tests xUnit unit tests
frontend/ React + Vite (glassmorphic UI)
scripts/ · tests/ healthcheck + integration test
docker-compose*.yml base / prod / ollama overrides
The appsettings.json and docker-compose.yml in this repo contain dev placeholder values only
(Jwt:Key, bootstrap password). Always override them via .env in production and never commit real
secrets (.env is in .gitignore).
Built for internal municipal use.














