Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

113 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Patra — Git-backed publishing and sharing for documents, drafts, and static sites

Patra

Self-hostable, Git-backed publishing and sharing of documents, static sites, and HTML drafts as shareable links — with an agent-friendly CLI for non-interactive publishing.

Patra (ಪತ್ರ / पत्र) is Sanskrit/Kannada for "page," "leaf," or "letter" — a fitting name for a place to keep and share your documents. The logo is a leaf whose veins read as lines of text.

Illustration of Patra publishing, sharing, versioning, and securing documents

What It Is

Patra hosts, versions, previews, and shares self-contained HTML artifacts and multi-file static sites with real access control. It is built for two audiences:

  • Teams that want a simpler, HTML-specialized "Drive" with a Git backbone, link sharing, team access, and an audit trail.
  • AI coding agents (Claude Code, Codex, etc.) that generate reports, dashboards, mockups, and plans and need to push a file and get back a clean, shareable URL — non-interactively, with token auth and deterministic output.

It is a Bun/Turbo monorepo: a Hono API server, a React/Vite web app, a patra CLI, and a shared types package.

Illustration of an agent publishing an HTML draft through Git-backed storage into a secure preview link

Features

  • Draft HTML hosting — publish a single standalone .html file to a private, authenticated viewer URL, served through short-lived signed content URLs on a separate content origin.
  • Git-backed repos + multi-file sites — every user and team owns one bare Git repo; upload folders or push over Git smart-HTTP. Linked pages, CSS, and assets resolve by relative path without rewriting.
  • Flexible sharing — public links, email shares, and team shares, with optional password protection, expiry, and organization/email-domain gating (public vs org link access).
  • Analytics + audit log — per-share and per-draft view metrics (total views, unique visitors, last viewed, referrers) plus an actor activity audit log.
  • Versioning — repos are Git-backed; restore any file (or the whole tree) from history as a new commit, and duplicate files or drafts.
  • Scoped API tokens — least-privilege tokens (repo:*, share:*, team:*, draft:*, git:*, site-data:*, webhook:*, audit:read, user:*, or *) enforced on every authenticated endpoint.
  • GitHub sync — one-way import via a GitHub App (selected-repository access) or a personal access token fallback; pick a whole repo, folder, or single file before syncing.
  • Teams — full team CRUD with owner / admin / member / viewer roles and email invitations.
  • Form / site-data collection — opt-in, per-collection form ingestion from hosted pages, public and rate-limited, storing only hashed visitor identifiers.
  • Outbound webhooks — user-configurable, HMAC-signed event deliveries (share.created, share.revoked, github_sync.completed) with SSRF guards (private/loopback hosts rejected).
  • First-run setup + admin — a setup wizard and a sysadmin-only setup checklist; sysadmins are derived from SYSADMIN_EMAILS.
  • Docs — a hosted product/agent/API reference, an OpenAPI 3.1 spec at GET /openapi.json, and a machine-readable GET /llms.txt.
  • Rate limiting — in-memory fixed-window limiter on public and auth endpoints, tunable via env.
  • Docker self-hosting — single app container, SQLite + Git repos on a volume.

Illustration of secure document sharing and access controls

Quick Start (Local Dev)

bun install
cp .env.example .env
bun run dev

The web app runs on http://localhost:5173 and proxies API traffic to the server on http://localhost:3000.

For local dev login, set ENABLE_DEV_LOGIN=true in .env, then sign in with any email and password dev.

Self-Hosting (Docker)

cp .env.production.example .env.production
# Edit .env.production: public URLs, OAuth credentials, and 32+ char secrets.
docker compose up --build

The compose setup runs one app container on port 3000 and stores SQLite, bare Git repositories, and extracted worktrees in the persistent data volume.

Minimum production settings:

  • NODE_ENV=production
  • APP_URL=https://your-domain
  • API_URL=https://your-domain
  • CONTENT_ORIGIN=https://content.your-domain (a separate host for sandboxed draft HTML)
  • DEPLOYMENT_NAME="Your Company Docs" for visible deployment branding (defaults to Patra)
  • SYSADMIN_EMAILS=admin@your-domain for setup/admin access
  • GOOGLE_REDIRECT_URI=https://your-domain/api/auth/google/callback
  • SESSION_SECRET, DRAFT_CONTENT_SECRET, HOOK_SECRET, and GITHUB_TOKEN_SECRET — each a unique 32+ character random value
  • ENABLE_DEV_LOGIN=false

If you terminate TLS at a reverse proxy, forward traffic to the container on port 3000. For full details and platform-specific notes, see docs/self-hosting.md and docs/deployment.md.

CLI

The command-line client is published as the patra binary. Authenticate with an API token created in Settings → API Tokens (tokens are prefixed pat_ and shown once):

patra login --token pat_...
patra draft ./plan.html          # publish one HTML file, print its URL
patra push ./site --to personal --message "Publish site"
patra teams

Drafts published with patra draft appear in the authenticated web app under Drafts, where owners can open, copy, search, and delete their private draft URLs.

Project Layout

Bun workspaces + Turborepo monorepo:

  • packages/server — Hono API, SQLite/Drizzle storage, Git smart-HTTP, file extraction, share/draft/webhook routes, OpenAPI + llms.txt.
  • packages/web — React/Vite/Tailwind web app.
  • packages/cli — the patra command-line client.
  • packages/shared — shared TypeScript types and Zod validation schemas.

Documentation

Documentation on GitHub Pages

GitHub Pages serves the web app's public UI — the marketing home page and the styled /docs guides, exactly as they render in the app — as a static site. The authenticated app (login, setup, dashboard, sharing) is stripped out for the static build, since there is no server on Pages.

The .github/workflows/docs-pages.yml workflow builds and deploys the site with GitHub Actions: it builds packages/web with VITE_PUBLIC_SITE=true (public routes only) and PAGES_BASE=/<repo>/ (so assets and routes resolve under the repo subpath), writes a 404.html SPA fallback for deep links, and publishes the dist/ output.

To enable it:

  1. In the repo, go to Settings → Pages.
  2. Under Build and deployment, set Source to "GitHub Actions".

The site publishes at https://<user>.github.io/<repo>/. The base path is derived from the repo name at build time, so it keeps working whether the repository stays named docs-share or is later renamed. Pushes to main that touch packages/web/**, packages/shared/**, docs/**, or the workflow file redeploy automatically; you can also trigger a manual run from the Actions tab.

The /docs content is the same Markdown in docs/, imported at build time and rendered by the app's docs pages — editing those files updates both the running app and the published site.

Security

Patra ships with authentication (Google OAuth sessions + scoped pat_ API tokens), sandboxed content serving (untrusted draft HTML runs from a separate CONTENT_ORIGIN behind short-lived signed URLs and a sandbox CSP), SSRF-guarded outbound webhooks, and rate limiting. Operators should set strong, unique 32+ character secrets and terminate TLS (HTTPS) in front of the app. See SECURITY.md.

Contributing

See CONTRIBUTING.md.

License

Apache-2.0. See LICENSE.

About

Patra: self-hostable, Git-backed publishing and sharing for documents, static sites, and agent-generated HTML drafts.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages