# How to Build TaxHacker from Source: Complete Self-Hosting Guide

> Learn how to build TaxHacker from source with this complete self-hosting guide. Follow simple steps to set up your Node.js and PostgreSQL environment for development.

- Repository: [Vasily Zubarev/TaxHacker](https://github.com/vas3k/TaxHacker)
- Tags: how-to-guide
- Published: 2026-04-01

---

**Building TaxHacker from source requires Node.js 20+, a PostgreSQL database, and environment variables configured in `.env` before running `npm install` and `npm run dev` to start the Next.js 15 application on port 7331.**

TaxHacker is a self-hosted AI-powered accounting web application that extracts data from receipts and invoices using LLM providers. The source repository at `vas3k/TaxHacker` is built with **Next.js 15**, **Prisma**, and **PostgreSQL**, making it straightforward to compile and run locally for development or production self-hosting.

## Prerequisites

Before building TaxHacker from source, ensure your system has:

- **Node.js 20** or higher (LTS recommended)
- **npm** (bundled with Node.js)
- **PostgreSQL** 12+ (local instance or container)
- **Git** for cloning the repository

## Step-by-Step Build Instructions

### 1. Clone the Repository

Clone the TaxHacker repository and navigate into the project directory:

```bash
git clone https://github.com/vas3k/TaxHacker.git
cd TaxHacker

```

### 2. Install Node Dependencies

Install the required npm packages including Next.js 15, Prisma, and React dependencies:

```bash
npm install

```

This command populates `node_modules/` with all dependencies defined in [`package.json`](https://github.com/vas3k/TaxHacker/blob/main/package.json), including the Prisma CLI and Next.js build tools.

### 3. Configure Environment Variables

Create a `.env` file from the provided example and edit the required variables:

```bash
cp .env.example .env

```

 Edit the file to include at minimum:

- `BETTER_AUTH_SECRET` — A random string of at least 16 characters (used in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts) for session encryption)
- `DATABASE_URL` — PostgreSQL connection string (e.g., `postgresql://user:pass@localhost:5432/taxhacker`)
- `UPLOAD_PATH` — Directory for receipt storage (default `./data/uploads`)
- `SELF_HOSTED_MODE` — Set to `true` to enable auto-login for local testing
- `OPENAI_API_KEY`, `GOOGLE_API_KEY`, or `MISTRAL_API_KEY` — Optional LLM credentials for AI extraction

### 4. Initialize the Database

Generate the Prisma client and apply database migrations:

```bash
npx prisma generate
npx prisma migrate dev --name init

```

The `prisma generate` command creates the type-safe `@prisma/client` based on `prisma/schema.prisma`, while `migrate dev` creates the database tables for users, transactions, and projects.

### 5. Start the Development Server

Launch the Next.js development server with Turbopack:

```bash
npm run dev

```

The application binds to **http://localhost:7331** by default (configurable via the `PORT` environment variable in `.env`). In development mode, the app uses the configuration from [`next.config.ts`](https://github.com/vas3k/TaxHacker/blob/main/next.config.ts) and auto-reloads on file changes.

### 6. Production Build (Optional)

For production deployment from source, build the optimized bundle and start the server:

```bash
npm run build
npm run start

```

The `npm run start` command executes the production server and automatically runs pending database migrations before binding to the configured port.

## Docker-Based Build Alternative

If you prefer containerized deployment over building from source locally, TaxHacker provides a ready-made Docker configuration.

### Using Docker Compose

Start both the application and PostgreSQL database with:

```bash
docker compose up -d

```

The [`docker-compose.yml`](https://github.com/vas3k/TaxHacker/blob/main/docker-compose.yml) orchestrates two services: the TaxHacker app container (`ghcr.io/vas3k/taxhacker:latest`) and a PostgreSQL 17 instance with persistent storage at `./data/postgres`. Environment variables defined in the compose file handle database connections and authentication automatically.

### Custom Dockerfile Build

To build a custom image from the local source:

```bash
docker build -t taxhacker:custom .
docker run -p 7331:7331 --env-file .env taxhacker:custom

```

The `Dockerfile` uses a multi-stage build to compile the Next.js application and configure the production runtime environment.

## Key Configuration Files

Understanding these core files helps troubleshoot build issues:

### Database Schema and Migrations

The `prisma/schema.prisma` file defines the data model for users, transactions, custom fields, and projects. The [`lib/db.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/db.ts) file exports a singleton Prisma client used throughout the application:

```typescript
// lib/db.ts
import { PrismaClient } from '@prisma/client'

export const db = new PrismaClient()

```

### Authentication Setup

TaxHacker uses **better-auth** for session management, configured in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts). When `SELF_HOSTED_MODE` is enabled, the middleware ([`middleware.ts`](https://github.com/vas3k/TaxHacker/blob/main/middleware.ts) at the project root) permits auto-login without credentials, simplifying local development.

### LLM Provider Configuration

AI receipt extraction supports OpenAI, Google Gemini, and Mistral through adapters defined in [`lib/llm-providers.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/llm-providers.ts):

```typescript
// lib/llm-providers.ts
import { OpenAI } from '@langchain/openai'

export function createLLM() {
  if (process.env.OPENAI_API_KEY) {
    return new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
  }
  // Additional provider checks...
}

```

### File Upload Storage

Uploaded receipts and invoices are stored at the path specified by `UPLOAD_PATH`. The [`lib/uploads.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/uploads.ts) and [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts) utilities handle file operations, requiring **GraphicsMagick** and **Ghostscript** for PDF conversion and image previews when processing documents outside the browser.

## Summary

- **Source builds** require Node.js 20+, npm, and PostgreSQL configured via `DATABASE_URL` in `.env`
- **Development workflow**: `npm install` → `npx prisma migrate dev` → `npm run dev` runs the app on port 7331
- **Production builds** use `npm run build` followed by `npm run start`, which automatically handles database migrations
- **Docker deployment** offers a faster alternative via `docker compose up -d` using the official `ghcr.io/vas3k/taxhacker` image
- **Critical env vars**: `BETTER_AUTH_SECRET` (min 16 chars), `SELF_HOSTED_MODE`, and optional LLM API keys for AI features

## Frequently Asked Questions

### What Node.js version is required to build TaxHacker?

TaxHacker requires **Node.js 20 or higher**. The [`package.json`](https://github.com/vas3k/TaxHacker/blob/main/package.json) specifies Next.js 15 and React 19 dependencies that rely on modern Node features. Building with older versions may result in compilation errors during the `npm install` or build phases.

### Can I run TaxHacker without Docker?

Yes. The source build process documented above runs entirely without Docker by executing `npm run dev` or `npm run start` directly. You only need a local PostgreSQL instance accessible via the `DATABASE_URL` environment variable. The Docker compose file is provided as a convenience for users who prefer containerized deployment.

### How do I configure AI receipt extraction?

Set one of the provider API keys in your `.env` file: `OPENAI_API_KEY`, `GOOGLE_API_KEY`, or `MISTRAL_API_KEY`. The application detects available keys in [`lib/llm-providers.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/llm-providers.ts) and initializes the corresponding LangChain adapter. If no keys are configured, the application runs without AI features, though manual data entry remains functional.

### Where are uploaded files stored?

Files are stored at the path defined by the `UPLOAD_PATH` environment variable, which defaults to `./data/uploads` relative to the project root. When using Docker, this path is typically mounted as a volume from the host (e.g., `./data:/app/data` in [`docker-compose.yml`](https://github.com/vas3k/TaxHacker/blob/main/docker-compose.yml)) to ensure persistence across container restarts.