Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fea5050
Customize theme for Neumann brand
JesseWynants Jan 9, 2026
7d5b345
Revert language selector to show full locale name
JesseWynants Jan 9, 2026
6264140
Add locale-aware footer with translations
JesseWynants Jan 9, 2026
3c1ea29
Hide categories on story cards
JesseWynants Jan 9, 2026
c01bf94
Fix hero width and center header on wide screens
JesseWynants Jan 9, 2026
c5f54fa
Fix hero to be full viewport width, preserve header width
JesseWynants Jan 9, 2026
83c7f70
Simplify container centering
JesseWynants Jan 9, 2026
8f60572
Match hero width constraints to header
JesseWynants Jan 9, 2026
ca4f308
Align hero width with header container
JesseWynants Jan 9, 2026
0158f2f
Add max-height to hero (660px)
JesseWynants Jan 9, 2026
2cd1396
Add dark overlay gradient to main content area
JesseWynants Jan 9, 2026
3c889f7
Apply gradient directly to main element
JesseWynants Jan 9, 2026
3d7b514
Update main gradient to gray-to-black (180deg)
JesseWynants Jan 9, 2026
56aa633
Fix gradient overlay on hero and remove content padding-top
JesseWynants Jan 9, 2026
c86af90
Update hero overlay styling
JesseWynants Feb 4, 2026
881cc40
[DEV-22636] Applied redirect fix for non-asciified Japanese/Unicode s…
fgyimah Mar 23, 2026
b67b287
Merge pull request #1 from prezly/feature/dev-22636-apply-fix-for-non…
fgyimah Mar 23, 2026
832a0aa
[DEV-22883] Add anchor links support and new Meilisearch index support
fgyimah May 8, 2026
ce6484f
[DEV-22883] Updated pnpm-lock.yaml
fgyimah May 8, 2026
cf2f326
Merge pull request #3 from prezly/feature/dev-22883-add-anchor-links-…
fgyimah May 8, 2026
2b5051f
[DEV-23048] Added section heading and content snippet to search results
fgyimah May 19, 2026
25abe15
Merge pull request #4 from prezly/feature/dev-23048-incorporate-in-pa…
fgyimah May 20, 2026
fd3b464
DEV-23074: Add hidecookie query param for preview logic
boki-prezly May 25, 2026
c913e76
Merge pull request #5 from prezly/feature/dev-23074-qa-remove-the-the…
boki-prezly May 26, 2026
c616103
Merge branch 'main' of https://github.com/prezly/theme-nextjs-neumann
christianprezly May 27, 2026
5d32e6f
phase 0+1
christianprezly May 27, 2026
d727b7b
clanka 1st pass
christianprezly May 28, 2026
db61a78
sdffdfgdndg
christianprezly Jun 3, 2026
5b57f40
minor adjustments
christianprezly Jun 4, 2026
e4a5adc
more adjustments
christianprezly Jun 4, 2026
d289ad8
sticky header
christianprezly Jun 4, 2026
64d028e
search results story grid
christianprezly Jun 4, 2026
be1dd3b
header image
christianprezly Jun 4, 2026
e44305c
fix: align hero image with Neumann source layout
Jun 5, 2026
8ff6ba5
category pages
Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,6 @@ yarn-error.log*
/test-results/
/playwright-report/
/playwright/.cache/

# Visual audit / scratch artifacts
/.scratch/
44 changes: 44 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# AGENTS.md

Neumann newsroom theme — a fork of Prezly's `theme-nextjs-bea` (Next.js 15 App Router). Package name is still `theme-nextjs-bea`. Heavy brand customization lives alongside the upstream base.

## Commands (pnpm — NOT npm)
Lockfile is `pnpm-lock.yaml`. `package.json` `engines` says npm, but always use **pnpm** (Node 20).

- `pnpm dev` — runs plain `next` on **port 3000** (no port override exists; CLAUDE.md's "3003" is wrong). It will fall back to 3001/3002 if 3000 is taken.
- `pnpm check` — Biome lint + format check (this is the gate, not `lint` alone).
- `pnpm typecheck` — `tsc --noEmit --incremental`.
- `pnpm lint:fix` / `pnpm format:fix` — Biome auto-fix.
- `pnpm build` — production build.
- `pnpm test` — Playwright (`npx playwright test`); see Testing below.
- `pnpm visual:audit:live` / `:local` — screenshot diff tooling (`scripts/visual-audit.ts`, runs via `tsx`).

Quality gate after any change: `pnpm typecheck` → `pnpm check` → `pnpm build`, all clean (warnings OK).

## Verifying UI against the live source
This fork visually mirrors `https://newsroom.neumann.com/`. When matching layout/crop/spacing, measure the live source with Playwright (computed styles + `getBoundingClientRect`) before changing CSS — the source uses responsive `50vh`-style heights and `object-fit: cover`, which are easy to mis-replicate with a fixed `aspect-ratio`.

## Testing
- Tests in `tests/` (`index.spec.ts`). `playwright.config.ts` reads `.env.local` and hits `TESTS_BASE_URL` (default `http://localhost:3000`). A server must be running and `.env.local` populated.
- CI `playwright.yml` only runs on Vercel `deployment_status` events, not on push. Push CI = lint only.

## Environment
Copy `.env.example` → `.env.local`. Required: `PREZLY_ACCESS_TOKEN`, `PREZLY_NEWSROOM_UUID`, `MEILISEARCH_API_KEY`. `PREZLY_THEME_UUID` is preset. `.env.example` lists sample tokens.

## Architecture (non-obvious bits)
- Pages live under `app/[localeCode]/` (the brackets are literal dirs; quote/escape them in shell globs). Server data via `app()` helper in `src/adapters/server/`.
- **`@prezly/theme-kit-nextjs` fetches live `ThemeSettings` from Prezly's backend at runtime and overrides `DEFAULT_THEME_SETTINGS`.** For fork-specific fonts/colors that must stick, hardcode them in `src/modules/Head/components/getCssVariables.ts` and the relevant component, not just in `DEFAULT_THEME_SETTINGS`.
- `next.config.js`: images use a custom Uploadcare loader; SVGs import as React components (`@svgr/webpack`); SCSS variables + mixins are injected globally via `prependData` (don't re-import them). Wrapper chain: `withBundleAnalyzer → withThemeKitConfig → withSentryConfig`. Sentry only enables in production with a DSN and not on Vercel.

## Brand customizations (Neumann)
- Brand defaults are hardcoded in `src/theme-settings.ts` (black bg, orange `#ef7b0b` accent). `Font.FF_UNIT_PRO` is self-hosted from `public/fonts/neumann/` and declared in `src/styles/_fonts.scss`; `getGoogleFontName()` returns `null` for it.
- `custom/` is **flat files** (`NeumannFooter.tsx`, `NeumannCategoriesNav.tsx`, `*.module.scss`) imported via `@/custom/*` — not the deep barrel structure CLAUDE.md describes. `custom/neumann.scss` and `custom/fonts.css` referenced in CLAUDE.md do not exist.
- `middleware.ts` matcher already excludes `fonts/` and `*.woff2?` so self-hosted fonts aren't intercepted — preserve that if editing the matcher.

## SCSS gotchas
- `src/styles/_fonts.scss` must be **CSS-only (no `@use`)**: `prependData` injects `@use` lines at the top of every SCSS file, and `@font-face`/CSS output must come after all `@use`. Putting `@use` in that file breaks the build.
- Biome only checks `app/**`, `src/**`, `custom/**` (see `biome.json`). Files outside those are unlinted.
- TS is strict with `noUnusedLocals`/`noUnusedParameters`. Use the `@/*` path aliases in `tsconfig.json` (e.g. `@/adapters/server`, `@/modules/*`, `@/custom/*`).

## Related instruction files
`CLAUDE.md` (root + `~/.claude/CLAUDE.md`) has broader theme conventions, but several specifics are stale — trust this file and the executable config (package.json, next.config.js, middleware.ts) over CLAUDE.md where they conflict, especially the dev port and `custom/` layout.
110 changes: 110 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is the **Neumann Newsroom Theme**, a customized Next.js 15 theme for the Prezly platform. It's based on the Prezly Bea Theme but heavily customized to match the Neumann brand identity (dark theme, orange accents).

## Commands

```bash
pnpm dev # Start development server (port 3003)
pnpm build # Production build
pnpm start # Start production server
pnpm typecheck # TypeScript type checking
pnpm check # Run all Biome checks (lint + format)
pnpm lint:fix # Fix linting issues
pnpm format:fix # Fix formatting issues
pnpm test # Run Playwright tests (requires dev server running)
```

## Architecture

### Data Layer

- **Prezly Theme Kit** (`@prezly/theme-kit-nextjs`): Core data-fetching abstraction for Prezly API
- **`src/adapters/server/`**: Server-side adapters for newsroom data, routing, metadata, analytics
- **`src/adapters/client/`**: Client-side adapters for HTTP, routing, locale, i18n
- **`app()` helper** (`src/adapters/server/app.ts`): Main server-side data access - `app().newsroom()`, `app().story()`, `app().stories()`, etc.

### Routing

- **App Router with locale prefix**: Routes under `app/[localeCode]/`
- **Route definitions**: `src/adapters/server/routing.ts`
- **Middleware** (`middleware.ts`): Locale detection via `IntlMiddleware`

### Key Routes
- `(index)/` - Homepage with story listings
- `(story)/[slug]/` - Individual story pages
- `category/[slug]/` - Category pages
- `media/` - Media gallery pages
- `search/` - Search page

### Neumann Customizations

This theme has been customized for the Neumann brand. Key customization points:

1. **Theme Settings** (`src/theme-settings.ts`): Hardcoded Neumann brand colors and settings
- Does NOT pull from Prezly API - uses `DEFAULT_THEME_SETTINGS` only
- Colors: Black background (#000000), orange accent (#ef7b0b), gray text (#c1c1c1)

2. **Custom Font** (`custom/fonts.css` and `custom/fonts/`):
- FF Unit Pro font (Neumann's brand font) loaded locally
- Three weights: 300 (light), 400 (regular), 700 (bold)
- Imported in layout.tsx

3. **Custom SCSS** (`custom/neumann.scss`): Brand-specific style overrides
- Typography with FF Unit Pro font
- Card styling with orange titles
- Navigation styling (uppercase links)
- Hero image fix for positioning
- Footer styling
- Imported in `src/styles/styles.globals.scss`

4. **Custom Header Navigation** (`custom/NeumannCategoriesNav.tsx`):
- Shows categories as direct links (Press, Stories) instead of dropdown
- Sennheiser external link configured via `main_site_url` setting

5. **Custom Footer** (`custom/NeumannFooter.tsx`):
- 3-column layout: Company, Service & Support, Products
- Matches the original Neumann newsroom footer
- Copyright and legal links at bottom

6. **Modified Header Component** (`src/modules/Header/ui/Header.tsx`):
- Uses `NeumannCategoriesNav` instead of default `Categories` component
- Removed categories bar layout - categories always in header

### Path Aliases

Defined in `tsconfig.json`:
- `@/adapters/server`, `@/adapters/client` - Data layer
- `@/components/*`, `@/modules/*` - UI code
- `@/hooks`, `@/utils`, `@/icons` - Utilities
- `@/custom/*` - Neumann-specific customizations
- `@/theme-settings` - Theme configuration

### Styling

- SCSS Modules with variables in `src/styles/variables/`
- Global SCSS imports auto-prepended via `next.config.js`
- CSS variables generated from theme settings in `src/modules/Head/components/getCssVariables.ts`

### Environment Variables

Required in `.env.local`:
- `PREZLY_ACCESS_TOKEN` - API access token
- `PREZLY_NEWSROOM_UUID` - Newsroom identifier
- `PREZLY_THEME_UUID` - Theme preset identifier (use `73015107-ac86-418b-9120-4ffa439d5c0f`)
- `MEILISEARCH_API_KEY` - For search functionality

## Neumann Brand Colors

| Purpose | Color | Hex |
|---------|-------|-----|
| Background | Black | #000000 |
| Card Background | Dark Gray | #2d2d2d |
| Accent/Links | Orange | #ef7b0b |
| Primary Text | White | #ffffff |
| Secondary Text | Gray | #c1c1c1 |
| Tertiary Text | Light Gray | #cccccc |
Loading