GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - docs-plus/editor

BranchesTags
Open more actions menu

Latest commit

 

History

245 Commits
245 Commits

Folders and files

NameName
Last commit message
Last commit date
.cursor/skills
.cursor/skills
 
 
.github
.github
 
 
.husky
.husky
 
 
app
app
 
 
components
components
 
 
docs
docs
 
 
extensions
extensions
 
 
hooks
hooks
 
 
lib
lib
 
 
scripts
scripts
 
 
styles
styles
 
 
tests
tests
 
 
types
types
 
 
.commitlintrc.json
.commitlintrc.json
 
 
.editorconfig
.editorconfig
 
 
.gitignore
.gitignore
 
 
.tool-versions
.tool-versions
 
 
AGENTS.md
AGENTS.md
 
 
CHANGELOG.md
CHANGELOG.md
 
 
LICENSE
LICENSE
 
 
Makefile
Makefile
 
 
README.md
README.md
 
 
biome.json
biome.json
 
 
bun.lock
bun.lock
 
 
bunfig.toml
bunfig.toml
 
 
components.json
components.json
 
 
ecosystem.config.cjs
ecosystem.config.cjs
 
 
eslint.config.mjs
eslint.config.mjs
 
 
next.config.ts
next.config.ts
 
 
package.json
package.json
 
 
playwright.config.ts
playwright.config.ts
 
 
postcss.config.mjs
postcss.config.mjs
 
 
tsconfig.json
tsconfig.json
 
 
tsconfig.sw.json
tsconfig.sw.json
 
 

Repository files navigation

TinyDocy

CI Nightly Release License: MIT Live demo

docs.plus docs.plus source @docs.plus extensions Discord

Bun Next.js React Tiptap Yjs Hocuspocus TypeScript

TinyDocy is a free, open-source (MIT) document editor where several people edit the same page at once and see each other's cursors. It is built with Tiptap 3, Yjs and Hocuspocus, needs no account, installs as an app, and keeps working offline. It is the public testbed for docs.plus: editor features land here first and move to docs.plus once they pass collaboration and scale checks.

Live demo: tiny.docs.plus. Open it in two windows and watch edits sync. It is a public sandbox: everyone sees the same documents, so don't type anything private.

Contents

  • Features
  • Quick start
  • How it works
  • Configuration
  • Deploying
  • Development
  • Documentation
  • Community

Features

Area What you get
Structured documents Title-first schema (heading block*), with each section folded, dragged to a new position or filtered by heading.
Outline Table of contents sidebar: click to jump, drag to move whole sections.
Real-time collaboration Live cursors and presence, conflict-free merging with Yjs CRDTs, and synced tabs shared by every visitor.
Rich content Lists, task lists, tables, blockquotes, code blocks with highlighting, live Mermaid diagrams and charts, and media embeds (image, video, audio, YouTube, Vimeo, Loom, SoundCloud, Spotify, X).
Installable app Web app manifest, install button, offline page, and a service worker that never touches documents or the live connection.
Offline editing Documents open from the device before the server answers. Offline edits sync on reconnect, and deleted documents never come back.
Fast with large documents Skeleton on first paint, code-split editor, and a single render on mount, so a 1,200-block document shows in about 1 s on desktop.
Hardened for a public demo Per-IP and per-document limits, size caps, origin checks, tombstones, CSP, and opt-in analytics that never sees document content.

Quick start

Requires Bun 1.4.4 or later. Node.js is not needed: Next.js, ESLint, Playwright and the git hooks run on the Bun runtime ([run] bun = true in bunfig.toml), and unit tests use bun test.

bun install

Then start both services:

make dev

Open http://localhost:3000, then open the same address in a second window to see collaboration.

make dev runs two processes:

Service Port Entry point
Next.js app 3000 app/
Hocuspocus WebSocket server (SQLite via bun:sqlite) 1234 scripts/hocus-server.ts

The service worker and offline page register only in production builds. To try them locally, build and start the app:

bun run build && bun run start

How it works

flowchart LR
  subgraph Browser
    UI[Next.js app<br/>skeleton → editor]
    SW[Service worker<br/>pages + static files]
    IDB[(IndexedDB<br/>offline copies)]
    UI <--> IDB
    UI -. offline fallback .- SW
  end
  UI <-- "one shared WebSocket<br/>(Yjs sync)" --> HP[Hocuspocus 4<br/>Bun.serve]
  UI -- "DELETE /api/documents/:id" --> API[Next.js route]
  HP <--> DB[(SQLite<br/>documents, activity,<br/>tombstones)]
  API --> DB
Loading
  • Documents are Yjs docs. Each tab is one document; the tab list itself is a shared document named global-tabs. Hocuspocus stores the encoded state in SQLite and enforces the guardrails in lib/security/.
  • One WebSocket per browser tab. lib/collab-session.ts multiplexes every document on a shared socket. It reuses sessions across remounts, keeps sessions with unsynced edits alive, and restores offline copies (lib/offline/) before the socket attaches.
  • The page renders before the editor loads. The server sends an app-shell skeleton with real intro text (good for SEO and slow connections). The editor bundle loads separately while the tab list syncs.
  • Editor extensions are layered. Heading fold, drag, filter and scale live in extensions/ and work in any Tiptap 3 app. Links, inline code, indent, placeholders, Mermaid and media come from the @docs.plus/extension-* packages.

Where things live

app/                 Routes: editor, /about, /privacy, /offline, metadata, API
components/
  app-skeleton/      Server-rendered loading shell
  document-editor/   The integrated editor
  editor-app/        Client shell: tabs, lazy editor, offline states
  pwa/               Service worker registration, install button, offline UI
  tab-bar/  toc-sidebar/  tiptap-ui/  tiptap-node/  ui/ (shadcn/ui)
extensions/          Standalone Tiptap extensions (heading-*, render-once,
                     table-of-contents, title-document)
hooks/               React hooks (synced tabs, Yjs document, connection state)
lib/
  collab-session.ts  Shared sessions on one socket
  offline/           Offline document copies (IndexedDB)
  pwa/               Service worker and its routing rules
  security/          Guardrails, CSP, tombstones, rate limits
scripts/             Hocuspocus server, retention purge
tests/               Unit, e2e, PWA, perf, soak, load (see tests/TESTING.md)
docs/                Runbooks, plans, brainstorms

Configuration

Everything is configured through environment variables, and most of them have safe defaults. There are two kinds.

Build-time settings (NEXT_PUBLIC_*, SEO_NOINDEX)

These are inlined by bun run build. Put them in .env.production before building; setting them at runtime has no effect.

Variable Default Purpose
NEXT_PUBLIC_HOCUS_URL ws://127.0.0.1:1234 Collaboration server URL. Production needs wss://.
NEXT_PUBLIC_SITE_URL https://tiny.docs.plus Canonical origin for metadata, sitemap and JSON-LD. Site copy lives in lib/site-config.ts.
SEO_NOINDEX unset 1 for previews and staging: noindex, Disallow: /, empty sitemap.
NEXT_PUBLIC_GA_MEASUREMENT_ID unset Opt-in Google Analytics 4 (G-…). Visitors must click Allow; GPC and DNT are honoured. See the analytics runbook.
NEXT_PUBLIC_PRIVACY_CONTROLLER, NEXT_PUBLIC_PRIVACY_EMAIL unset Data controller and contact on /privacy. Set both before enabling analytics.
NEXT_PUBLIC_SERVICE_WORKER on 0 unregisters the worker and deletes its caches. See the service worker runbook.
NEXT_PUBLIC_OFFLINE_CACHE on 0 turns off offline document copies and deletes stored ones.
NEXT_PUBLIC_MAX_EMBED_IMAGE_BYTES 262144 Images are downscaled in the browser to this size before embedding.
NEXT_PUBLIC_MAX_TABS_PER_CLIENT 50 Tab cap in the UI.
NEXT_PUBLIC_DISCORD_INVITE_URL, NEXT_PUBLIC_GITHUB_REPO_URL project links Community links in the status strip.

Runtime settings (server processes)

These are read when the Next.js app, Hocuspocus or the retention script starts. The full list, with defaults, is in lib/security/guardrail-config.ts; operational guidance is in the abuse guardrails runbook.

Variable Default Purpose
DB_PATH ./db.sqlite SQLite file. The Next.js app and Hocuspocus must use the same one.
HOCUS_PORT, HOCUS_HOST 1234, 0.0.0.0 Where Hocuspocus listens.
TRUSTED_PROXY off 1 only when every request comes through one reverse proxy that appends X-Forwarded-For.
HOCUS_ALLOWED_ORIGINS any Comma-separated browser origins allowed to open sockets.
MAX_DOC_SIZE_BYTES 1 MiB Per-document cap; production sets 2 MiB. Playground and tab-list caps are separate.
WS_CONNECTION_LIMIT, WS_SOCKETS_PER_IP, MAX_WS_SOCKETS 10, 30, 5000 Connection limits.
DOC_CREATION_RATE_LIMIT, MAX_TOTAL_DOCUMENTS 10/h, 2000 Document creation limits.
RETENTION_DAYS, TOMBSTONE_RETENTION_DAYS 30, 90 Idle documents are deleted and tombstoned; tombstones outlive offline copies.
HOCUS_LOGGER, HOCUS_THROTTLE, HOCUS_REDIS on, on, off Optional Hocuspocus extensions.
HOCUS_ALLOW_ISOLATED_TABS_DOCS off 1 in dev and tests only. The server refuses to start with it in production.

Deploying

Production runs as three PM2 processes defined in ecosystem.config.cjs: Next.js on 3847, Hocuspocus on 3848, and an optional Redis on 6380. They sit behind a TLS-terminating reverse proxy.

To deploy or update:

git pull && bun install --frozen-lockfile && bun run build && bunx [email protected] restart ecosystem.config.cjs --update-env

Requirements:

  • TLS and the proxy. The collaboration URL must be wss://. Only the proxy may reach the app ports, because TRUSTED_PROXY=1 trusts its forwarding headers.
  • Service worker headers. The proxy must not change Cache-Control on /_next/static/service-worker/sw.js; it must stay public, max-age=0, must-revalidate.
  • Retention. Run bun scripts/purge-retention.ts daily (cron or a systemd timer) and rotate the PM2 logs; abuse events contain IP addresses.
  • Taking content down. Delete the document; never reset its stored state, because offline copies would push it back.

Release notes for each change, including deploy steps, are in the changelog.

Development

Command What it does
make dev Next.js and Hocuspocus together.
bun run build / bun run start Production build and server.
bun run test Unit tests with bun test (the stress probe runs with test:stress).
bun run test:e2e Playwright against make dev (set CI= to reuse running servers).
bun run test:pwa Service worker and offline tests against a production build (PWA_BASE_URL).
bun run test:perf, test:soak, test:load Typing latency, long-running soak and the Yjs load harness.
bun run typecheck TypeScript for the app (including the Hocuspocus server) and the service worker.
bun run lint / bun run check ESLint (Next.js rules) and Biome.

Test layers, environments and CI notes: tests/TESTING.md.

Conventions:

  • Bun only (bun, bunx; never npm or npx).
  • Conventional Commits, enforced by commitlint.
  • Named exports; kebab-case files; PascalCase components with title-case acronyms.
  • shadcn/ui for new UI.
  • Every pull request adds an entry to CHANGELOG.md.

The full conventions are in AGENTS.md.

Stack: Bun · Next.js 16 (App Router, Turbopack) · React 19 · Tiptap 3 and ProseMirror · Yjs and Hocuspocus 4 · SQLite · Tailwind CSS 4 and Sass · TypeScript (strict) · Biome, ESLint, Husky and commitlint · bun test and Playwright.

CI (.github/workflows/ci.yml) runs on every pull request and push to main. One job runs bun audit, Biome, ESLint, the typecheck, unit tests and the production build; the other runs the Playwright Chromium suite. A nightly workflow (.github/workflows/nightly.yml) runs the service worker, soak and load layers twice a day (03:41 and 08:00 UTC).

Releases: tag main with vX.Y.Z and push the tag; .github/workflows/release.yml publishes the GitHub release, listing the pull requests merged since the previous tag and linking to CHANGELOG.md.

The @docs.plus/extension-* packages are refreshed daily (04:17 UTC) by .github/workflows/docs-plus-extensions.yml. It opens a pull request after a read-only verification job, which needs "Allow GitHub Actions to create and approve pull requests" in the repository's Actions settings.

Documentation

Document For
CHANGELOG.md What changed in each release, with deploy steps.
Abuse guardrails runbook Limits, abuse events, alerts, scheduled jobs, content takedown.
Service worker runbook Caching rules, kill switch, deployment checks.
Analytics runbook GA4 setup, privacy settings, event list.
tests/TESTING.md Test layers and how to run them.
AGENTS.md Repository conventions and project facts.
docs/plans, docs/brainstorms Design history of the editor features.

Community

TinyDocy is the validation testbed for docs.plus: features are proven here before they land in the production editor.

  • docs.plus: the live platform
  • docs-plus/docs.plus: the production repository
  • Discord: the community

License

MIT. See LICENSE.

About

tiny.docs.plus

Resources

Readme
MIT license
Activity
Custom properties

Stars

2 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Packages

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.