Frontend¶
Home · Top · Table of Contents
Table of Contents¶
- Stack
- Commands
- Available Pages
- Wallet Configuration
- Contract Addresses
- Files And Storage
- Live Contract Draft Collaboration
- Encrypted Messaging And Two-Factor Authentication
- Email And Notifications
- Privacy Analytics
- Oracle Routes
- Solana Helpers
- Legal Localization Helpers
- Internationalization
- Styling And Motion
- Lifecycle Countdown UI
- FAQ And Recovery Routes
- Deployment
- Authors and Contributors
- Legal
Kevin K. Le (LinkedIn) — Founder, Founding Engineer, and Current Lead Engineer; Software Engineer at the Oregon Blockchain Group, University of Oregon.
Kellen Snider — Founding Engineer; Software Engineer at the Oregon Blockchain Group, University of Oregon. His vision, ideas, and dedication during TrustLedger's Ethereum development were invaluable to the codebase we build on today.
See
CREDITS.md.
This document explains the Next.js frontend under src/. Read it when changing
wallet connection, contract calls, API routes, email flows, file handling, or
frontend deployment.
Stack¶
Home · Top · Table of Contents
| Tool | Version Source | Purpose |
|---|---|---|
| Next.js | src/package.json |
App router frontend. |
| React | src/package.json |
UI runtime. |
| Reown AppKit | src/package.json |
Wallet connection modal. |
| wagmi | src/package.json |
React hooks and EVM client wiring. |
| viem | src/package.json |
EVM ABI and RPC primitives. |
| next-intl | src/package.json |
Internationalization. |
| Sass | src/package.json |
Shared SCSS motion and layout layer. |
| Resend | src/package.json |
Email delivery. |
| Jest/RTL | src/package.json |
Component and utility unit tests. |
| Playwright | src/package.json |
E2E browser tests. |
Commands¶
Home · Top · Table of Contents
Run frontend commands from src/.
| Task | Command |
|---|---|
| Install dependencies | npm install |
| Start dev server | npm run dev:frontend |
| Build | npm run build:frontend |
| Start production server | npm run start:frontend |
| Lint | npm run lint:frontend |
| Fix lint and formatting | npm run fix:frontend |
| Run unit tests | npm run test:unit |
| Install Playwright browser | npm run install:playwright |
| Run E2E tests | npm run test:e2e |
| Run React Doctor | npm run doctor |
Available Pages¶
Home · Top · Table of Contents
All user-facing routes are locale-prefixed. The canonical production base is
https://trustledger-zeta.vercel.app. English links use the /en prefix.
| Page | Production URL | Access | Description |
|---|---|---|---|
| Home | /en | Public | Landing page with contract phase walkthrough, value proposition, and chain-mode preview toggle. |
| About | /en/about | Public | Project background, contributors, and live age timer counting up from launch. |
| Analytics | /en/analytics | Public | Privacy-respecting event dashboard powered by the /api/analytics/events collector. |
| Arbitration | /en/arbitration/[id] | Wallet | Per-dispute juror panel: commit-reveal voting, evidence submission, appeals, and reward claims. |
| Client Accept | /en/client/accept | Token | Magic-link page for clients to review and fund a proposed contract. |
| Create Contract | /en/create | Wallet | Contract creation wizard with encrypted live draft collaboration and IPFS attachment support. |
| Dashboard | /en/dashboard | Wallet | Contract management hub: active, submitted, disputed, and resolved contracts for clients and freelancers. |
| FAQ | /en/faq | Public | Product FAQ and wallet/transaction recovery guide. |
| Freelancer Review | /en/freelancer/review | Token | Magic-link page for freelancers to review a client-proposed contract before accepting. |
| Juror Dashboard | /en/juror | Wallet | Juror staking, eligibility status, and open-dispute list. |
| Legal Index | /en/legal | Public | Index of all legal documents (terms, privacy policy, cookie policy, etc.). |
| Legal Document | /en/legal/[slug] | Public | Individual localized legal document (e.g., /en/legal/terms, /en/legal/privacy). |
| Reputation | /en/reputation | Public | Wallet reputation lookup, rating history, and recovery-mode status. |
| Status | /en/status | Public | GitHub analytics, deployment health, and project activity metrics. |
| Account | /en/account | Wallet | Connected wallet session overview, auto-logout setting, and Privacy & Data Rights (local data export, deletion, cookie preferences). |
| Admin | /en/admin | Admin | Read-only admin dashboard (requires magic-link session). |
| Admin Sign-In | /en/admin/sign-in | Public | Magic-link sign-in entry point for the admin dashboard. |
Access key:
- Public — no wallet or auth required.
- Wallet — connected wallet required; wallet-check gating is enforced client-side.
- Token — HMAC magic-link token required (delivered via email).
- Admin — active admin magic-link session required; server-side redirect enforced.
Wallet Configuration¶
Home · Top · Table of Contents
src/lib/wagmi.ts configures Reown AppKit and wagmi. Supported frontend
networks are:
| Network | Chain ID |
|---|---|
| Sepolia | 11155111 |
| Arbitrum One | 42161 |
| Base | 8453 |
| Optimism | 10 |
Set NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID for WalletConnect relay wallets.
Without it, injected wallets and Coinbase may still work, but relay-based mobile
and QR flows can fail.
Contract Addresses¶
Home · Top · Table of Contents
The frontend reads default and network-specific deployment variables from
src/lib/wagmi.ts. Run npm run sync:frontend:env after a local deploy to
write local addresses into src/.env.local. The Sepolia GitHub deployment
workflow writes Vercel environment variables automatically after deployment.
Read Environment for the full address variable list.
Files And Storage¶
Home · Top · Table of Contents
The frontend includes client-side encryption helpers in src/lib/encryption.ts.
The encryption format uses AES-256-GCM with PBKDF2-SHA256 and stores versioned
JSON metadata with salt, IV, and ciphertext.
IPFS upload support posts documents to /api/ipfs/pin, which reads the
server-only PINATA_JWT. Never expose Pinata bearer tokens with a
NEXT_PUBLIC_ prefix.
Live Contract Draft Collaboration¶
Home · Top · Table of Contents
The create-contract page supports encrypted draft sharing before deployment.
SecureDraftSessionPanel.tsx lets parties write terms in Markdown, HTML, or
plain text, apply small formatting helpers, upload local image attachments into
the draft body, and share a link plus a separate session key. The terms editor
handles Ctrl/Cmd+Z and redo shortcuts inside the collaborative draft area. The
default share action creates a one-time encrypted draft link; live co-editing
starts only when the user explicitly chooses Start Live Room.
Collaboration is intentionally plaintext-blind:
- The browser encrypts each draft snapshot with AES-GCM before it leaves the device.
- Snapshot share URLs contain
tl_draftonly; live-room URLs containtl_draftandtl_room. The separate session key is never sent to the server. - The connected wallet must match the encrypted allowlist before imported or live room snapshots decrypt.
useEncryptedDraftCollaboration.tsdebounces local edits, usesBroadcastChannelfor same-browser tab sync, and polls/api/create-collab/[roomId]for cross-browser updates./api/create-collab/[roomId]stores only short-lived encrypted snapshots with size limits, room validation, TTL pruning, and no plaintext contract terms.- The UI clears local share URLs and session keys after the user ends live sync
or completes contract submission. Ending live sync also calls
DELETE /api/create-collab/[roomId]so transient room snapshots are removed from the relay when they are no longer needed. - Copy actions show Copied! briefly and then return to Copy Link or
Copy Session Key. The email helper opens a
mailto:draft with the share link and separate session key; it never sends email server-side.
This is a production-shaped collaboration seam without committing the project to a vendor. For high-volume production rooms, replace the in-memory relay behind the same encrypted snapshot contract with Redis, Postgres realtime, Durable Objects, or a WebSocket service. Keep the browser-side encryption and wallet allowlist checks intact.
Encrypted Messaging And Two-Factor Authentication¶
Home · Top · Table of Contents
The messages UI lives at src/app/[locale]/messages/ and imports its components
from src/components/messages/ (ConversationList.tsx,
ActiveThreadPanel.tsx, MessageThread.tsx, MessageComposer.tsx,
types.ts). Messages are end-to-end encrypted: the client hook
src/lib/messagingCrypto.ts and the pure primitives in src/lib/crypto/e2e
handle X25519 key generation, per-conversation message-key derivation, and
encrypt/decrypt calls. Unwrapped keys live only in page memory and are never
written to storage. Outbound plaintext is moderated by a transient,
non-persisted server call (POST /api/messages/moderate) before the client
encrypts it.
Two-factor authentication (TOTP) is opt-in and surfaced through
src/components/TwoFactorSetting.tsx (account settings toggle) and
src/components/TotpStepUpPrompt.tsx (step-up challenge during sign-in), with
supporting UI in src/components/two-factor/.
Both features rely on the off-chain account session: src/lib/accountSession.ts
manages the challenge/response bearer token (cached in sessionStorage, never
localStorage) and src/lib/authedFetch.ts attaches it to authenticated
requests. Read Architecture for the
server-side services and database tables behind these surfaces.
Email And Notifications¶
Home · Top · Table of Contents
Magic links use HMAC-SHA256 tokens from src/lib/magicLink.ts. Email delivery
uses the provider abstraction in src/services/email.ts. Supported providers
are Resend, Brevo, Postmark, and a local-only log provider for development
testing. Magic-link recipients can be a comma- or semicolon-separated list for
limited multi-recipient test flows; the service de-duplicates recipients and
caps each send at five addresses.
The notification service supports contract offer, work submitted, approval,
dispute, dispute resolution, rating, and deadline reminder messages. Deadline
reminders are scheduled by src/vercel.json at:
The cron endpoint is /api/cron/deadline-reminders.
Privacy Analytics¶
Home · Top · Table of Contents
src/components/PrivacyAnalytics.tsx sends page-view and frontend-error beacons
only when NEXT_PUBLIC_PRIVACY_ANALYTICS_ENABLED=true. The matching server
collector at /api/analytics/events also requires
TRUSTLEDGER_ANALYTICS_ENABLED=true, so accidental client-side enablement does
not collect events by itself.
The collector is intentionally aggregate-only: it stores no cookies, wallet addresses, raw IP addresses, user agents, query strings, emails, raw documents, encrypted draft bodies, or session keys. It honors Do Not Track and Global Privacy Control headers.
Oracle Routes¶
Home · Top · Table of Contents
The frontend package exposes display-rate oracle routes:
| Route | Purpose |
|---|---|
/api/oracle/rates?base=eth"e=usd |
Validated exchange-rate lookup with TTL caching and stale fallback. |
/api/oracle/status |
Provider URL, TTL, supported pairs, and cache metadata. |
Read Oracle Architecture before adding assets, providers, or on-chain oracle consumption.
Solana Helpers¶
Home · Top · Table of Contents
src/helpers/solana.ts records the current Solana decision:
native-program-first support. It provides cluster defaults, Explorer URL
construction, and conservative public-key shape checks. Read
Solana Support before adding wallet or transaction code.
Legal Localization Helpers¶
Home · Top · Table of Contents
src/helpers/legal-docs.ts is the registry for legal document metadata. It
tracks source files, supported locales, translation status, and a constrained
translation prompt for machine-assisted drafts. Legal translations should remain
human-reviewed before publication; the helper exists to preserve Markdown shape
and prevent accidental changes to legal meaning.
The legal document route reads reviewed locale-specific Markdown from
src/content/legal/<locale>/<SOURCE_FILE>.md first and falls back to the
English source in src/content/legal/<SOURCE_FILE>.md. Keep translated legal
bodies out of the live route until they have been reviewed for legal meaning,
defined terms, numbering, links, and Markdown formatting.
Internationalization¶
Home · Top · Table of Contents
The frontend uses next-intl. Keep user-visible strings in the established
message structure and verify locale routing before moving text into components.
Every key in src/messages/en.json must exist in each supported locale file.
Run npm run i18n:scan after adding or moving visible copy. The scanner checks
locale key parity, blocks placeholder-prefixed translations, and fails when JSX
or visible attributes contain hard-coded English instead of message keys.
Styling And Motion¶
Home · Top · Table of Contents
TrustLedger uses restrained motion for state feedback only. Countdown panels, wallet menus, walkthrough controls, live-sync indicators, and action buttons may animate hover, focus, progress, or state changes. They must honor reduced motion and must not hide content until an animation completes.
Lifecycle Countdown UI¶
Home · Top · Table of Contents
Dashboard contract cards show a live next-stage countdown when the on-chain contract has a relevant deadline:
- Active contracts count down to the freelancer delivery deadline.
- Submitted contracts count down to the client approval or dispute window.
- Approved contracts with a warranty hold-back count down to the hold-back unlock time.
The countdown updates once per second for user clarity. It is display-only; the smart contract remains the enforcement source for reclaim, release, and warranty claims. Expired timers switch to a "Since Expiry" label so users can tell that the next action may be available.
The /[locale]/about route includes a compact project stopwatch that counts up
from May 2, 2026. The footer links to this route so project background can grow
without adding clutter to the dashboard or create-contract flows.
Global styling lives in src/app/globals.scss and imports Tailwind v4,
src/app/helpers.css, and src/app/app-desktop.scss. The helper layer owns
reusable surfaces, text helpers, link underlines, accessibility helpers,
responsive clusters, and high-contrast behavior. app-desktop.scss owns shared
layout widths, page headers, workspace grids, and responsive shell behavior. Use
Tailwind for component structure and helper classes for repeated theme,
interaction, and motion states.
Home-page motion currently includes contract phase transitions, progress
feedback, signature verification feedback, CTA hover treatment, value lift,
status pulse, document hash shimmer, orbit motion, link underline motion, and
protection-list interaction. Every new animation must keep content visible by
default and honor prefers-reduced-motion.
FAQ And Recovery Routes¶
Home · Top · Table of Contents
The product FAQ route is app/[locale]/faq/page.tsx. The custom 404 experience
is implemented by app/[locale]/not-found.tsx for localized app routes and
app/not-found.tsx for root-level fallback routes. Keep FAQ links available in
the top navigation and footer so users can recover from wallet, route, and
transaction issues without leaving the app.
Branded HTTP status pages replace the Vercel/Next defaults for 400, 401,
403, 405, 408, 429, 500, 502, 503, and 504 at
app/[locale]/<status>/page.tsx, each sharing the animated scene and copy in
components/ErrorStateContent.tsx (reduced-motion safe, localized across all
eight locales). Runtime failures are caught by app/[locale]/error.tsx (route
boundary, localized) and app/global-error.tsx (self-contained root boundary
that renders its own shell when the layout itself fails).
Deployment¶
Home · Top · Table of Contents
The root deploy.yml workflow runs vercel deploy --prod from src/ after
writing contract address variables to Vercel. For local frontend-only
deployment, use:
The canonical deployed frontend route is
https://trustledger-zeta.vercel.app/en.
Authors and Contributors¶
Home · Top · Table of Contents
- Kevin K. Le — Founder, Founding Engineer, and Current Lead Engineer (LinkedIn)
- Kellen Snider — Founding Engineer (LinkedIn)
See CREDITS.md for the complete acknowledgement list.
Legal¶
Home · Top · Table of Contents
This document is part of TrustLedger, an open-source decentralized escrow and
arbitration protocol. Use of this software and documentation is subject to the
Terms and Conditions,
Privacy Policy, and Risk Disclosure.
See LEGAL.md for the full compliance and licensing overview.