Demo Bank App is the end-to-end reference for modelling banking workflows using PayNotes and driving them through the MyOS.
A PayNote is a programmable payment agreement shared by a payer, payee, and guarantor. It captures the commercial promise, the evidence required to fulfill it, and the automated actions that release or refund funds. Everyone sees the same terms and same timeline.
POST /v1/paynotes/bootstrapβapps/bank-api/src/paynote/bootstrapPayNote.tsvalidates the uploaded PayNote, hydrates payer/payee accounts, and forwards the document plus channel bindings to MyOSPOST /documents/bootstrapso processing begins instantly.POST /v1/paynotes/webhookβapps/bank-api/src/paynote/webhook.tsingests MyOS callbacks, downloads event detail viaGET /myos-events/{eventId}, and maps capture events to real ledger transfers.- Together these handlers amount to ~500 lines of code illustrating how little code is required to wrap a PayNote flow with bank-grade system.
- The web app collects the PayNote (YAML or parsed PDF), prompts for source/destination accounts, then calls
POST /v1/paynotes/bootstrap. - The bootstrap handler verifies the document, binds participants, and hands it to MyOS via
POST /documents/bootstrap. - MyOS processes the PayNote and calls back into
POST /v1/paynotes/webhook; the handler retrieves the full payload withGET /myos-events/{eventId}. - When capture events (for example
PayNote/Capture Funds RequestedorPayNote/Reserve Funds and Capture Immediately Requested) appear, the webhook performs the corresponding bank transfer and logs the result.
- Node.js 22+ (LTS) - JavaScript runtime environment
- npm - Package manager
- Docker - Required for LocalStack (AWS service emulation)
- AWS SAM CLI - Required for local Lambda development and testing
- Localstack samlocal - Required for local Lambda development and testing
Choose one of the following installation methods:
Option 1: Using pip (Recommended)
pip3 install aws-sam-cliOption 2: Using other methods See the official AWS SAM CLI installation guide for Windows, Linux, and other installation options.
Verify Installation
sam --version
β οΈ Troubleshooting SAM CLI: If you get a "bad interpreter" error, SAM CLI may have been installed with an older Python version. Solutions:Option 1: Reinstall with current Python
pip3 uninstall aws-sam-cli pip3 install aws-sam-cliOption 2: Add Python bin to PATH (if you see PATH warnings)
# Add to your shell profile (.zshrc, .bashrc, etc.) export PATH="$(python3 -m site --user-base)/bin:$PATH"
pip3 install aws-sam-cli-localVerify Installation
samlocal --version# 1. Install dependencies
npm install
# 2. Ensure Docker is running
npm run docker:check
# 3. Start all services (frontend, backend, localstack)
npm run serve:allThe app will be available at:
- Frontend: http://localhost:4200
- Backend API: http://localhost:3000
- LocalStack: http://localhost:4566
| Command | Description |
|---|---|
npm start |
Start development server |
npm run dev |
Start development server (alias) |
npm test |
Run tests for affected projects |
npm run test:all |
Run tests for all projects |
npm run test:integration |
Run integration tests for affected projects |
npm run test:integration:all |
Run integration tests for all projects |
npm run test:watch |
Run tests in watch mode |
npm run e2e |
Run E2E tests locally |
npm run e2e:dev |
Run E2E tests against dev environment |
npm run e2e:prod |
Run E2E tests against production environment |
npm run build |
Build affected projects |
npm run build:all |
Build all projects |
npm run lint |
Lint affected projects |
npm run lint:all |
Lint all projects |
npm run lint:fix |
Lint and auto-fix affected issues |
npm run typecheck |
Run TypeScript type checking for all projects |
npm run format |
Format code with Prettier |
npm run format:check |
Check code formatting |
npm run format:staged |
Format only staged files with Prettier |
npm run security:audit |
Run security audit on production dependencies |
npm run security:audit:dev |
Run security audit on development dependencies |
npm run security:audit:fix |
Fix security vulnerabilities |
npm run pre-commit |
Run pre-commit checks manually |
npm run validate-commit |
Validate commit message format |
npm run generate-docs |
Generate OpenAPI docs from TypeScript |
npm run wait-for-backend |
Wait for backend to be ready |
npm run clean |
Reset Nx cache |
npm run graph |
View dependency graph |
npm run serve:all |
Start all services with Nx |
npm run serve:stack |
Start backend stack (LocalStack + Lambda) |
npm run docker:check |
Verify Docker is running |
π‘ Affected vs All: By default, commands run only on "affected" projects (those changed since the last commit). Use
:allvariants to run on all projects.
Start all services with Nx orchestration:
# Start all services with dependency management
npm run serve:all
# Start individual services
nx serve localstack # ensures LocalStack is running
nx serve @demo-bank-app/bank-api # Backend API only (starts localstack)
nx serve @demo-bank-app/bank-web-app # Frontend only
# Check service status
docker ps --filter 'name=localstack-demo-bank-app'
# Stop services when done
docker stop localstack-demo-bank-app# All tests
npm test
# Unit tests in watch mode
npm run test:watch
# E2E tests (full-stack local testing)
npm run e2e
# E2E tests against remote environments
npm run e2e:dev # Test against dev environment
npm run e2e:prod # Test against production environmentNote: For local E2E testing, start the backend services first, then run E2E tests:
# Terminal 1: Start the full stack
npm run serve:all
# Terminal 2: Run E2E tests (includes automatic health check)
npm run e2eThe E2E command automatically waits for the backend to become healthy before running tests.
Environment Variables:
E2E_BASE_URL: Frontend URL for E2E tests (default: http://localhost:4300)BACKEND_URL: Backend URL for health checks (default: http://localhost:3000)
# Run security audit (production dependencies only, moderate+)
npm run security:audit
# Run security audit (all dependencies, high+ only)
npm run security:audit:dev
# Automatically fix security vulnerabilities
npm run security:audit:fix
# Check all vulnerability levels (including low)
npm audit# Build affected projects
npm run build
# Build all projects (when needed)
npm run build:all
# Preview production build
npx nx preview bank-web-app
# Utility commands
npm run clean # Reset Nx cache
npm run graph # View dependency graph- docs/problem-exploration: Project context and problem exploration
- docs/requirements/: Functional requirements & UX
- docs/adr/: Architectural decisions & rationale
- docs/design/: Technical design & architecture
This project follows a hexagonal architecture within an Nx monorepo.
demo-bank-app/
βββ apps/ # Deployable applications
β βββ bank-web-app/ # React SPA (Vite + Tailwind)
β β βββ src/ # Frontend source code
β β βββ tailwind.config.js # Styling configuration
β β βββ vite.config.ts # Build configuration
β βββ bank-api/ # AWS Lambda backend
β β βββ src/ # Lambda source code
β β βββ project.json # SAM local serve config
β βββ localstack/ # LocalStack service wrapper
β β βββ project.json # LocalStack serve config
β βββ bank-web-app-e2e/ # Playwright E2E tests
β βββ src/ # E2E test suites
β βββ playwright.config.ts # Test configuration
βββ libs/ # Shared libraries
β βββ bank-api-contract/ # Shared API contracts (ts-rest + Zod)
β βββ domain/ # Domain logic (business rules)
β βββ application/ # Use cases & application services
β βββ infrastructure/ # External adapters (DB, APIs)
βββ docs/ # Architecture & requirements
β βββ adr/ # Architectural Decision Records
β βββ requirements/ # Functional & non-functional specs
β βββ design/ # Technical design documents
βββ nx.json # Nx workspace configuration
/apps: Deployable units (SPAs, Lambdas, E2E tests)/libs: Reusable code shared between applications
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β /apps (Adapters) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β bank-web-app/ β bank-api/ β bank-web-app-e2e/ β
β (React SPA) β (AWS Lambda) β (E2E Tests) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββΌββββββββββββββββ
β β β
βββββββββββββββββΌββββ ββββββββΌββββββββ βββββΌβββββββββββββ
β /libs/domain/ β β /libs/app/ β β /libs/infra/ β
β (Business Logic) β β (Application)β β (Adapters) β
β β’ Accounts β β β’ Ports β β β’ DynamoDB β
β β’ Transfers β β β’ Commands β β β’ MyOS Client β
β β’ Blue Docs β β β’ Queries β β β’ S3 Storage β
βββββββββββββββββββββ ββββββββββββββββ ββββββββββββββββββ
Each app manages its own infrastructure-as-code:
bank-web-app/: S3 bucket, CloudFront distributionbank-api/: AWS Lambda, API Gateway, DynamoDB- Shared resources: Defined in dedicated infrastructure packages
- DevDependencies centralized at root - All build tools, linters, and testing frameworks managed in workspace root
- Runtime dependencies per project - Only production dependencies live in individual app/lib package.json files
- Nx workspace resolution - Enables consistent tooling versions across all projects
- Tree-shaking enabled: Only used code included via esbuild bundling
- Minification in production: Code compression for faster cold starts
- Source maps: Bundled source maps for clear stack traces
# Development build (fast iteration)
nx serve bank-api # No minification and tree shaking
# Production build (optimized)
nx build bank-api # Minified tree-shaked bundle, all dependencies inlined- Centralized contracts: TypeScript API definitions using ts-rest + Zod
- Cross-app consistency: Backend, frontend, and SDKs import the same contract
- Type safety: Compile-time API validation between client and server
- Auto-completion: Full IDE support for API endpoints and schemas
# Generate OpenAPI docs from TypeScript contract
npm run generate-docs # Creates docs/api/openapi.{json,yaml}Benefits:
- π Contract-first development
- π Documentation stays in sync with code
- π± Enables SDK generation for multiple platforms
- β Single source of truth for API structure
- Frontend: React, TypeScript, Tailwind CSS, Vite
- Backend Node.js, AWS Lambda, DynamoDB
- Testing: Vitest, Playwright
- Build: Nx, esbuild
- Deployment: AWS SAM, GitHub Actions
- Local development Localstack / Docker
This project uses automated git hooks to ensure code quality and security:
# Pre-commit (automatic on git commit)
- Phase 1: Format staged files with Prettier + ESLint
- Phase 2: Security audit (production: moderate+, dev: high+ only)
- Phase 3: Run affected tests
- Block commit if any phase fails
# Commit message (automatic on git commit)
- Validate conventional commit format
- Ensure consistent commit historyGit hooks are automatically installed via Husky:
- β Pre-commit: Formats code + security audit + runs tests
- β Commit-msg: Validates conventional commit format
- β Security audit: Blocks commits with vulnerabilities (moderate+ in prod, high+ in dev)
- β Staged-only formatting: Fast iteration (formats only changed files)
Conventional Commit Format: type: description (feat, fix, docs, chore, etc.)
graph TB
A[Push/PR] --> B["π§ͺ Quality Gates<br/>Unit Tests β’ Lint β’ Build β’ Security"]
B --> C["π³ Integration Tests<br/>AWS Services via LocalStack"]
C --> D["β‘ Local Stack E2E<br/>SAM Local + React Dev + E2E"]
D --> E{Branch Type?}
E -->|PR to main| F["π Deploy Dev<br/>+ Cloud E2E Tests"]
E -->|Push to main| G["π Deploy Production<br/>+ Cloud E2E Tests"]
subgraph "Pre-Deployment Test Pyramid"
direction TB
T1["1οΈβ£ Unit Tests<br/>(Fast, Isolated)"]
T2["2οΈβ£ Integration Tests<br/>(AWS Services)"]
T3["3οΈβ£ Local E2E<br/>(Full Stack)"]
T1 --> T2 --> T3
end
subgraph "Post-Deployment"
T4["4οΈβ£ Cloud E2E<br/>(Live Environment)"]
end
%% Connect pyramid to main flow
B -.-> T1
C -.-> T2
D -.-> T3
F -.-> T4
G -.-> T4
style A fill:#e1f5fe
style E fill:#fff3e0
style F fill:#e8f5e8
style G fill:#fff8e1
style T1 fill:#f3e5f5
style T2 fill:#e8f5e8
style T3 fill:#fff3e0
style T4 fill:#fce4ec
4-Tier Test Pyramid:
- Unit Tests: Fast, isolated tests without external dependencies
- Integration Tests: AWS service integration via LocalStack containers
- Local Stack E2E: Full-stack tests against local services (pre-deployment validation)
- Cloud E2E: End-to-end tests against live AWS environments (post-deployment verification)
Deployment Flow:
- PR to main β Deploy to dev environment + run cloud E2E tests
- Merge to main β Deploy to production + run cloud E2E tests
- Zero manual approvals - Fully automated with proper test gates
This project demonstrates modern TypeScript/Node.js development with AWS serverless architecture, following hexagonal architecture principles and industry best practices.