A modern, full-featured financial transaction management application built with Next.js 15, React 19, and TypeScript. This platform seamlessly integrates Plaid for bank connectivity, Dwolla for ACH transfers, Appwrite for real-time database management, and Tailwind v3 shadcn/ui for a beautiful, accessible UI.
This application is a complete fintech solution that connects users to their bank accounts, displays transaction history, and enables secure fund transfersβall through modern web technologies and industry-standard financial APIs.
| Layer | Technologies |
|---|---|
| Framework | Next.js 15.1.6 (App Router) |
| Runtime | React 19.2.3 |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 3.4.19 + Animations |
| UI Components | shadcn/ui + Radix UI |
| Forms | React Hook Form 7.71.2 + Zod validation |
| Charts | Chart.js 4.5.1 + React-ChartJS-2 |
| Bank Connectivity | Plaid 41.4.0 |
| Payments | Dwolla v2 3.4.0 |
| Database | Appwrite (Node SDK 20.0.0) |
| Utilities | react-countup, query-string, clsx, tailwind-merge |
The app uses Next.js Route Groups (parentheses in folder names) to organize layouts without affecting URL paths:
app/
βββ (auth)/ # Authentication routes (separate layout)
β βββ sign-in/ # Login page
β βββ sign-up/ # Registration page
β βββ layout.tsx # Auth-specific layout (no sidebar)
β
βββ (root)/ # Protected routes (with sidebar layout)
β βββ dashboard/ # Main dashboard with balance overview
β βββ my-banks/ # Bank accounts management
β βββ transaction-history/ # Full transaction details & filtering
β βββ transfer/ # Money transfer interface
β βββ layout.tsx # Root layout with Sidebar + Navigation
β
βββ api/ # API routes for backend logic
β βββ auth/ # Authentication endpoints
β βββ plaid/ # Plaid webhook handlers
β βββ dwolla/ # Dwolla payment callbacks
β
βββ layout.tsx # Root layout wrapper
βββ globals.css # Global Tailwind styles
βββ global-error.tsx # Global error boundary
Key Benefit: The (auth) group uses a clean layout without navigation, while (root) uses a full-featured layout with sidebarsβall without changing actual URLs.
All data mutations and fetches happen in server-side action files using Next.js App Router patterns:
user.actions.ts- User registration, login, profile management, and session handling with Appwritebanks.actions.ts- Bank account linking via Plaid, account list retrieval, account details fetchingtransactions.actions.ts- Transaction history queries, filtering, and paginationdwolla.actions.ts- ACH transfer creation, fund recipient setup, payment processing
// lib/appwrite.ts
createSessionClient() // For user-authenticated operations (read/write own data)
createAdminClient() // For server-side admin operations (database access with API key)Both clients use getter methods for lazy-loaded Account, Database, and Users services.
Layout & Navigation:
Sidebar.tsx- Left navigation for desktopMobileNav.tsx- Responsive mobile navigationRightSidebar.tsx- Additional info panelHeaderBox.tsx- Page header with greeting
Financial Display:
BankCard.tsx- Bank account card with balance displayBankInfo.tsx- Detailed bank account informationBankDropDown.tsx- Account selector dropdownBankTabItem.tsx- Tab-based account switcherTotalBalanceBox.tsx- Aggregated balance displayAnimatedCounter.tsx- Animated number transitions usingreact-countup
Forms & Input:
AuthForm.tsx- Login/signup form with React Hook Form + Zod validationPaymentTransferForm.tsx- Money transfer form with validationFormInputField.tsx- Reusable form input component
Integrations:
PlaidLink.tsx- Plaid Link button to connect banksCategory.tsx- Transaction category display
Data Visualization:
TransactionsTable.tsx- Sortable, paginated transaction tableDoughnutChart.tsx- Chart.js doughnut chart for spending by categoryRecentTransactions.tsx- Quick view of latest transactionspagination.tsx- Reusable pagination component
UI Elements:
Copy.tsx- Copy-to-clipboard utility componentFooter.tsx- Application footer
The app uses shadcn/ui (built on Radix UI) for accessible, customizable components:
- Form inputs with built-in validation
- Buttons with multiple variants
- Dropdown menus
- Modals and dialogs
- Tables
- Tooltips
Components are stored in components/ui/ and styled with Tailwind CSS.
React Hook Form provides efficient, performant form handling with minimal re-renders:
const form = useForm({
resolver: zodResolver(authFormSchema),
defaultValues: { email: "", password: "" }
});
const onSubmit = async (data) => {
// Validated data only reaches here
await signUpUser(data);
};Benefits:
- Isolated component re-renders
- Built-in error handling
- Client-side validation before server
- Easy integration with Zod schemas
useState()- Component state managementuseEffect()- Side effects, data fetchinguseCallback()- Memoized callback functionsuseMemo()- Memoized values (for expensive calculations)useRef()- Direct DOM access for animationsuseContext()- Global state (if applicable)useTransition()- Handling server action loading statesuseActionState()- Managing server action state
While not explicitly shown in the structure, common custom hooks would include:
useAuth()- Authentication state and functionsuseUser()- Current user data and profileuseTransactions()- Fetch and filter transactionsuseBanks()- Manage connected bank accountsuseBalance()- Calculate and update total balanceusePlaidLink()- Handle Plaid Link flowuseDwolla()- Handle transfer workflows
Visualize spending categories using Chart.js:
// components/DoughnutChart.tsx
import { Doughnut } from "react-chartjs-2";
<Doughnut
data={chartData}
options={chartOptions}
/>Features:
- Real-time category breakdown
- Responsive sizing
- Custom colors per category
- Interactive legend
- PlaidLink Component initiates Plaid Link modal
- User selects their bank and authenticates
- Plaid returns a public token
- Exchange public token for access token via API
- Store token in Appwrite database
- Fetch transactions and account details using token
components/PlaidLink.tsx- Link UI componentlib/plaid.ts- Plaid client initializationlib/actions/banks.actions.ts- Server actions for token exchange and data fetching
- User fills transfer form with amount and recipient
- Create recipient using Dwolla API (if new)
- Initialize transfer between accounts
- Dwolla processes ACH transaction
- Webhook updates transaction status
components/PaymentTransferForm.tsx- Transfer UIlib/actions/dwolla.actions.ts- Transfer orchestrationapp/api/dwolla/webhook- Payment status updates
- User login creates Appwrite session
- Session stored in
httpOnlycookie createSessionClient()uses session for authenticated queries
- Users - User profiles, KYC data
- Banks - Linked bank accounts and tokens
- Transactions - Transaction history and details
Appwrite provides real-time database updates for:
- Transaction status changes
- New transfer completions
- Balance updates
# Development server (hot reload)
npm run dev
# Production build
npm run build
# Start production server
npm start
# Linting
npm run lintCreate .env.local:
# Appwrite
NEXT_PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT=your_project_id
NEXT_APPWRITE_KEY=your_api_key
# Plaid
NEXT_PUBLIC_PLAID_CLIENT_ID=your_client_id
PLAID_SECRET=your_secret_key
PLAID_ENV=sandbox
# Dwolla
DWOLLA_ENV=sandbox
DWOLLA_KEY=your_key
DWOLLA_SECRET=your_secret
# Database
DATABASE_URL=your_db_urlimport { z } from "zod";
const authFormSchema = z.object({
email: z.string().email("Invalid email"),
password: z.string().min(8, "Min 8 characters"),
firstName: z.string().min(2, "Min 2 characters"),
lastName: z.string().min(2, "Min 2 characters"),
});
type AuthFormData = z.infer<typeof authFormSchema>;- Mobile-first approach
sm:(640px),md:(768px),lg:(1024px),xl:(1280px)- Responsive components for all screen sizes
- MobileNav for tablet/mobile, Sidebar for desktop
Tailwind's animate-* utilities combined with tw-animate-css:
- Smooth transitions on data load
- Button hover effects
- Modal animations
- Loading spinners
- User fills
PaymentTransferForm.tsx - React Hook Form validates against schema
- Form submission calls server action
createTransfer() - Server action calls Dwolla API
- Dwolla processes ACH transfer
- Webhook updates Appwrite database
- UI reflects new transaction in
TransactionsTable.tsx
β
Secure user authentication with Appwrite
β
Multi-bank account linking via Plaid
β
ACH fund transfers with Dwolla
β
Real-time transaction history
β
Spending analytics with Chart.js
β
Responsive design with Tailwind CSS
β
Type-safe forms with React Hook Form + Zod
β
Accessible UI with shadcn/ui + Radix
β
Server-side rendering with Next.js
β
Production-ready error handling
- Next.js Documentation
- React Documentation
- Tailwind CSS
- shadcn/ui
- React Hook Form
- Zod Validation
- Plaid Documentation
- Dwolla Documentation
- Appwrite Documentation
- Chart.js Documentation
Private Repository - All rights reserved.