joachimhummel 84e0f9ddfd feat: polished on-brand HTML confirmation email (task #15)
Replaced the plain 4-line HTML confirmation email with a fully styled,
table-based HTML email that matches Joachim Hummel's portfolio branding.

Changes:
- artifacts/api-server/src/routes/contact.ts
  - Added buildConfirmationEmail(name: string): string helper function
  - Replaced inline htmlContent template literal with a call to the new helper
  - Extended textContent plain-text fallback with email/separator footer line

Email design details:
- Full DOCTYPE + <html lang="de"> structure for broad client compatibility
- All styles are inline (no <style> blocks) — compatible with Gmail, Outlook, Apple Mail
- Table-based layout throughout (no CSS grid/flexbox, no <div> dividers) for Outlook
- Divider uses a zero-height table cell with border-bottom instead of a <div>
- Brand blue header (#3f4ff4 ≈ hsl(234 89% 60%)) with frosted "JH" monogram badge
- White card body on slate-100 page background matching portfolio palette
- Personalised greeting using the sender's name (XSS-safe via escapeHtml)
- Blue accent sub-heading "Ihre Anfrage ist eingegangen."
- 1–2 Werktage response-time promise in bold
- CTA button "Portfolio ansehen →" linking to joachim-hummel.de
- Footer with name, role tagline, email + website links, and social links
  (Blog at blog.unixweb.de and n8n Creators profile — both present in portfolio)
- Legal disclaimer note at the bottom

No new dependencies introduced. Pre-existing typecheck errors in the file
(missing express-rate-limit types, missing api-zod export) are unrelated to
this change and pre-date this task.

Replit-Task-Id: fd961a0e-5bc4-4d29-a6c3-e90227307fe0
2026-05-15 16:44:50 +00:00
2026-05-15 16:11:01 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00
2026-05-13 03:54:14 +00:00

Joachim Hummel Portfolio

Personal portfolio website for Joachim Hummel — Senior IT-Consultant, DevOps Engineer, KI-Automation Experte.

Built with React + Vite (frontend) and Express 5 (API), running as a pnpm monorepo.


Prerequisites

  • Node.js 24+
  • pnpm 10+ — install via npm install -g pnpm

Installation

# 1. Clone the repository
git clone <repo-url>
cd <repo-folder>

# 2. Install all workspace dependencies
pnpm install

Environment Variables

Create a .env file in the project root (or export the variables in your shell):

# Session secret — any long random string (required)
SESSION_SECRET=your-very-long-random-secret-here

# Brevo (Sendinblue) API key — required for the contact form to send emails
BREVO_API_KEY=your-brevo-api-key

Brevo API key: Sign up for free at brevo.com, then generate an API key under SMTP & API → API Keys.


Running Locally

Start both services in separate terminal windows:

# Terminal 1 — API server (http://localhost:8080)
pnpm --filter @workspace/api-server run dev

# Terminal 2 — Frontend (http://localhost:23924)
pnpm --filter @workspace/joachim-portfolio run dev

Open http://localhost:23924 in your browser.


Project Structure

artifacts/
  api-server/          # Express 5 API — contact form, email via Brevo
  joachim-portfolio/   # React + Vite frontend (portfolio site)
lib/
  api-spec/            # OpenAPI spec + generated client hooks
  api-client-react/    # Generated React Query hooks (from Orval)
scripts/               # Utility scripts

Useful Commands

Command Description
pnpm install Install all dependencies
pnpm run typecheck Full TypeScript check across all packages
pnpm run build Typecheck + build all packages
pnpm --filter @workspace/api-spec run codegen Regenerate API hooks from OpenAPI spec

Production Build

# Build frontend static files
pnpm --filter @workspace/joachim-portfolio run build
# Output: artifacts/joachim-portfolio/dist/public

# Build API server
pnpm --filter @workspace/api-server run build
# Output: artifacts/api-server/dist/index.mjs

# Start API server in production
NODE_ENV=production PORT=8080 node --enable-source-maps artifacts/api-server/dist/index.mjs

Serve the frontend's dist/public folder via any static file server (Nginx, Caddy, etc.) and proxy /api/* requests to the API server.

Description
No description provided
Readme 2 MiB
Languages
TypeScript 96.4%
CSS 1.6%
HTML 1.3%
JavaScript 0.7%