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 records
  • components/dashboard/ – Statistics widgets and data visualizations
  • components/settings/ – Profile, LLM configuration, and subscription UI
  • components/forms/ – Reusable field components including FormInput and FormSelect

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, and lib/ + models/ for business logic.
  • Next.js 14 app router patterns power the frontend with type-safe layouts in app/layout.tsx and app/page.tsx.
  • Prisma and PostgreSQL handle persistence, with schema definitions in prisma/schema.prisma and query logic in models/.
  • Better-Auth in lib/auth.ts provides 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →