Skip to content

Commit f1b9506

Browse files
committed
chore: SEO + perf cleanup, drop framer-motion, optimize sample images
- seo: add per-locale canonical URLs via getAlternates(path, locale); include /about, /contact, /privacy, /terms in sitemap.xml - a11y: set <html lang> from URL locale via inline init script before paint (server-side read would opt-out of static rendering) - a11y: split nested button in ScenePicker custom-thumb (remove × becomes a sibling button instead of a child of the select button) - perf: replace framer-motion in Nav mega-menu and AnimatedGrid with CSS animations (drops the dep + bundle weight) - perf: re-encode sample/scene JPEGs (10.5MB → 1MB exif sample, ~3MB → ~350KB scene photos) - tests: add sitemap, metadata, AnimatedGrid, ToolHeading specs (now 871 tests across 68 files)
1 parent cff5a1c commit f1b9506

62 files changed

Lines changed: 523 additions & 176 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ PhotoTools is an educational photography application — free calculators, simul
2323
- `npm run dev` — start dev server with Turbopack at `http://localhost:3200`
2424
- `npm run build` — production build via `next build`
2525
- `npm run start` — serve production build locally
26-
- `npm test` — run Vitest tests (781 tests across 56 files)
26+
- `npm test` — run Vitest tests (869 tests across 67 files)
2727
- `npm run test:coverage` — run tests with coverage report
2828
- `npm run type-check` — run TypeScript compiler in noEmit mode
2929
- `npm run test:watch` — run tests in watch mode
@@ -72,7 +72,7 @@ src/
7272
navigation.ts Locale-aware Link, usePathname, useRouter, redirect
7373
request.ts Message loader — merges all JSON files per locale
7474
redirects.ts Centralized redirect rules (consumed by next.config.ts)
75-
metadata.ts getAlternates() helper for hreflang in page metadata
75+
metadata.ts getAlternates() helper for canonical + hreflang in page metadata
7676
messages/en/ English translations (source of truth, 41 files)
7777
messages/es/ Spanish translations (41 files)
7878
messages/ja/ Japanese translations (41 files)
@@ -243,7 +243,7 @@ Three external services provide production monitoring:
243243
- **DRY**: Avoid duplicating logic, styles, constants, or markup. Extract shared utilities, components, and data modules. When adding a feature, check if similar patterns already exist in the codebase and reuse them.
244244
- **200-line file limit**: Keep all `.ts`/`.tsx` files under 200 lines (test files exempt). If a file grows beyond this, break it into smaller focused modules (e.g. extract hooks, sub-components, helpers, constants, or types into separate files).
245245
- **Test files** co-located next to source files (`*.test.ts`)
246-
- **56 test files, 780 tests** covering math, data, education, ads, i18n (including all 31 locales), observability, and component integration
246+
- **67 test files, 869 tests** covering math, data, education, ads, i18n (including all 31 locales), sitemap, metadata helpers, observability, and component integration
247247
- **After file changes in `src/app/`**, clear `.next` cache (`rm -rf .next`) and restart dev server to avoid stale MIME type and 404 errors
248248
- **i18n strings required**: Whenever a new user-facing string is added or an existing one is modified, create or update the corresponding translation in the appropriate JSON file under `src/lib/i18n/messages/en/`. Never hardcode user-facing text directly in components — always use `useTranslations` (client) or `getTranslations` (server) to reference translation keys.
249249
- **Privacy Sandbox is deprecated** — do not discuss, recommend, or implement any Privacy Sandbox APIs (Topics, Attribution Reporting, Protected Audience, etc.)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ These tools are functional in the dev environment but not yet published to produ
5858
| UI | React 19, TypeScript 6, CSS Modules |
5959
| Rendering | Canvas API, WebGL2 + GLSL shaders |
6060
| i18n | next-intl |
61-
| Unit tests | Vitest + Testing Library (781 tests, 56 files) |
61+
| Unit tests | Vitest + Testing Library (869 tests, 67 files) |
6262
| E2E tests | Playwright (Chromium + Firefox) |
6363
| Deployment | Vercel (auto-deploy from `main`) |
6464
| Analytics | Vercel Speed Insights, Google Analytics |

package-lock.json

Lines changed: 0 additions & 54 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
"@vercel/speed-insights": "^2.0.0",
3333
"advanced-cropper": "~0.17.1",
3434
"exifreader": "^4.37.0",
35-
"framer-motion": "^12.38.0",
3635
"jpeg-js": "^0.4.4",
3736
"next": "^16.2.2",
3837
"next-intl": "^4.9.0",

public/images/samples/exif-example.jpg

100755100644
-9.05 MB
Loading

public/images/scenes/cityscape.jpg

-2.84 MB
Loading

public/images/scenes/landscape.jpg

-2.27 MB
Loading

public/images/scenes/street.jpg

-1.57 MB
Loading

public/images/scenes/wildlife.jpg

-2.57 MB
Loading

src/app/[locale]/about/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import type { Metadata } from 'next'
22
import { setRequestLocale, getTranslations } from 'next-intl/server'
33
import { getAlternates } from '@/lib/i18n/metadata'
4+
import type { Locale } from '@/lib/i18n/routing'
45
import { Link } from '@/lib/i18n/navigation'
56

6-
export async function generateMetadata(): Promise<Metadata> {
7+
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }): Promise<Metadata> {
8+
const { locale } = await params
79
const t = await getTranslations('metadata.about')
810
return {
911
title: t('title'),
1012
description: t('description'),
11-
alternates: getAlternates('/about'),
13+
alternates: getAlternates('/about', locale as Locale),
1214
}
1315
}
1416

0 commit comments

Comments
 (0)