All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Pinned TypeScript to 5.9.3 so
npm installresolves cleanly withopenapi-typescript@7, which still declarespeerDependencies.typescriptas^5.x. Revisit TypeScript 6 after openapi-typescript publishes peer support for it (openapi-ts/openapi-typescript#2723).
- Added Vitest 4 unit test suite (
npm run test:unit) with 69 tests across 8 files covering server config (api-error,redirects,auth-profile), server services (hashPassword, JWT sign/verify), server middleware (globalErrorHandler), and client utilities (parseFeatureFlags/isFeatureEnabled,formatDate/formatNumber/formatCurrency). - Added
vitest.config.tswith per-directory environment mapping:nodeforsrc/server/**tests,happy-domforsrc/client/**tests. - Added Playwright E2E test suite (
playwright/e2e/) with full coverage parity: auth, rate-limiting, WebMCP, accessibility, i18n, layout, routing, security headers, and SEO metadata. Sharedlogin()helper inplaywright/e2e/helpers/auth.ts. - Added
playwright.config.tswithwebServerauto-start, Chromium project, and trace/screenshot on failure. - Added
playwright/README.md. - Updated
.github/workflows/ci.ymlE2E job to Playwright;webServerhandles server lifecycle automatically in CI. npm run testnow runslint → type-check → test:unit → test:e2e.- Added Helmet 8 security headers middleware (
src/server/middleware/security-headers.ts) covering CSP, HSTS (production), Referrer-Policy, Permissions-Policy, COOP, COEP (production), CORP, X-Content-Type-Options, and X-Frame-Options per OWASP Secure Headers Project 2026 guidance. - Added
docs/SECURITY_HEADERS.mddocumenting every active header, the rationale for each decision, and a hardening guide. - Added
playwright/e2e/security/security-headers.spec.tsto verify required headers are present on HTML, API, and static asset responses. - Added GitHub Actions CI workflow (lint, typecheck, Playwright E2E) plus
.github/ci.envfor non-secret CI env defaults. - Added
skills/migrate-ci-github-to-gitlab/SKILL.mdto guide migrating CI from GitHub Actions to GitLab CI/CD. - Added feature-flag starter support with env defaults (
VITE_FEATURE_FLAGS) and runtime hook-based overrides (useFeatureFlag). - Added
docs/FEATURE_FLAGS.mdto document feature-flag setup and usage. - Added auth backing starter profiles (
AUTH_PROFILE=local|supabase|postgres) with setup guidance indocs/AUTH_PROFILES.md. - Added contract-first API documentation in
docs/openapi.yamlplus generated shared API types undersrc/generated/api/(openapi.generated.ts,api-types.ts). - Added
skills/api-first/SKILL.mddocumenting the OpenAPI contract location, generation command, and generated output layout. - Added shared
LoadingFallbackandBackHomeCtaUI components to reduce repeated loading/CTA markup. - Added
skills/migrate-design-system-to-shadcn/SKILL.mdto guide full Chakra-to-shadcn migration with explicit removal criteria. - Added
skills/add-form-manager/SKILL.mdto standardize React Hook Form + Zod adoption, starting with login-form migration guidance. - Added REST-style auth session endpoints (
POST /api/session,DELETE /api/session) while keeping legacy browser auth routes for compatibility. - Added
docs/API.mdto document API contract conventions and migration-readiness guidelines. - Added two migration SOP skills:
skills/migrate-api-to-tanstack-query/SKILL.mdandskills/migrate-api-to-graphql-client/SKILL.md. - Added a localized footer GDPR notice clarifying that only essential cookies are used by default.
- Added
skills/playwright-migration/SKILL.mdto standardize migration from Cypress to Playwright with clear file updates, validation steps, and done criteria. - Added
cypress/e2e/layout/footer-position.cy.tsto verify the footer remains pinned to the viewport bottom on short pages. - Added WebMCP
increment-countertool registration on the private Product page, plus Cypress coverage incypress/e2e/auth/webmcp-increment.cy.ts. - Added Simplified Chinese (
zh) locale support across the client i18n provider, language switcher, locale dictionaries, and i18n key validation. - Added a combined policy-writing guide page at
/policiesplus a maintenance SOP inskills/policy-guide/SKILL.md. - Added a config-driven redirect system in
src/server/config/redirects.tswith middleware integration and E2E coverage (cypress/e2e/routing/redirects.cy.ts). - Added redirect documentation in
docs/REDIRECTS.mdand a reusable agent SOP atskills/add-redirect/SKILL.md. - Added a shared client
Linkcomponent that unifies Chakra UI link styling with React Router navigation and standardized external-link handling.
- Migrated from Vite 7 to Vite 8: updated
vite^7.3.3→^8.0.0and@vitejs/plugin-react5.1.4→^6.0.2. Vite 8 switches the build pipeline to Rolldown and Oxc (replacing esbuild/Rollup). Novite.config.tschanges required — the project's config does not use any deprecated options. - Updated ESLint ecosystem to ESLint 10:
eslint9→10.3.0,@eslint/js9→10.0.1,eslint-plugin-react-dom2→5.7.7,eslint-plugin-react-x2→5.7.7,eslint-plugin-react-hooks7.0.1→7.1.1,eslint-plugin-react-refresh0.5.1→0.5.2,typescript-eslint8.56.1→8.59.3,@stylistic/eslint-plugin5.9.0→5.10.0,globals17.3.0→17.6.0. - Updated runtime dependencies:
@chakra-ui/react3.33.0→3.35.0,framer-motion12.34.3→12.38.0,react/react-dom19.2.4→19.2.6,react-icons5.5.0→5.6.0,react-router7.13.1→7.15.0. - Updated
@types/node24.7.2→25.7.0 (compatible with TypeScript 5.9). - Moved
new Date().getFullYear()inFooterto a module-level constant to satisfy the newreact-x/purityrule. - Upgraded TypeScript 5.9.3→6.0.3. TypeScript 6 is a transition release bridging 5.x and the forthcoming Go-based 7.0; it introduces new compiler defaults (
strict,target,moduleResolution) and deprecates legacy options. The existingtsconfig.app.jsonandtsconfig.node.jsonalready used explicit values for all changed defaults, so no tsconfig edits were required. - Upgraded
react-intl8.1.3→10.1.8. Version 10 requires React 19 and TypeScript 5+ (both already satisfied). The project uses only stable APIs (IntlProvider,FormattedMessage,useIntl) — none of the deprecatedFormattedHTMLMessage/intl.formatHTMLMessageAPIs — so no source changes were required. - Removed
SESSION_SECRETstartup validation: the server no longer rejects short or template-like values. The.envTemplatenow ships with working local-dev defaults (local-dev-session-secret,local-dev-storage-key) socp .envTemplate .env && npm run devworks without any additional setup. Use strong random values in production. - Moved OpenAPI-generated TypeScript and shared API aliases from
src/shared/tosrc/generated/api/; imports use@/generated/api/api-types. - Updated auth verification to route through profile-aware starter mode logic (
localworks by default;supabase/postgresrequire provider wiring). - Updated API auth behavior to favor REST-style
/api/*responses for API clients while preserving legacy browser form auth endpoints as compatibility shims. - Reduced duplication across route loading fallbacks, back-home page CTAs, and Express pass-through handlers.
- Centralized repeated rate-limit message/user literals and removed redundant store throttle literal in favor of utility defaults.
- Compacted boundary guidance docs by keeping details in architecture docs and linking from client/contributing docs.
- Refined React boundary placement: route-level
Suspensenow handles lazy page loading,PageLayoutno longer wraps all page content in a blanketSuspense, and product counter actions use feature-levelErrorBoundary+ localSuspense. - Added React 19
Activityaround loading fallbacks for route and feature loading states. - Refactored WebMCP registration logic into
src/client/utilities/webmcp.tsso the Product page stays focused on view behavior. - Updated
PageLayoutto use a full-height flex column so the footer consistently sits at the bottom of the viewport. - Replaced separate Terms/Privacy footer links with a single policy guide link and routed legacy
/privacyand/termspaths to/policies. - Refined testing guidance across
AGENTS.md,docs/CONTRIBUTING.md, andcypress/README.mdto keep E2E contract coverage lean and migration-friendly while still requiring feature-level automated tests at the right layer. - Simplified
cypress/e2e/seo/page-meta.cy.tsto assert core metadata contracts without over-coupling to every page-specific metadata field. - Replaced client-side CryptoJS encryption/decryption with native Web Crypto API (AES-GCM + PBKDF2) in persistence flow.
- Moved
index.htmlinline speculation-rules fallback script topublic/js/speculation-rules-fallback.jsso it loads from'self'without requiring'unsafe-inline'inscript-src. - Removed
<meta http-equiv>security headers fromindex.html(X-Content-Type-Options,X-Frame-Options, minimal CSP); all policies are now delivered as HTTP response headers covering every response type. - Updated
docs/TECHNOLOGY.mdto reflect that CSRF protection and login rate limiting are already implemented (was listed as future work).
- Removed unused
ejsdependency (template system was removed in v1.2.0 but the package lingered). - Removed Cypress and all related config (
cypress.config.ts,cypress/directory,skills/playwright-migration/SKILL.md). - Removed
crypto-jsand@types/crypto-jsdependencies.
- Added Helmet 8 with a full security header suite following OWASP and 2026 industry guidance. Strict CSP eliminates
'unsafe-inline'for scripts;X-XSS-Protectionis explicitly disabled (deprecated); HSTS withpreloadis production-only; Permissions-Policy opts out of camera, microphone, geolocation, payment, and ad-tracking APIs. - Added IP-based rate limiting for
POST /login/passwordwith configurable env overrides (LOGIN_RATE_LIMIT_MAX_ATTEMPTS,LOGIN_RATE_LIMIT_WINDOW_MS).
- Added proper SEO metadata and a sitemap.xml file to public pages.
- Added Terms of service and Privacy policy.
- Added AI-friendly files such as AGENTS.md & docs/ARCHITECTURE.md.
- Added a new
skills/folder usingskills/<skill-name>/SKILL.mdformat, includingskills/rebrand/SKILL.mdfor rebranding title/description metadata acrossindex.html,package.json,README.md, and header branding. - Added a shared
PageMetacomponent that maps page title/description to full metadata fields using React 19 metadata tags (Open Graph, Twitter, canonical, and mobile tags), with usage across every page and Cypress coverage. - Added React 19 meta tags.
- Added ScrollToTop functionality on route change.
- Added a shared
PageTransitioncomponent insrc/client/ui/components/page-transition.tsx, integrated throughPageLayoutso route transitions apply across all pages. - Added a shared
AnimatedButtoncomponent insrc/client/ui/components/animated-button.tsxto reuse Framer Motion tap animations across app buttons. - Improved Accessibility: skip to content link, useId() to avoid form field id collisions, and useAnnounce hook for aria-live.
- Better Error handling: Added second suspense boundary around the content, error-handler middleware for the server, and an centralized error handler for the client.
- Added a second non-persistent reducer for more transient data.
- Node.js 24: Updated engine requirement from Node 22 to Node 24.
- Make header and footer into reusable components, and a light mode/dark mode toggle.
- Update the user flow with a proper home page before login.
- Moved the Login page to a client route.
- Improved the design of the home page and 404 page.
- Moved to JWT for session expiration.
- Updated the ESLint configuration.
- Updated dependency versions.
- Changed the favicon.
- Expanded the .gitignore file.
- Changed the counter to show an example of useOptimistic.
- EJS template system that is no longer used.
- Removed the CSS reset. Now provided by Chakra UI.
- Fixed a bug that prevented it from loading without any saved data. Cold start now working as expected.
- Cypress for E2E testing
- Chakra UI design system
- React Router
- Added a CHANGELOG
- Added a .env template
- Added a css reset
- Added speculation rules for server-side pages
- Organized the server files for better API construction
- Updated the versions of dependencies
- Improved SEO metadata handling
- Historical documentation
Frontend
- Build Tool: Vite
- Static Typing: TypeScript
- UI Framework: React
- State Management: Redux Toolkit
Backend
- Server Runtime: Node.js
- Web Framework: Express
- Template Engine: EJS
- Authentication Library: Passport.js
Security and Storage
- Local Storage
- Crypto Library: Crypto JS
Linting and Formatting
- Linter: ESLint
When making changes, add them to the "Unreleased" section under the appropriate category:
- Added for new features
- Changed for changes in existing functionality
- Deprecated for soon-to-be removed features
- Removed for now removed features
- Fixed for any bug fixes
- Security for security improvements
When creating a new release:
- Move items from "Unreleased" to a new version section
- Add the release date
- Update the version number in package.json
- Create a git tag for the release
- Major.Minor.Patch (e.g., 1.0.0)
- Major: Breaking changes
- Minor: New features (backwards compatible)
- Patch: Bug fixes (backwards compatible)