Project Structure of vas3k/TaxHacker: Next.js 14 Architecture and Directory Guide
The vas3k/TaxHacker repository follows a feature-oriented Next.js 14 app router structure organized into three main layers: the app/ directory for routing and layouts, components/ for UI primitives and domain widgets, and lib/ paired with models/ for business logic and data access, all backed by Prisma and PostgreSQL.
TaxHacker is a modern full-stack tax management application built with Next.js 14, TypeScript, and Prisma. Understanding the project structure of vas3k/TaxHacker reveals a clean architectural separation between server-side rendering logic, reusable interface components, and type-safe data persistence layers. The codebase leverages the latest Next.js app router patterns alongside Better-Auth for authentication and Tailwind CSS for styling.
Top-Level Directory Organization
The repository root organizes code by technical responsibility. Key directories include app/ for Next.js routing, components/ for React components, lib/ for utilities and services, and models/ for data access wrappers.
| Directory | Purpose | Key Files |
|---|---|---|
app/ |
Next.js 14 app router entry points | layout.tsx, page.tsx, loading.tsx |
components/ |
Reusable UI components | ui/, forms/, dashboard/, transactions/ |
lib/ |
Configuration, auth, and database | config.ts, auth.ts, db.ts |
models/ |
Prisma model wrappers | users.ts, transactions.ts |
prisma/ |
Database schema and client | schema.prisma |
.github/ |
CI/CD workflows | workflows/docker-release.yml |
The Next.js App Router Structure
The app/ directory implements Next.js 14's app router pattern with nested layouts and error boundaries.
app/layout.tsx serves as the root layout, wrapping all pages with global providers and navigation shells. app/page.tsx handles the home route, redirecting authenticated users to the dashboard or visitors to the landing page. app/loading.tsx provides global suspense fallback UI, while app/global-error.tsx catches uncaught exceptions at the root level.
Route groups and dynamic segments follow standard Next.js conventions, with individual route folders co-locating page logic, loading states, and error handlers.
Component Architecture
Components are organized by scope and reusability. The components/ui/ directory contains Tailwind-styled primitives like Button, Select, and Table that serve as building blocks throughout the application.
Feature-specific components reside in dedicated subdirectories:
components/transactions/– CRUD interfaces for financial recordscomponents/dashboard/– Statistics widgets and data visualizationscomponents/settings/– Profile, LLM configuration, and subscription UIcomponents/forms/– Reusable field components includingFormInputandFormSelect
Data Layer: Prisma and Models
Database access flows through two layers. prisma/schema.prisma defines the PostgreSQL schema including User, Transaction, Category, Project, and File entities with their relations.
The lib/db.ts file exports a singleton Prisma client instance for use across the application. models/ contains thin TypeScript wrappers that encapsulate Prisma queries and business logic, such as models/users.ts which handles user lookup and self-hosted mode support.
Configuration and Authentication
Centralized configuration lives in lib/config.ts, which validates environment variables through Zod schemas. This ensures type-safe access to BASE_URL, AI provider keys, Stripe secrets, and database URLs.
Authentication is implemented in lib/auth.ts using Better-Auth with JWT sessions and email OTP delivery via Resend. The auth layer supports a self-hosted shortcut mode that bypasses standard flows for local development.
Infrastructure Files
Deployment and development are containerized via Dockerfile and docker-compose.yml, orchestrating PostgreSQL and Redis services. GitHub Actions workflows in .github/workflows/ automate Docker builds and releases.
Working with the Codebase
Accessing Typed Configuration
Environment variables are accessed through the centralized config object:
import config from '@/lib/config';
// Access validated environment variables
console.log('App base URL →', config.app.baseURL);
if (config.ai.openaiApiKey) {
// Initialize OpenAI client with type-safe key
const client = new OpenAI({ apiKey: config.ai.openaiApiKey });
}
Source: lib/config.ts defines the Zod schema and validation logic.
Fetching the Current User
Authentication helpers provide session management:
import { getCurrentUser } from '@/lib/auth';
export async function showUserInfo() {
const user = await getCurrentUser(); // Redirects if unauthenticated
console.log(`Hello, ${user.name}!`);
}
Source: lib/auth.ts implements Better-Auth integration.
Database Operations
Prisma client operations follow this pattern:
import { prisma } from '@/lib/db';
async function createTransaction(userId: string, data: Partial<Transaction>) {
return await prisma.transaction.create({
data: { ...data, userId },
});
}
async function recentTransactions(userId: string, limit = 10) {
return await prisma.transaction.findMany({
where: { userId },
orderBy: { issuedAt: 'desc' },
take: limit,
});
}
Source: lib/db.ts exports the Prisma client; prisma/schema.prisma defines models.
Using UI Components
Form components accept standardized props:
import { FormSelect } from '@/components/forms/simple';
export function CurrencyPicker() {
const [currency, setCurrency] = useState('USD');
const currencies = [
{ code: 'USD', name: 'US Dollar', color: '#009933' },
{ code: 'EUR', name: 'Euro', color: '#003399' },
];
return (
<FormSelect
items={currencies}
title="Currency"
placeholder="Select currency"
value={currency}
onValueChange={setCurrency}
required
/>
);
}
Source: components/forms/simple.tsx exports reusable form primitives.
Summary
- The project structure of vas3k/TaxHacker separates concerns into
app/for routing,components/for UI, andlib/+models/for business logic. - Next.js 14 app router patterns power the frontend with type-safe layouts in
app/layout.tsxandapp/page.tsx. - Prisma and PostgreSQL handle persistence, with schema definitions in
prisma/schema.prismaand query logic inmodels/. - Better-Auth in
lib/auth.tsprovides JWT-based authentication with email OTP support. - Tailwind CSS components in
components/ui/offer reusable design system primitives. - Docker and GitHub Actions in
.github/workflows/enable automated CI/CD pipelines.
Frequently Asked Questions
What framework powers the TaxHacker frontend?
TaxHacker uses Next.js 14 with the app router architecture. The entry points reside in the app/ directory, where app/layout.tsx provides the root layout and app/page.tsx handles the home route with conditional redirects to either the dashboard or landing page.
How does TaxHacker handle database migrations and schema?
Database schema is defined in prisma/schema.prisma, which models entities like User, Transaction, and Category with their PostgreSQL relations. The Prisma client is instantiated in lib/db.ts and consumed through typed model wrappers in the models/ directory, ensuring compile-time safety for all database queries.
Where are environment variables validated and accessed?
All environment variables flow through lib/config.ts, which uses Zod for parsing and validation. This creates a type-safe configuration object exposing BASE_URL, AI provider keys, Stripe secrets, and database connection strings with runtime validation that fails fast on missing or invalid values.
What authentication library does TaxHacker use?
The project implements Better-Auth via lib/auth.ts, supporting JWT sessions and email-based OTP authentication through Resend. The system also includes a self-hosted mode that bypasses standard authentication flows for local development environments, implemented in models/users.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →