The Problem

Organizations and individuals need a simple, self-hostable document archival platform that handles long-term storage, full-text search, email ingestion, and content extraction from scanned documents without vendor lock-in. Most existing solutions either require SaaS subscriptions, lack robust content extraction, or demand complex infrastructure for features like organization-level custom properties and tagging rules.

What This Does

Papra is a full-featured document management platform built on a monorepo structure with 1655 files across apps/ (1435 files), packages/ (186 files), and root (16 files). The codebase is TypeScript-heavy (1080 TS files, 231 TSX files) with a React-based web client (apps/papra-client/src/index.tsx), a Next.js/docs site (apps/docs/), and a React Native mobile app (apps/mobile/app/index.tsx). Core services live in apps/papra-server/src/index.ts and apps/papra-server/src/modules/app/server.ts, handling API routing, organization management, and document operations. The mobile app (apps/mobile/src/modules/documents/documents.services.ts) integrates scanning, import, and sync workflows. Shared infrastructure includes API clients (apps/mobile/src/modules/api/api.client.ts), authentication modules (apps/mobile/src/modules/auth/auth.client.ts), and config services (apps/mobile/src/modules/config/config.services.ts). A .changeset/ directory indicates intentional versioning workflows, and 259 test files exist across the monorepo.

How It Is Wired

Execution originates at three entry points: apps/papra-server/src/index.ts (Node/Express server), apps/papra-client/src/index.tsx (web SPA), and apps/mobile/app/index.tsx (React Native). The server routes through apps/papra-server/src/modules/app/server.ts to organization- and document-level handlers. The web client (apps/papra-client/src/index.tsx) renders via Vite and consumes the API; the mobile client routes through apps/mobile/src/modules/app-providers.tsx for global providers (auth, config, app state). Key out-of-process effects occur via email ingestion (OWLRelay integration referenced in docs), Docker Compose generation (apps/docs/src/docker-compose-generator/dc-generator.astro), and content extraction using Transformer models. The .changeset/config.json governs version bumps across the monorepo. The server touches the filesystem for document storage, the database for metadata, and external services for OAuth and email processing—wiring is dense but explicitly structured per-module rather than monolithic.

How To Use It

Setup:

pnpm install

Installs across 5 package folders (apps/docs, apps/mobile, apps/papra-client, apps/papra-server, apps/website). Docker Compose is available via apps/docs/src/docker-compose-generator/dc-generator.astro and documented in apps/docs/src/content/docs/02-self-hosting/.

Configuration: Environment variables are expected in apps/papra-server/.env (not present in the structure—add your own). Required keys likely include database connection strings, OAuth credentials, and email server details per the self-hosting guides.

Running it:

# Development
pnpm --filter @papra/server dev
# or via Docker Compose (see docs)
pnpm --filter @papra/docs dev

The server starts at apps/papra-server/src/index.ts; the web client at apps/papra-client/src/index.tsx; the mobile dev server via apps/mobile.

Real-World Use

A law firm stores client intake PDFs and automatically tags contracts by extracting text via Transformer models. An employee forwards an invoice email to the generated address (@papra.app), which lands in apps/papra-server/src/modules/email/ (inferred from the ingestion guides), triggers content extraction, and files it under the correct organization with custom properties. The mobile team then retrieves it via the React Native app (apps/mobile/app/(app)/document/view.tsx) with full-text search.

Code Health & Issues

  • Measured: 259 test files found; 95 doc files found. No structural red flags detected—tests, CI, license, and lockfile are present where expected.
  • SDLC: No .env file in the server app (add your own). The monorepo uses .changeset/ for versioning but has no LICENSE at root beyond the LICENSE file present. Deep analysis of runtime behavior has not run for this repo yet.

The Bottom Line

Papra is a capable, well-structured document archival platform with genuine self-hosting flexibility, TypeScript rigor, and a broad feature set (email ingestion, content extraction, tagging rules, organizations). The monorepo layout and pnpm workspace make it maintainable for a team comfortable with modern JS tooling. It’s best suited for teams that need on-prem document control without building infrastructure from scratch—but expect to provision your own database, OAuth keys, and email stack.