# 🎨 Playground Frontend

This is the **frontend** of the Playground project.
Built with **Angular 21** and **Angular Material**, including a light/dark theme toggle and
multi-language support (EN/DE) via **ngx-translate**.

The app is built as a static **Single Page Application (SPA)** served by **NGINX**,
deployed at:
👉 [https://app.andreas-dahm.eu](https://app.andreas-dahm.eu)

---

## 🧩 Tech Stack

| Component | Purpose |
| --------- | ------- |
| Angular 21 | Frontend framework (standalone components, signals, zoneless change detection) |
| Angular Material 21 | UI components & theming |
| Tailwind CSS 4 | Utility-first styling (CSS-first config, no `tailwind.config.js`) |
| ngx-translate 18 | i18n / instant translation |
| Babylon.js 9 | WebGL/WebGPU rendering for the algorithm demos |
| Swiper 14 | Image carousels in the project dialogs |
| Angular Service Worker | PWA / offline caching |
| NGINX | Serves the compiled SPA |
| Docker + Gitea Actions | Automated build, test & image publishing |

Requires **Node.js 22**.

---

## 📁 Project Structure

```
playground-frontend/
├─ src/
│  ├─ app/
│  │  ├─ layout/            # app shell, topbar, dialogs
│  │  ├─ pages/             # about, projects, algorithms, imprint, stopwatch, not-found
│  │  ├─ service/           # theme, language, SEO, GPU capability
│  │  ├─ shared/            # reusable components & helpers
│  │  ├─ constants/
│  │  ├─ app.config.ts
│  │  └─ app.routes.ts
│  ├─ assets/
│  │  ├─ i18n/              # en.json / de.json (keys must stay in sync)
│  │  ├─ logos/, flags/, icons/
│  │  └─ projects/          # project screenshots
│  ├─ tailwind.css          # Tailwind entry + @theme tokens
│  ├─ styles.scss           # Material theme setup & component overrides
│  └─ index.html
├─ scripts/check-i18n.mjs   # fails the build on i18n key drift
├─ Dockerfile
├─ nginx.conf
├─ ngsw-config.json         # service worker caching rules
├─ lighthouserc.json
└─ .gitea/workflows/build-Frontend-a.yml
```

---

## 🚀 Local Development

**1. Install dependencies**
```bash
npm install
```

**2. Start development server**
```bash
ng serve --open
```
App runs at http://localhost:4200

**3. Docker build (local)**
```bash
docker build -t playground-frontend:local .
docker run -p 8080:80 playground-frontend:local
```
Then open http://localhost:8080

---

## 🧪 Scripts

| Command | Purpose |
| ------- | ------- |
| `npm start` | Dev server |
| `npm run build` | Production build |
| `npm run watch` | Rebuild on change (development configuration) |
| `npm test` | Unit tests (Karma + Jasmine, headless Chrome) |
| `npm run lint` | ESLint over `src/**/*.ts` and `src/**/*.html` |
| `npm run i18n:check` | Verifies `en.json` and `de.json` share the exact same keys |

---

## ⚙️ Gitea Actions (CI/CD)

CI/CD runs on a **self-hosted Gitea instance** at `git.andreas-dahm.eu`.
Workflow file: `.gitea/workflows/build-Frontend-a.yml`

Triggered on every push to `main` and on pull requests targeting `main`.

**Job 1 — `quality-check`** (runs on both pushes and PRs):

1. Lint & type check — `npm run lint`
2. i18n key sync — `npm run i18n:check`
3. Unit tests — `npx ng test --watch=false`
4. Production build — `npx ng build --configuration production`
5. Lighthouse audit — `npx lhci autorun` (performance & SEO)

**Job 2 — `docker`** (only on a push to `main`, and only if `quality-check` passed):

Builds the image and pushes it to the Gitea container registry at `git.andreas-dahm.eu`
with these tags:

```
git.andreas-dahm.eu/<owner>/playground:frontend-a-<branch>
git.andreas-dahm.eu/<owner>/playground:frontend-a-<branch>-<short-sha>
git.andreas-dahm.eu/<owner>/playground:frontend-a-main
```

**Required repository secret:**

| Name | Description |
| ---- | ----------- |
| `TOKEN_GITEA` | Gitea access token used to authenticate against the container registry |

---

## 🌐 Deployment

The built image is deployed via the `playground-deploy` repository on the Hostinger KVM
server using **Traefik**:

```bash
docker compose pull
docker compose up -d
```

✅ Live site at https://app.andreas-dahm.eu

---

## 🪄 Maintainer

Andreas Dahm
📧 andreas.dahm@gmail.com
🌐 https://andreas-dahm.eu
