A transparent donation tracking platform built with React, Tailwind CSS, and VietQR API integration.
- Node.js >= 18.0.0
- pnpm >= 8.0.0
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Build for production
pnpm build
# Preview production build
pnpm previewpnpm dev- Start development server (port 5173)pnpm build- Build for productionpnpm preview- Preview production buildpnpm lint- Run Biome linterpnpm lint:fix- Fix linting issues automaticallypnpm format- Format code with Biomepnpm format:check- Check code formatting without changespnpm check- Run all Biome checks (lint + format)pnpm type-check- Type-check with TypeScriptpnpm test:e2e- Run Playwright E2E testspnpm test:e2e:debug- Debug E2E testspnpm test:e2e:ui- Run E2E tests with UI
- Frontend: React 18 + TypeScript
- Styling: Tailwind CSS v4 + shadcn/ui
- State Management: Zustand
- Form Handling: React Hook Form + Yup validation
- Build Tool: rsbuild (Rust-based)
- Code Quality: Biome (all-in-one linter + formatter)
- Testing: Playwright for E2E tests
- i18n: i18next (Vietnamese & English)
- QR Code: qrcode library + VietQR API
This project uses Biome as a unified toolchain for linting and formatting. Biome replaces both ESLint and Prettier with a single, fast Rust-based tool.
Biome configuration is defined in biome.json:
- Formatter: Tab indentation (width 2), 88-char line width, LF line endings
- Linter: Recommended rules with strict correctness and style checks
- Import Organization: Automatic import sorting and deduplication
- JavaScript: Always semicolons, arrow parentheses
# Check and report issues
pnpm lint
# Fix issues automatically (linting)
pnpm lint:fix
# Format code
pnpm format
# Check formatting without changes
pnpm format:check
# Run all checks (lint + format)
pnpm checkVS Code: Install the Biome extension
Add to .vscode/settings.json:
{
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
}
}src/
├── components/ # React components
│ └── common/ # Header, Hero, Reasons, Stats, DonationForm
├── pages/ # Page components (Home)
├── services/ # API clients (VietQR)
├── store/ # Zustand stores (donation)
├── hooks/ # Custom React hooks
├── types/ # TypeScript interfaces
├── utils/ # Utilities (validation schemas)
├── styles/ # Global CSS
├── i18n/ # Internationalization
│ ├── locales/ # Translation files (en.json, vi.json)
│ └── index.ts # i18n configuration
├── App.tsx # Root component
└── index.tsx # Entry point
The app supports Vietnamese (vi) and English (en) with dynamic locale switching.
- Update
src/i18n/locales/en.jsonandsrc/i18n/locales/vi.json - Use translations in components:
const { t } = useTranslation(); t('key')
Use the language switcher in the Header component, which persists selection to localStorage.
The app integrates with VietQR API for generating bank transfer QR codes.
Set VITE_VIETQR_API_URL in .env:
VITE_VIETQR_API_URL=https://api.vietqr.io/v1
import { vietqrService } from '@/services/vietqr';
const qrData = await vietqrService.generateQR({
bankCode: 'ACB',
accountNumber: '123456789',
amount: 100000,
});Forms use React Hook Form with Yup validation:
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { donationFormSchema } from '@/utils/validation';
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: yupResolver(donationFormSchema),
});# Run all tests
pnpm test:e2e
# Run tests in debug mode
pnpm test:e2e:debug
# Run tests with UI
pnpm test:e2e:uiTest files are located in tests/e2e/ directory.
# Build for production
pnpm build
# Preview the build locally
pnpm previewThe build output is in the dist/ directory, optimized with code splitting and CSS purging.
Copy .env.example to .env.local and update values:
cp .env.example .env.localAvailable variables:
VITE_VIETQR_API_URL- VietQR API base URL
- Biome Documentation
- React Documentation
- Tailwind CSS
- React Hook Form
- Yup Validation
- Zustand
- VietQR API
- rsbuild
- Playwright
MIT