Skip to content

AdrianDeutsch/newscore

Repository files navigation

NewsCore

NewsCore – cloud-natives Nachrichtenportal

CI Backend Coverage Frontend Coverage Nuxt 3 Java 21 Spring Boot 3 GraphQL MIT License

NewsCore ist ein cloud-natives, hochverfügbares Nachrichtenportal: redaktionelle Inhalte aus einem CMS, ausgeliefert über eine GraphQL-API (Backend-for-Frontend) an ein server-seitig gerendertes Nuxt-3-Frontend — ausgelegt für High-Traffic und GitOps-Betrieb auf OpenShift/Kubernetes.

Live-Demo: Startseite → Artikeldetail → Volltextsuche
Ein echter End-to-End-Lauf: Startseite mit Ressort-Filter → Artikeldetail → Volltextsuche — Nuxt 3 SSR über die GraphQL-API (auch als MP4).

📑 Inhaltsverzeichnis

⭐ Highlights

  • Lauffähiger Vertical Slice in einem Befehldocker compose up --build startet GraphQL-Gateway + SSR-Frontend.
  • N+1-frei by design — nested author/category werden per DataLoader (@BatchMapping) gebatcht.
  • Austauschbare Datenquelle — Resolver kennen nur Service-Interfaces; In-Memory-Mock, Sophora-CMS und ElasticSearch sind reine Profil-Schalter, ohne Resolver-Änderung.
  • Hohe Testabdeckung, in CI erzwungen — Backend 98 %, Frontend 96 % (Gate ≥ 80 %).
  • Dokumentierte Entscheidungen — jede Technologiewahl als ADR.

📸 Screenshots

Startseite Artikeldetail Suche
Startseite — Ressort-Filter + Artikel-Grid Artikeldetail — Breadcrumb, Autor, Cover Suche — search("klima") → 2 Treffer

✨ Features

Feature Status Technologie Anmerkung
GraphQL-BFF-Gateway Spring Boot 3, spring-graphql, Java 21 Schema-first
N+1-Vermeidung DataLoader via @BatchMapping author + category
Application-Cache Caffeine (@Cacheable) ADR-003
SSR-Frontend Nuxt 3, Vue 3, TypeScript useAsyncData
GraphQL-Client urql (ssrExchange) ADR-001
Edge-Caching Varnish (VCL) + Apache (TLS/gzip/Header) ADR-008, event-getriebenes PURGE
Volltextsuche ElasticSearch 8 (Profil-gesteuert) ADR-004, Testcontainers
CMS-Datenquelle Sophora-HTTP-Adapter (Profil sophora) ADR-010, Default In-Memory
Event-Streaming Kafka + Avro/Schema-Registry + DLQ ADR-011, EmbeddedKafka + Mock-Registry
Aktive Cache-Invalidierung article.events → ES-Reindex + Evict schließt den Loop zu ADR-003
Analytics → PostgreSQL analytics-service (Node, kafkajs + pg) search.events + user.events (Pageviews) → Postgres
Observability-Endpoint Actuator + /actuator/prometheus Grafana folgt
Lokales Stack-Setup docker-compose (ES + Kafka + Postgres) ein Befehl
CI-Pipeline GitLab CI (5 Stages) Coverage-Gate
K8s/OpenShift + GitOps Helm-Umbrella-Chart + ArgoCD ADR-006, HPA/PDB/NetworkPolicy
Observability Prometheus + Grafana + Loki ADR-007, Dashboards/Alerts/JSON-Logs
Distributed Tracing OpenTelemetry + Tempo (OTLP) ADR-009, Trace↔Logs-Korrelation

🏗 Architektur

flowchart TD
    User([Browser]) -->|HTTPS| Apache[Apache Reverse Proxy<br/>TLS · Rate-Limit]
    Apache --> Varnish[Varnish Cache]
    Varnish -->|Cache-Miss| Nuxt[Nuxt 3 SSR<br/>urql]
    Nuxt -->|GraphQL| GW[GraphQL API Gateway<br/>Spring Boot · BFF<br/>DataLoader · Caffeine]
    GW --> CMS[(Sophora CMS)]
    GW --> ES[(ElasticSearch 8)]
    GW --> PG[(PostgreSQL)]
    GW --> Kafka{{Apache Kafka}}
    Kafka --> Analytics[Analytics-Service]
    GW --> Prom[Prometheus / Grafana / Loki]

    classDef done fill:#ecfdf5,stroke:#00a862,color:#0b1220;
    classDef soon fill:#f1f5f9,stroke:#94a3b8,color:#475569,stroke-dasharray:4 3;
    class Nuxt,GW,ES,Kafka,Analytics,PG,Prom,Apache,Varnish done;
    class CMS soon;
Loading

Grün = in dieser Iteration umgesetzt · gestrichelt = vorgesehen (Roadmap). Begründung der zentralen Schicht: ADR-002 — GraphQL BFF.

🚀 Quick Start

Variante A — Komplettes Stack (Docker)

docker compose up --build
# Frontend:  http://localhost:3000
# GraphiQL:  http://localhost:8080/graphiql

Variante B — Apps einzeln (lokal)

# Terminal 1 — API-Gateway (Maven Wrapper lädt Maven beim ersten Lauf)
cd apps/api-gateway && ./mvnw spring-boot:run

# Terminal 2 — Frontend
cd apps/frontend && npm install && npm run dev

Hooks aktivieren (nach dem Clone)

git config core.hooksPath .githooks
chmod +x .githooks/*

🎯 Teststrategie

Strikte Testpyramide — Bulk an Unit-Tests, gezielte Integrationstests, wenige E2E (Roadmap):

        ┌────────────────────┐
        │   E2E (Playwright) │   🔜 Roadmap
        ├────────────────────┤
        │  Integrationstests │   GraphQlTester · Testcontainers (ES) · EmbeddedKafka
        ├────────────────────┤
        │     Unit-Tests     │   JUnit 5 · Vitest  (Bulk)
        └────────────────────┘
Schicht Tooling Umfang
Backend JUnit 5, Mockito, AssertJ 52 Unit-Tests
Backend GraphQlTester, Testcontainers (ES), EmbeddedKafka (+ Mock-Schema-Registry) 11 Integrationstests
Frontend Vitest, Vue Test Utils, happy-dom 16 Tests
analytics-service Vitest (gemockt: kafkajs + pg) 12 Tests
cd apps/api-gateway          && ./mvnw verify                        # Backend: Tests + JaCoCo-Gate
cd apps/frontend             && npm run test:unit -- --run --coverage
cd services/analytics-service && npm run test:unit -- --run --coverage

Coverage-Gate ≥ 80 % in allen Modulen erzwungen (Frontend ~95 %, analytics-service 100 % der Logik-Schicht). Flaky-Test-Policy: FLAKY-TESTS.md.

🔁 CI/CD Pipeline

GitHub Actions (.github/workflows/ci.yml) baut und testet bei jedem Push/PR alle Module parallel (Status oben als Badge): api-gateway (./mvnw verify inkl. Testcontainers-ES + EmbeddedKafka), frontend, analytics-service (Lint + Tests + Build) sowie helm lint/template.

Die produktive GitLab-CI + ArgoCD-GitOps-Pipeline (.gitlab-ci.yml) bildet den Deploy-Pfad gemäß Spec ab — fünf Stages mit pfadbasierten rules:

validate ─→ test ─→ build ─→ security ─→ deploy-staging ─→ deploy-prod (manuell)
 lint        unit/IT   images     trivy      ArgoCD sync       ArgoCD sync
  • validate — ESLint + type-check (Frontend), Checkstyle (Backend)
  • test — Unit + Integration, Coverage als Report/Artifact
  • build — Container-Images → Registry (nur main/develop)
  • security — Trivy-Scan, kein Merge bei HIGH/CRITICAL CVEs
  • deploy — GitOps via ArgoCD (Staging automatisch, Prod manuelles Gate)

📁 Projektstruktur

newscore/
├── apps/
│   ├── api-gateway/        # Spring Boot 3 · GraphQL BFF · ES · Kafka (eigene README)
│   └── frontend/           # Nuxt 3 · urql · SSR (eigene README)
├── services/
│   └── analytics-service/  # Node/TS · Kafka → PostgreSQL (eigene README)
├── infrastructure/
│   ├── helm/newscore/      # Umbrella-Chart (Deploy/Svc/HPA/PDB/Ingress/NetworkPolicy/ServiceMonitor)
│   ├── argocd/             # ArgoCD Application-Manifeste (staging/prod)
│   ├── prometheus/         # Scrape-Config + Alert-Rules
│   ├── grafana/            # Provisioning (Datasources) + Dashboards
│   ├── loki/               # Promtail-Config (Log-Aggregation)
│   ├── varnish/            # default.vcl (Edge-Cache, TTLs, PURGE)
│   └── apache/             # Reverse-Proxy (TLS/gzip/Security-Header)
├── docs/
│   ├── adr/                # Architecture Decision Records
│   ├── defects/            # Defect-Template + Bugs
│   └── images/banner.svg
├── .github/                # Actions-CI, Issue/PR-Templates, Dependabot, CODEOWNERS
├── .githooks/              # pre-commit · commit-msg · pre-push
├── docker-compose.yml      # lokales Stack-Setup (ES + Kafka + Registry + Postgres)
├── .gitlab-ci.yml          # GitLab-CI/GitOps-Pipeline (Deploy)
├── CONTRIBUTING.md · FLAKY-TESTS.md · LICENSE
└── README.md

🐞 Defect Management

Bugs werden in docs/defects/ nach dem Defect-Template dokumentiert (Severity, Repro-Schritte, Root Cause, Regressionstest).

📐 Architecture Decision Records

ADR Entscheidung
ADR-001 urql als GraphQL-Client im Frontend
ADR-002 GraphQL-Gateway nach BFF-Pattern
ADR-003 Caffeine als In-Process-Cache
ADR-004 ElasticSearch als Volltextsuche (Profil-gesteuert)
ADR-005 Kafka-Eventing mit JSON-Serialisierung + DLQ
ADR-006 Helm-Umbrella-Chart + ArgoCD-GitOps
ADR-007 Observability mit Prometheus, Grafana und Loki
ADR-008 Varnish-Edge-Cache + Apache-Reverse-Proxy
ADR-009 Distributed Tracing mit OpenTelemetry + Tempo
ADR-010 Sophora-CMS als austauschbare Datenquelle
ADR-011 Avro + Schema-Registry (ersetzt ADR-005 §2)

🛣 Roadmap

  • Volltextsuche: ElasticSearch-SearchService (profil-gesteuert, Testcontainers) — erledigt
  • Eventing (Epic 4): Kafka-Producer/Consumer, DLQ, aktive Cache-Invalidierung, Analytics → Postgres — erledigt
  • Plattform (Epic 5): Helm-Umbrella-Chart, ArgoCD-Apps, HPA/PDB, NetworkPolicies (OpenShift) — erledigt
  • Observability (Epic 6): Prometheus-Scrape/Alerts, Grafana-Dashboards, JSON-Logs → Loki — erledigt
  • Caching (Epic 3): Varnish-VCL + Apache-Proxy, event-getriebenes PURGE — erledigt
  • Tracing: OpenTelemetry + Tempo (OTLP), Trace↔Logs-Korrelation — erledigt
  • Datenanbindung: Sophora-CMS-HTTP-Adapter (Profil sophora), Default In-Memory — erledigt
  • Analytics-Eventing: user.pageview-Producer im Frontend — erledigt
  • Eventing-Härtung: Avro + Confluent Schema-Registry (ersetzt JSON aus ADR-005) — erledigt
  • Frontend: GraphQL-Codegen, Playwright-E2E, i18n, PWA

📄 Lizenz

MIT

About

Cloud-natives Medienportal — GraphQL BFF (Spring Boot 3, Java 21) + Nuxt 3 SSR · Kafka/Avro · ElasticSearch · Varnish/Apache · Helm/ArgoCD · Observability

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors