A self-hosted document management web application for uploading, organizing, and viewing documents directly in the browser. Built with Next.js, Turso, and Cloudflare R2.
- Document Upload - Upload documents with automatic metadata extraction
- Categories - Create and assign categories to organize documents
- Tags - Add custom tags for flexible document classification
- In-Browser Viewing - View documents without downloading:
- PDF files via
@pdf-viewer/react - DOCX files via
docx-preview - Markdown files via
react-markdownwith GFM support - Plain text files
- PDF files via
- Download Option - Download documents directly when needed
- Private Storage - Documents stored in private Cloudflare R2 bucket
- Admin Login - Private email/password login with JWT cookie sessions
- Framework: Next.js 16 (App Router)
- UI: shadcn/ui + Tailwind CSS v4
- Database: Turso (libSQL/SQLite)
- ORM: Drizzle ORM
- Storage: Cloudflare R2 (private bucket)
- Document Preview: pdf-viewer, docx-preview, react-markdown
- Package Manager: pnpm
- Linting: Biome
- Node.js 22 LTS (recommended; Next.js requires 20.9.0 or newer)
- pnpm
- Turso account
- Cloudflare account with R2
-
Copy the environment template:
cp .env.local.example .env.local
-
Configure your environment variables:
# Turso Database TURSO_DATABASE_URL=libsql://your-db-name-your-org.turso.io TURSO_AUTH_TOKEN=your-turso-auth-token # Auth AUTH_JWT_SECRET=your-long-random-auth-secret ADMIN_USER=admin@example.com ADMIN_PASSWORD=replace-with-a-strong-password # Cloudflare R2 Storage R2_ACCOUNT_ID=your-cloudflare-account-id R2_ACCESS_KEY_ID=your-r2-access-key-id R2_SECRET_ACCESS_KEY=your-r2-secret-access-key R2_BUCKET_NAME=your-bucket-name
pnpm installPush the schema to your Turso database:
pnpm db:pushSeed the admin user once from your environment:
pnpm db:seed-adminThis creates the admin_users row using ADMIN_USER and ADMIN_PASSWORD from your environment.
pnpm devOpen http://localhost:3000 to start using the application.
src/
├── app/ # Next.js App Router pages
│ ├── api/ # API routes
│ ├── documents/[id]/ # Document viewer page
│ └── page.tsx # Home page
├── components/
│ ├── documents/ # Document-related components
│ ├── upload/ # Upload components
│ ├── ui/ # shadcn/ui components
│ └── viewers/ # Document viewers (PDF, DOCX, MD, TXT)
├── lib/
│ ├── actions/ # Server actions
│ ├── db/ # Drizzle ORM setup & schema
│ └── storage/ # R2 storage utilities
| Command | Description |
|---|---|
pnpm dev |
Start development server |
pnpm build |
Build for production |
pnpm start |
Start production server |
pnpm lint |
Run Biome linting |
pnpm format |
Format code with Biome |
pnpm typecheck |
Run TypeScript checks |
pnpm db:seed-admin |
Seed the admin user from ADMIN_USER and ADMIN_PASSWORD |
pnpm db:generate |
Generate Drizzle migrations |
pnpm db:push |
Push schema to database |
pnpm db:studio |
Open Drizzle Studio |
- documents - Uploaded file metadata
- categories - Document categories with color coding
- tags - Reusable document tags
- documentCategories - Many-to-many document-category relationships
- documentTags - Many-to-many document-tag relationships