Skip to content

The petfolio-fe repository

The PetFolio Frontend is built as a Nx monorepo with a modular architecture designed for scalability and maintainability.

Read the introduction to Nx for more information on how the workspace uses Nx.

Applications and libraries

The workspace is split into applications and libraries - deployable entry points in apps/ and reusable shared code in libs/.

Our applications

Project Description
petfolio-business Main Next.js application (App Router)
petfolio-docs MkDocs Material documentation site
petfolio-ui-tests Playwright end-to-end tests

Our libraries

Project Description
ui-component-library Shared React component library with Storybook
util-global-theme Material UI theming utilities and type definitions

Nx enforces strict module boundaries between these projects, controlling which libraries each application and library is allowed to import from.

Technology stack

Technology Category Purpose
Nx Build System Monorepo orchestration and task management
Next.js Framework App routing, SSR, server components
React UI Library Building user interfaces
Material UI Design System Component library with theming
TypeScript Language Adds type safety to JavaScript
Jest Testing Unit and integration testing
Playwright Testing End-to-end browser testing
ESLint Linting Code quality and style enforcement
Storybook Documentation Interactive component documentation
MkDocs Material Documentation Static documentation site generation

Design patterns

File naming conventions

File Type Pattern Example
Component PascalCase Button.tsx
Test *.spec.tsx Button.spec.tsx
Story *.stories.tsx Button.stories.tsx
Styled Component Styled*.tsx StyledButton.tsx
Utility camelCase themeUtils.ts
Config kebab-case next.config.mjs
Documentation kebab-case getting-started.md

Atomic design

Components are organised hierarchically:

graph LR
    A[Atoms] --> B[Molecules]
    B --> C[Organisms]
    C --> D[Templates]
    D --> E[Pages]

    classDef layer-infra fill:#f5a6232e,stroke:#f5a623,stroke-width:2px
    classDef layer-domain fill:#7ed32126,stroke:#7ed321,stroke-width:2px
    classDef layer-api fill:#4a90d926,stroke:#4a90d9,stroke-width:2px

    class A,B layer-infra
    class C,D layer-domain
    class E layer-api
Diagram key
  • Blue (API layer): Pages - route-level entry points
  • Green (Domain layer): Organisms and Templates - composed business UI
  • Orange (Infrastructure layer): Atoms and Molecules - foundational building blocks
  • Atoms: Basic building blocks (Button, Input, Icon)
  • Molecules: Simple combinations (SearchBar, FormField)
  • Organisms: Complex components (Header, ProductCard)
  • Templates: Page layouts
  • Pages: Actual routes in the app

Direct imports with path aliases

To avoid barrel export issues (bundle size, HMR performance, server/client boundary violations), components are imported directly from their source files using TypeScript path aliases.

Path aliases are configured in tsconfig.base.json:

1
2
3
4
5
6
7
8
{
  "compilerOptions": {
    "paths": {
      "@util-global-theme/*": ["libs/util-global-theme/src/lib/*"],
      "@ui-component-library/*": ["libs/ui-component-library/src/lib/*"]
    }
  }
}

Example imports:

1
2
3
4
5
6
7
// Component library - use direct imports
import { Button } from '@ui-component-library/atoms/Button/Button';
import { ButtonSize, ButtonVariant } from '@ui-component-library/atoms/Button/Button.types';

// Theme utilities - use direct imports
import { createDefaultTheme } from '@util-global-theme/createTheme/createDefaultTheme';
import { TypographyVariant } from '@util-global-theme/types/TypographyVariant';

Benefits:

  • Clear server/client boundaries in Next.js App Router
  • Better tree-shaking for smaller bundles
  • Faster builds and Hot Module Replacement (HMR)
  • Explicit component dependencies

Enforcement:

ESLint enforces this pattern by banning the export * from syntax, preventing barrel exports from being created.

Security

  • ESLint Security Plugin: Detects common vulnerabilities
  • No Unsanitised Plugin: Prevents XSS attacks
  • TypeScript Strict Mode: Catches type-related bugs
  • Multi-stage builds: Minimal production images
  • Trivy scanning: Vulnerability detection in dependencies
  • Non-root user: Containers run with restricted privileges
  • Health checks: Automatic restart on failure
  • Dependabot: Automated dependency updates
  • Version pinning: Exact versions in package-lock.json
  • Audit on CI: npm audit runs in pipeline

Performance

  • App Router: Automatic code splitting
  • Server Components: Reduced client bundle size
  • Standalone output: Optimised production builds
  • Image optimisation: Built-in next/image
  • Nx cache: 10-100x faster repeat builds
  • Incremental builds: Only rebuild changed code
  • Parallel execution: Utilise all CPU cores