a1f523628ed617ec1f3fb373bd5540576f183373
Document Template Editor
FastAPI + React application for managing Jinja2-annotated .docx document templates.
Features
- Authentication with JWT (register/login)
- User roles:
userandadminwith admin user management panel - Initial admin: seeded from
.envon startup - Template upload: load a
.docxfile with Jinja2 placeholders - Auto-detected form fields: variables become text, textarea, number, date, table cell, or repeating table row fields
- Style preservation: font, alignment, table cell styles captured from the original document
- Document preview: render filled template as HTML preview
- Export: download as
.docxor.pdf - Reusable templates: fill the same template multiple times
Project Structure
backend/ # FastAPI API
frontend/ # React + Vite UI
samples/ # Sample .docx templates
Quick Start (Docker)
cp .env.example .env
docker compose up --build
| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Backend | http://localhost:8000 |
| API docs | http://localhost:8000/docs |
Default admin: admin / admin123 (configure in .env).
Stop: docker compose down · Remove data: docker compose down -v
Quick Start (Local)
Requires PostgreSQL running locally (or use Docker only for the database):
docker compose up db -d
Backend
cd backend
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
uvicorn app.main:app --reload --port 8000
Frontend
cd frontend
npm install
npm run dev
Create Sample Template
cd backend
source .venv/bin/activate
python ../samples/create_sample_template.py
Jinja2 Syntax in .docx
Use standard Jinja2 in your Word document:
| Pattern | Purpose |
|---|---|
{{ client_name }} |
Simple text variable |
{{ description }} |
Auto-detected as textarea if name contains "description" |
{%tr for item in items %} |
Repeating table row (docxtpl syntax) |
{{ item.product }} |
Field inside table row loop |
Example Table Row
In a Word table row, write:
{%tr for item in items %}
{{ item.name }} | {{ item.qty }} | {{ item.price }}
{%tr endfor %}
The parser detects items as a table_row field and item.name, item.qty, item.price as child table_cell fields with preserved table styles.
API Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /api/auth/register |
Register user |
| POST | /api/auth/login |
Login (OAuth2 form) |
| GET | /api/auth/me |
Current user |
| GET | /api/users |
List users (admin) |
| POST | /api/users |
Create user (admin) |
| PATCH | /api/users/{id} |
Update user (admin) |
| DELETE | /api/users/{id} |
Delete user (admin) |
| GET | /api/templates |
List templates |
| POST | /api/templates |
Upload template (.docx) |
| GET | /api/templates/{id} |
Get template with variables |
| POST | /api/documents |
Create filled document |
| POST | /api/documents/preview |
Preview without saving |
| GET | /api/documents/{id}/export/docx |
Export DOCX |
| GET | /api/documents/{id}/export/pdf |
Export PDF |
PDF Export
PDF export uses LibreOffice headless if available:
# ALT Linux / Fedora
sudo apt install libreoffice # or your distro equivalent
Without LibreOffice, install weasyprint as fallback:
pip install weasyprint
Environment Variables
Create backend/.env:
SECRET_KEY=your-secret-key-here
DATABASE_URL=postgresql+psycopg2://doceditor:doceditor@localhost:5432/doceditor
ADMIN_EMAIL=admin@example.com
ADMIN_USERNAME=admin
ADMIN_PASSWORD=change-me
FRONTEND_URL=http://localhost:5173
CORS_ORIGINS=http://localhost:5173,http://localhost:3000
The admin user is created automatically on startup if it does not exist.
Workflow
- Login — use admin credentials from
.env, or register as a regular user - Upload Template — select
.docxwith Jinja2 variables - Fill Form — dynamic form generated from detected variables
- Preview — see rendered document with your data
- Save & Export — document saved; export as DOCX or PDF
- Reuse — use the same template again from Templates list
Tech Stack
- Backend: FastAPI, SQLAlchemy, docxtpl, python-docx, JWT auth
- Frontend: React 18, Vite, TypeScript, React Router
Description
Languages
TypeScript
53.7%
Python
42.7%
CSS
3.2%
Dockerfile
0.3%
HTML
0.1%