An open-source invoice factoring protocol built on the Stellar network. ILN lets freelancers get paid immediately for outstanding invoices by selling them at a discount to liquidity providers, who earn short-term yield for funding them. This repository is the Next.js web client: wallet connection, invoice submission and funding flows, governance, analytics, and the protocol's public-facing dashboards.
- Network: Stellar Testnet (Soroban smart contracts)
- Overview
- Key Features
- Tech Stack
- Project Structure
- Getting Started
- Available Scripts
- Testing
- Documentation
- Design System
- Contributing
- Security
- License
ILN bridges the gap between freelancers who need cash flow today and liquidity providers looking for short-term, invoice-backed yield. A freelancer submits an invoice on-chain; a liquidity provider funds it at a discount; the payer settles it on its due date; the LP collects the spread. All of this is coordinated by a Soroban smart contract, with this frontend providing the interface for every participant role: freelancers, payers, liquidity providers, governance voters, and protocol admins.
The app is a single Next.js project (App Router) that talks directly to Soroban RPC and Horizon for on-chain state, uses Supabase for off-chain reminder preferences, and Freighter (or WalletConnect) for wallet signing — there is no separate backend service for core protocol interactions.
- Invoice origination & management — submit single or batched invoices, view public invoice detail pages, export tables, generate PDFs, and share invoice QR codes / deep links.
- Funding marketplace — browse open invoices, inspect payer risk, fund invoices, compare opportunities, and track LP portfolio allocation, yield, and transfers.
- Payer workflows — pay invoices, mark invoices as paid, open disputes, opt into email reminders, and view payer-specific dashboard state.
- Analytics & stats — protocol-wide metrics, volume charts, token breakdowns, dispute rates, yield analytics, freelancer cash-flow analytics, and a leaderboard.
- Governance & admin — create/list/vote on proposals, delegate voting power, manage the token allowlist, and view protocol health and contract version info.
- Growth & engagement — referrals, product roadmap, reputation profiles with a score simulator, an in-app notification center, a command palette, onboarding tours, and a PWA offline fallback page.
- Internationalization & theming — multi-locale support via
next-intl/i18next, with light/dark theme support.
| Category | Tools |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack), React 19, TypeScript 5 |
| Package manager | pnpm 9, with a committed pnpm-lock.yaml |
| Styling | Tailwind CSS v4, PostCSS, next-themes for light/dark mode |
| Blockchain integration | @stellar/stellar-sdk (Soroban RPC, transaction simulation, XDR parsing, Horizon reads), @stellar/freighter-api |
| Data fetching & cache | TanStack Query (@tanstack/react-query) |
| Internationalization | next-intl, i18next, i18next-browser-languagedetector, react-i18next |
| PWA & offline | next-pwa, a generated service worker, public/manifest.json |
| Notifications & email | sonner, @supabase/supabase-js, React Email, Resend |
| Charts & exports | recharts, jspdf, papaparse, qrcode / qrcode.react |
| Guided UX & icons | react-joyride, lucide-react |
| Component workshop | Storybook 10 (local component development; see Documentation for CI status) |
| Mocking | Mock Service Worker (MSW) |
| Testing | Vitest, Testing Library, jest-axe, Playwright, Stryker (mutation testing) |
├── app/ # Next.js App Router — the live route tree
│ ├── admin/ # Admin health & protocol configuration dashboard
│ ├── analytics/ # Protocol, leaderboard, and freelancer analytics
│ ├── api/ # Feedback, notifications, and reminder cron endpoints
│ ├── dashboard/ # Personalized dashboard routes
│ ├── freelancer/ # Freelancer dashboard
│ ├── governance/ # Proposal list, detail, creation, and explainer routes
│ ├── i/[id]/ # Public invoice detail route
│ ├── invoices/batch/ # Batch invoice submission
│ ├── leaderboard/ # Protocol leaderboard
│ ├── lp/ # LP dashboard and invoice comparison
│ ├── marketplace/ # Open invoices explorer
│ ├── offline/ # PWA offline fallback page
│ ├── pay/[id]/ # Payer checkout and dispute flow
│ ├── payer/ # Payer dashboard and reminder opt-in
│ ├── profile/[address]/ # Reputation and activity profile
│ ├── referrals/ # Referral dashboard
│ ├── roadmap/ # Product roadmap
│ ├── stats/ # Protocol stats
│ ├── submit/ # Invoice submission flow
│ ├── tokens/ # Accepted token reference page
│ └── Providers.tsx # TanStack Query & MSW provider setup
├── src/
│ ├── components/ # Reusable UI components
│ ├── context/ # Global React contexts (wallet, notifications, toasts)
│ ├── hooks/ # Custom hooks and background polling
│ ├── lib/ # Services layer (Stellar SDK, Supabase client, Horizon)
│ ├── utils/ # General helpers (reputation decay, formatting, health checks)
│ └── app/ # Legacy route tree — see docs/architecture.md, not the live routes
└── e2e/ # Playwright end-to-end specs
src/app/is a legacy tree kept around for older route experiments and is not what Next.js actually serves —app/at the repository root is the live route tree. See Frontend Architecture Overview for the full explanation and directory-by-directory breakdown.
- Smart contract layer (
src/lib/contract/,src/lib/invoice-nft.ts,src/utils/soroban.ts) — connects UI actions to the Soroban smart contract, reconstructs Invoice NFT metadata, and tracks mint/burn/transfer history from Horizon transaction logs and contract simulation. - State & context layer (
src/context/) —WalletContext(Freighter/WalletConnect connection, multi-token balances),NotificationContext(in-app notification history),ToastContext(Sonner-backed alerts). - Background polling (
src/hooks/usePositionPolling.ts) — watches funded-invoice state transitions (Funded → Paid,Funded → Defaulted,Funded → Disputed) for the connected LP every 60 seconds and surfaces due-date warnings. - Payer email reminders (
app/api/reminders/) — a cron-triggered route that reads Supabase reminder preferences, sends 72h/24h warning emails via Resend, and records deliveries to prevent duplicates.
- Node.js — the version pinned in
.nvmrc(>=20.19.0 <21, currently20.20.2) - pnpm 9 — enable via Corepack (see below)
- Freighter browser extension, configured for Stellar Testnet — Chrome / Firefox
corepack enable
corepack prepare pnpm@9.0.0 --activate
pnpm installpnpm install also runs Husky's prepare script, which wires up .husky/pre-commit (lint-staged) and .husky/pre-push (tsc --noEmit).
cp .env.local.example .env.localThe checked-in example ships with safe Stellar Testnet defaults, so local UI development works without any extra setup. The tables below cover what each group of variables does; pnpm run env:check verifies the example file stays in sync with what the code actually references.
Stellar & smart contract configuration
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_CONTRACT_ID |
CD3TE3IAHM737P236XZL2OYU275ZKD6MN7YH7PYYAXYIGEH55OPEWYJC |
Invoice Factoring smart contract ID on Soroban Testnet. |
NEXT_PUBLIC_NETWORK_PASSPHRASE |
Test SDF Network ; September 2015 |
Stellar network passphrase. |
NEXT_PUBLIC_RPC_URL |
https://soroban-testnet.stellar.org |
Soroban RPC endpoint. |
NEXT_PUBLIC_NETWORK_NAME |
TESTNET |
Human-readable network label (TESTNET, MAINNET, LOCAL). |
NEXT_PUBLIC_STELLAR_NETWORK |
testnet |
Network type identifier (testnet, public). |
NEXT_PUBLIC_TESTNET_USDC_TOKEN_ID |
CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75 |
USDC asset contract ID on testnet. |
NEXT_PUBLIC_TESTNET_EURC_TOKEN_ID |
GDHU6WRG4IEQXM5NZ4BMPKOXHW76MZM4Y2IEMFDVXBSDP6SJY4ITNPP |
EURC asset contract ID on testnet. |
NEXT_PUBLIC_TESTNET_XLM_TOKEN_ID |
native-xlm |
Native XLM token identifier. |
NEXT_PUBLIC_GOVERNANCE_ADMIN_ADDRESS |
GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF |
Fallback admin address for governance parameters. |
Feature flags
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_INSURANCE_POOL_ENABLED |
false |
Enables the liquidity insurance pool UI. |
NEXT_PUBLIC_ORACLE_ENABLED |
false |
Displays oracle price-feed verification badges. |
NEXT_PUBLIC_NFT_ENABLED |
false |
Enables Soroban Invoice NFT metadata display. |
NEXT_PUBLIC_NFT_CONTRACT_ID |
(unset) | Overrides the NFT contract ID (defaults to the main contract ID). |
NEXT_PUBLIC_NFT_METADATA_METHOD |
token_uri |
Contract method used to resolve NFT metadata. |
NEXT_PUBLIC_NFT_EVENT_HINTS |
(unset) | Optional event-name hints for NFT event parsing. |
NEXT_PUBLIC_API_MOCKING |
disabled |
Set to enabled to start MSW mocks in local development. |
See docs/feature-flags.md for the full reference, including where each flag is read.
Indexer, notifications & email (server / cron)
| Variable | Description |
|---|---|
NEXT_PUBLIC_INDEXER_API_URL |
Indexer REST API base URL (activity feed, analytics charts). |
NEXT_PUBLIC_INDEXER_WS_URL |
Indexer WebSocket URL for real-time updates. |
INDEXER_URL |
Server-side indexer URL (leaderboard, server functions). |
NOTIFICATION_API |
External backend base URL for notifications. |
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL. |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anonymous (browser-safe) key. |
SUPABASE_SERVICE_ROLE_KEY |
Server-only key used by the reminder cron to bypass RLS. |
RESEND_API_KEY |
Resend API key used to send payer reminder emails. |
CRON_SECRET |
Secret used to authorize GET /api/reminders (the cron trigger). |
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID |
WalletConnect project ID, from cloud.walletconnect.com. |
Local UI development works fine without these — they only matter when exercising Supabase-backed reminders, email delivery, or WalletConnect. See docs/supabase-setup.md for the reminder schema.
App metadata & GitHub feedback integration
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_APP_URL |
https://app.iln.finance |
Base URL used in email links and deep links. |
NEXT_PUBLIC_APP_VERSION |
dev |
Version label shown in in-app release notes. |
NEXT_PUBLIC_CONTRACT_VERSION |
testnet:CD3TE3IA |
Contract version label shown in the admin health dashboard. |
GITHUB_TOKEN / GITHUB_OWNER / GITHUB_REPO |
(unset) | Used by the in-app feedback widget to file GitHub issues directly. |
Runtime-injected variables that don't belong in .env.local.example (like NODE_ENV) are tracked in .env.local.example.allowlist instead, and are exempt from env:check.
pnpm devOpen http://localhost:3000. To use a funded testnet wallet: open Freighter, switch to Testnet, copy your public key, fund it via the Stellar Testnet Friendbot, then connect Freighter from the app navbar.
| Command | Purpose |
|---|---|
pnpm dev |
Start the Next.js development server |
pnpm build |
Create a production build |
pnpm start |
Serve the production build |
pnpm run lint |
Run ESLint |
pnpm run lint:fix |
Run ESLint with automatic fixes |
pnpm run format / format:check |
Write / check Prettier formatting |
pnpm run env:check |
Verify .env.local.example covers every env var the code references |
pnpm test |
Run the Vitest unit/integration suite once |
pnpm run test:watch |
Run Vitest in watch mode |
pnpm run test:e2e |
Run the Playwright end-to-end suite |
pnpm run test:mutation |
Run Stryker mutation testing |
pnpm run verify |
Lint + env:check + format:check + typecheck + unit tests, in one shot |
pnpm run storybook |
Start Storybook locally on port 6006 |
pnpm run build-storybook |
Build static Storybook output |
pnpm run chromatic |
Run Chromatic visual regression checks |
pnpm run clean |
Remove build/test caches (.next, .turbo, coverage, etc.) |
pnpm run scaffold:component |
Scaffold a new component with a matching story/test file |
pnpm run generate:changelog |
Regenerate CHANGELOG.md via git-cliff |
The project uses a layered testing strategy rather than one tool for everything — see docs/testing.md for the full breakdown of when to reach for which tool. In short:
- Vitest + Testing Library for unit, hook, and component behavior (
__tests__/,src/**/__tests__/). - Playwright for critical end-to-end flows — wallet connection, invoice workflows, governance, responsive layouts (
e2e/). - jest-axe for component-level accessibility regressions.
- Storybook + Chromatic for visual regression and UI documentation.
- MSW to mock network responses where a real backend or contract node isn't needed.
- Stryker for periodic mutation-testing coverage audits.
pnpm test # unit/integration tests
pnpm run test:e2e # Playwright end-to-end suite
pnpm run verify # everything CI checks, in one command| Doc | What it covers |
|---|---|
| Developer Quickstart | Full setup guide, including the dev container / Codespaces path. |
| Frontend Architecture Overview | Data flows, directory-by-directory breakdown, the app/ vs src/app/ situation. |
| Testing Strategy | Which test tool to use for which kind of change. |
| Troubleshooting Guide | Local setup symptoms, Freighter connection, database gotchas. |
| Contributing Guidelines | Branching, commit conventions, code style, PR process. |
| Doc | What it covers |
|---|---|
| Route Map | Every canonical route, its purpose, and active redirects. |
| Feature Flags Reference | Every NEXT_PUBLIC_* flag and what it gates. |
| API Routes | Request/response shapes for the app's own API routes. |
| Error Codes Reference | Mapped contract error codes and remediation guidance. |
| i18n Setup Guide | Locale architecture and how to add a new locale. |
| Supabase Setup | Schema and setup for the payer reminder flow. |
| Doc | What it covers |
|---|---|
| CI/CD Overview | Workflow triggers, required status checks, runner configuration. |
| Visual Regression Workflow | Chromatic baseline configuration. |
| Lighthouse CI | Performance budget thresholds and how they're enforced. |
| Bundle Size Tracking | Bundle budget policy and how the size-check workflow works. |
| Contract Fixtures | Test fixtures used for Soroban contract interaction tests. |
| Contract Integration Status | Current status of live contract integration coverage. |
| Screen Reader Testing Guide | Manual a11y verification steps beyond automated checks. |
| Incident Response Process | Frontend-specific security incident response process. |
Additional internal references
| Doc | What it covers |
|---|---|
| Payer Routes Audit | Notes on the canonical payer dashboard route and historical aliases. |
| Repo Size Audit | Notes on repository/build artifact size. |
| Good First Issue Candidates | Curated, self-contained issues for new contributors. |
| Accessibility Implementation Summary | Summary of a11y work completed to date. |
| Toast Notification Accessibility Audit | Audit notes specific to the toast notification system. |
The UI follows a curated design language called The Fiscal Atelier — a "Warm Industrial" aesthetic combining structural Navy/Slate with warm parchment grays, a "no 1px borders" rule (containment via background-shift instead), and a typography pairing of Newsreader (serif, for display statements and data points) with Manrope (sans-serif, for functional UI text).
Read the full breakdown — layout grids, elevation layers, and color tokens — in DESIGN.md.
Contributions are welcome. Please read CONTRIBUTING.md first — it covers setup, testing standards, code style, and Stellar-specific conventions in detail. The short version:
- Create a branch:
git checkout -b feature/your-feature-name - Make your changes, and add/update stories and tests for any component behavior you touch.
- Commit using conventional commit format:
feat(scope): describe the change. - Run
pnpm run verifylocally before opening a PR. - Open a pull request against
main(ordevelop, depending on the target — see docs/ci-cd.md for branch-specific required checks).
New to the codebase? Good First Issue Candidates is a curated starting point.
This is a live financial application interacting with Soroban smart contracts and user wallets. If you find a security issue, please follow the disclosure process in SECURITY.md rather than opening a public issue — it also links to the frontend incident response process.
This repository does not currently declare a license file. Contact the maintainers before reusing or redistributing code from this repository.