Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,43 @@ jobs:
name: build-output
path: frontend/dist
retention-days: 7

bundle-budget:
name: Bundle analysis & size budget
needs: [lint, test]
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: frontend/pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build with rollup visualizer
run: pnpm run build:analyze

- name: Enforce size budget (size-limit)
run: pnpm run size

- name: Upload bundle analysis (treemap)
uses: actions/upload-artifact@v4
with:
name: bundle-stats
path: frontend/dist/stats.html
retention-days: 14
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ pnpm run test:watch # Run tests in watch mode
> **⚠️ Important:** Always use `pnpm` (not `npm` or `yarn`) to maintain consistency.
> Using different package managers creates lock file conflicts and dependency mismatches.

### Soroban contracts (proxy / upgrade safety)

Smart contracts live in [navin-contracts](https://github.com/Navin-xmr/navin-contracts). This frontend does not embed Rust contracts, but any future Soroban client code should validate **contract StrKeys** (`C…`) and, for upgradeable or proxy deployments, restrict calls to IDs listed in environment configuration.

- Utilities: `frontend/src/utils/contractSafety.ts` (`validateSorobanContractId`, `checkSorobanContractForProxySafety`).
- Optional allowlist: set `VITE_SOROBAN_CONTRACT_ALLOWLIST` in `.env` (see `frontend/.env.example`) to a comma-separated list of trusted contract StrKeys.

---

## Contributing
Expand Down
4 changes: 4 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
VITE_API_BASE_URL=http://localhost:3000/api

# Optional: comma-separated Soroban contract StrKeys the app is allowed to use (proxy / upgrade safety).
# When set, client code should reject any other contract id before invoking Soroban.
# VITE_SOROBAN_CONTRACT_ALLOWLIST=CDEMO...,COTHER...
8 changes: 8 additions & 0 deletions frontend/.size-limit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"name": "All production JS/CSS (gzip)",
"path": ["dist/assets/*.js", "dist/assets/*.css"],
"limit": "2400 kB",
"gzip": true
}
]
5 changes: 5 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Bundle size & analysis

- **Budget (CI):** [`size-limit`](https://github.com/ai/size-limit) reads `dist/assets/*.{js,css}` after a production build; limits live in [`.size-limit.json`](./.size-limit.json).
- **Treemap:** `pnpm run build:analyze` sets `ANALYZE=true`, runs `rollup-plugin-visualizer`, and writes `dist/stats.html`. The GitHub Actions **Bundle analysis & size budget** job uploads that file as the `bundle-stats` artifact.

## React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
Expand Down
7 changes: 7 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"build:analyze": "cross-env ANALYZE=true tsc -b && cross-env ANALYZE=true vite build",
"size": "size-limit",
"lint": "eslint .",
"preview": "vite preview",
"test": "vitest run",
"test:watch": "vitest"
},
"dependencies": {
"@stellar/freighter-api": "^6.0.1",
"@stellar/stellar-base": "^14.1.0",
"@tailwindcss/vite": "^4.2.1",
"axios": "^1.7.0",
"lucide-react": "^0.575.0",
Expand All @@ -23,6 +26,7 @@
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@size-limit/file": "^12.0.1",
"@tailwindcss/postcss": "^4.2.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
Expand All @@ -34,12 +38,15 @@
"@typescript-eslint/parser": "^8.0.0",
"@vitejs/plugin-react": "^5.1.1",
"autoprefixer": "^10.4.24",
"cross-env": "^10.1.0",
"eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"globals": "^16.5.0",
"jsdom": "^28.1.0",
"postcss": "^8.5.6",
"rollup-plugin-visualizer": "^7.0.1",
"size-limit": "^12.0.1",
"tailwindcss": "^4.2.1",
"typescript": "^5.6.0",
"vite": "^7.3.1",
Expand Down
Loading