Welcome to the [TiddlyWiki Community Plugin Library]!
This plugin source is maintained by the TiddlyWiki Chinese Community and is dedicated to collecting all TiddlyWiki5 related plugins on the web, hoping to provide a one-click installation and update plugin experience for TiddlyWiki users all around the world.
If you don't know how to use TiddlyWiki and this source, you are welcome to read the plugins related section in the TiddlyWiki Tutorials for Chinese Communities. As mentioned above, both the plugin source and the tutorial are open source projects, you can find them in GitHub and participate in contributing! If you like, you can join us through QQ groups and other means, see the Chinese tutorials mentioned above for details.
To add this plugin library to your Wiki, simply drag the link in cpl website to your Wiki with your mouse:
On this site, you can browse through various interesting plugins and install them in your own TW once you find the one you like. There is a comment section under each plugin info tiddler on this site where you can leave your thoughts. ↓
- Pull this repo
- Make sure to install NodeJS and run
npm i - In this repo folder, run:
npm run helpfor further guidance
This project uses Modern.TiddlyDev with the following structure:
src/CPLServer/— Server-side plugin (API routes, data store, rate limiting)src/CPLPlugin/— Client-side plugin (browser API client, UI components)wiki/— TiddlyWiki content and configurationwiki/files/plugin-offline/— Offline plugin files (for plugins not available online)wiki/files/plugin-fetched/— Fetched plugin files (populated by scheduled scripts in production)data/— Runtime data directory (downloads, ratings, created automatically)
Start the development server with hot reload:
pnpm devThe server will start on http://127.0.0.1:15745 by default. The tiddlywiki-plugin-dev CLI automatically loads plugins from src/, so you don't need to manually declare them in wiki/tiddlywiki.info.
For LAN access (useful for mobile testing):
pnpm dev:lanWe have three levels of automated tests:
Unit tests — Data store, rate limiter, and utility functions:
pnpm test:unitAPI tests — Server route handlers (runs a test server on port 9876):
pnpm test:apiE2E tests — Playwright browser automation across Chromium, Firefox, and WebKit:
pnpm test:e2eTo run E2E tests with the interactive UI:
pnpm test:e2e:uiAll tests:
pnpm test # Unit tests only (Jest)
# To run everything:
pnpm test:unit && pnpm test:api && pnpm test:e2eBuild the deployable static site artifacts from the Modern.TiddlyDev wiki and plugin library:
pnpm build
pnpm run build:static-site
pnpm run build:static-librarypnpm build prepares the plugin packages.
pnpm run build:static-site builds the browser-facing static website.
pnpm run build:static-library builds the static plugin library JSON artifacts used by the published mirror.
Place plugin .json files into wiki/files/plugin-offline/ to make them available for download via the server. The download route (GET /cpl/api/download-plugin/:title) checks wiki/files/plugin-fetched/ first, then falls back to wiki/files/plugin-offline/.
For a writable local runtime server that exercises the CPL boot path exactly like the Node.js deployment:
pnpm server:testStart the production server in read-only mode:
pnpm server:prodThe server launcher compiles the TypeScript plugin sources into runtime plugin JSON files under cache/runtime-plugins/, and then starts a standard TiddlyWiki Node.js server with those compiled plugins injected as boot-time plugin arguments. This keeps the runtime compatible with TiddlyWiki's Node.js boot process while preserving TypeScript source under src/.
This is intentionally different from pnpm dev:wiki: pnpm dev:wiki runs the Modern.TiddlyDev development server with wiki writes enabled, while pnpm server:test verifies the production-like runtime plugin loading path used by the CPL server.
For public deployments, configure read-only mode so wiki writes stay disabled while download statistics and API routes remain available.
If the server is deployed behind a reverse proxy or CDN, make sure the real client IP is preserved correctly. Download throttling, vote limits, and similar protections depend on the client address seen by the CPL server.
CPL Server requires environment variables for authentication and admin configuration. Copy .env.example to .env and fill in your values:
cp .env.example .envRequired variables:
| Variable | Description |
|---|---|
CPL_JWT_SECRET |
Random string for JWT signing. Generate with node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" |
CPL_GITHUB_CLIENT_ID |
GitHub OAuth App Client ID |
CPL_GITHUB_CLIENT_SECRET |
GitHub OAuth App Client Secret |
CPL_ADMIN_GITHUB_IDS |
Comma-separated list of GitHub user IDs who can moderate comments |
CPL_SERVER_ID |
(Optional) Unique server identifier for multi-server deployments (e.g., "china", "us", "eu"). Leave empty for single-server setups. |
Never commit .env to git — it is already in .gitignore.
Creating a GitHub OAuth App:
- Go to https://github.com/settings/applications/new
- Set Authorization callback URL to
http://your-domain/cpl/api/auth/github/callback - Copy the Client ID and Client Secret to your
.env
CPL now includes a self-hosted comment system with GitHub OAuth authentication and moderation:
- Users authenticate via GitHub OAuth
- Comments support wikitext formatting (dangerous syntax is filtered server-side)
- New comments are held for moderation (
pendingstatus) - Admins (configured in
CPL_ADMIN_GITHUB_IDS) can approve, reject, or delete comments - Comment data is stored in
data/comments/as JSON files, suitable for git backup - Rate limiting: 10 comments per hour per user (configurable via
CPL_COMMENT_RATE_LIMIT)
The browser-side CPL client exposes the server API as $tw.cpl, with $tw.cplServerAPI retained as a legacy alias.
CPL supports deploying multiple mirror servers (e.g., China, US, Europe) that all sync data via git without conflicts.
How it works:
- Each server writes to its own files:
stats.{serverId}.json,ratings.{serverId}.json,comments/{plugin}.{serverId}.json - When reading data, the server aggregates across all files:
- Stats: download counts are summed
- Ratings: ratings are merged and averages recalculated
- Comments: comments are merged and deduplicated by ID
- All servers can push/pull from the same git repository without merge conflicts
Setup:
-
Set
CPL_SERVER_IDin each mirror's.envfile:# China mirror CPL_SERVER_ID=china # US mirror CPL_SERVER_ID=us # Europe mirror CPL_SERVER_ID=eu
-
Each server will automatically use server-specific files
-
Periodically run the reconciliation script to detect issues:
pnpm run reconcile-data # Dry run (report only) pnpm run reconcile-data -- --fix # Apply fixes pnpm run reconcile-data -- --clean-stale # Remove stale mirror files (30+ days old)
Git workflow:
# On each mirror, periodically:
git pull origin main # Get data from other mirrors
pnpm run reconcile-data # Check for issues
git add data/
git commit -m "Update stats from {serverId} mirror"
git push origin mainComment IDs: Each comment gets a unique ID in the format {serverId}-{timestamp}-{random} to prevent collisions across mirrors.
Stale mirrors: If a mirror goes offline permanently, run pnpm run reconcile-data -- --clean-stale to remove its files after 30 days of inactivity.
To keep wiki/files/plugin-fetched/ up to date with the latest plugin versions, schedule pnpm run fetch-plugins to run periodically.
Windows — Use Windows Task Scheduler:
- Create a new task that runs
pnpm run fetch-plugins - Set the working directory to the repo root
- Schedule it to run daily or at your preferred interval
Linux/macOS — Use cron:
# Fetch plugins daily at 3 AM
0 3 * * * cd /path/to/TiddlyWiki-CPL && pnpm run fetch-pluginsThe script fetches the latest plugin JSON files and saves them to wiki/files/plugin-fetched/. Run pnpm run fetch-plugins:dry-run -- --allow-ci --best-effort to preview what would be fetched without writing files.

