Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

682 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

WordJS โ€” the CMS where a plugin can't take over your site

npm CI License: MIT Node Security Policy Ask DeepWiki

Build a website with drag-and-drop. Add plugins without trusting them.

Try it in one command:

npx create-wordjs@latest my-site

No PHP, no MySQL, no build step โ€” it downloads a ready-to-run bundle, starts a single process, and prints a one-time setup-wizard URL for you to open in your browser.


๐Ÿง What is WordJS?

WordJS is free, open-source software for building and running a website โ€” a blog, a shop, a company site, a portfolio. If you've heard of WordPress, think "WordPress, rebuilt for today": you get a visual, drag-and-drop page builder, ready-made themes and plugins, and search-engine-friendly pages out of the box.

The difference is what happens when you install a plugin.

On most website software, every add-on you install gets the keys to everything โ€” your database, your passwords, your files. One bad or hacked plugin can quietly wreck the whole site. It's the single most common way websites get breached.

WordJS is built so that can't happen.

๐Ÿ” The big idea, in plain English

Think about apps on your phone. A flashlight app can't read your bank messages unless you let it โ€” each app is boxed off and has to ask permission for anything sensitive.

WordJS does that for website plugins. Every plugin runs in its own locked box (a separate, operating-system-enforced process) and starts with nothing โ€” no access to your files, your database, your visitors' data, or the internet. It only gets a capability when you, the admin, grant it โ€” and you see exactly what each plugin is asking for.

So a plugin that turns out to be buggy, greedy, or outright malicious stays in its box. It can't read your passwords, steal your config, or take the site down. That safety is enforced by the operating system itself โ€” not by trusting the plugin to behave.

Every other major CMS runs plugins with full trust. This is the one thing they can't copy without breaking their entire ecosystem โ€” and it's what WordJS is built around.

A plugin runs in its own OS process; every capability crosses a default-deny bridge the administrator granted, and anything ungranted is refused at the host

WordJS visual editor โ€” dragging blocks onto the canvas to build a page

Building a page by dragging blocks and editing text right on the canvas โ€” the visual editor ships in the core, not as a paid add-on.


โš–๏ธ How it compares

WordJS WordPress Ghost Strapi Payload
Plugins can't compromise the site โœ… OS-enforced sandbox โŒ full trust โ€” no plugin runtime โŒ in-process โŒ in-process
You approve what each plugin can do โœ… per-plugin, default-deny โŒ โ€” โŒ โŒ
Drag-and-drop page builder in core โœ… built in partial (paid builders) โŒ โŒ headless โŒ headless
SEO-ready out of the box โœ… SSR + metadata + sitemap โœ… via plugins โœ… โŒ your job โŒ your job
Import your WordPress site โœ… built-in importer โ€” โœ… โŒ โŒ
What it takes to run 1 process, SQLite PHP + MySQL Node + MySQL Node + DB + frontend Node + DB
License MIT GPLv2 MIT MIT (paid tier) MIT (paid cloud)
Ecosystem maturity โš ๏ธ young, first-party only 60k+ plugins large large growing

The honest row is the last one: WordJS is young, and every plugin and theme in its marketplace today is first-party โ€” there's no third-party author community yet. What it already has is the row at the top.


โœจ What's inside

๐ŸŽจ Build

  • Drag-and-drop visual editor (Puck) with 30 blocks & edit-in-place text
  • Token-driven themes + a live customizer
  • 64 themes & 31 plugins, one-click install
  • Real SEO: server-rendered pages, sitemap, RSS, social cards
  • Media library with automatic AVIF/WebP optimization

๐Ÿงฉ Extend โ€” safely

  • Every plugin in its own OS process
  • Ask-permission capabilities, default-deny
  • Install-time code scanner + one-click sha256-verified marketplace
  • WordPress-style hooks, filters & shortcodes
  • Import from WordPress (posts, pages, comments, dates)

โš™๏ธ Run

  • One process to deploy, SQLite by default
  • Or split / multi-machine over secure mTLS
  • SQLite ยท PostgreSQL ยท MySQL/MariaDB
  • Automatic HTTPS (Let's Encrypt)
  • 2FA, API tokens, webhooks, metrics
See the full feature list

Plugin system & security (the core differentiator)

  • OS-process plugin sandbox. Every plugin runs in a separate operating-system process (child_process.fork) โ€” its own memory and event loop โ€” so a crash, memory blow-up, or exploit is contained by the kernel and never takes down the host. Plugins reach the core only through a permission-checked wordjs bridge (structured-clone RPC, no live host references, an exact method allow-list).
  • Install-time code scanner. Before a plugin can activate, its JavaScript is parsed and walked for dangerous constructs (eval, exec/spawn, dynamic require, sensitive modules, forbidden process access). It's fail-closed (an unparseable file is rejected) and runs on every plugin โ€” no exemptions.
  • Ask-permission model (default-deny). A plugin's manifest requests scoped capabilities (database, filesystem, settings, users:read, email:provider, notifications:provider, network, โ€ฆ); an admin grants each one per plugin. A call works only if the capability is BOTH declared AND granted. Activation shows the admin exactly what the plugin requests and grants that declared set โ€” only when the plugin has no grant record yet, so a later per-permission revoke survives a re-activation. First-party plugins get no extra privilege โ€” same sandbox, same rules.
  • Kernel hardening on Linux (default-on). Each plugin child also runs as an unprivileged user with dropped capabilities, no-new-privs, PID/IPC/UTS namespaces, a read-only filesystem, and a seccomp syscall denylist. A plugin without the network grant is dropped into an empty network namespace, so it can't reach the internet or your internal services even at the kernel level. (Probe-gated, with a clean fallback where unavailable; Windows gets a Job Object memory cap; macOS relies on process isolation.)
  • Per-plugin data isolation. Each plugin gets only its own wjp_<slug>_ database tables and a secret-scrubbed view of config โ€” core users/options/sessions and secrets are unreachable. On PostgreSQL/MySQL the database itself enforces this via a per-plugin low-privilege role/user.
  • Plugin & theme marketplace. A curated catalog of 31 first-party plugins and 64 first-party themes with one-click, sha256-verified installs through the same hardened, sandboxed pipeline as manual uploads. Sources are admin-configurable (point it at any HTTPS catalog); all catalog items are first-party today, with third-party submissions on the roadmap.

Authoring & content

  • Visual builder (Puck) โ€” drag-and-drop editing, in-place rich text (bold/italic/links, a color picker with eyedropper, font family from your installed fonts, size, alignment), a searchable block inserter with reusable section patterns, and a device preview (desktop/tablet/mobile) that renders the canvas at true device width.
  • Real server-side rendering โ€” public pages are React Server Components, so crawlers and first paint get the real content, per-page metadata (generateMetadata), OpenGraph/Twitter cards, JSON-LD, real 404s, and a no-JS search form.
  • SEO basics โ€” semantic HTML, sitemap.xml, robots.txt, and an RSS feed.
  • Themes โ€” a shared, token-driven CSS framework (--wjs-* design tokens) that auto-styles pages, plus a live customizer at /admin/themes/customize. A theme's optional server-side functions.js runs in the same sandbox as plugins.
  • Hooks, filters & shortcodes (WordPress-style), dynamic roles & permissions (database-driven), and UI in espaรฑol / english / portuguรชs.
  • WordPress (WXR) importer โ€” upload a .xml export to bring over authors, categories/tags, posts/pages (with meta, term relationships, and threaded comments), preserving publish dates. Idempotent and re-runnable.
  • Backups โ€” full-site export/restore with retention pruning, plus privacy-first analytics (no cookies, daily-rotated salted IP hashing) and a built-in cron.

Operations

  • Gateway โ€” a clustered reverse proxy (one worker per CPU, auto-respawn), health-check eviction, an mTLS internal control channel, and SSE-aware proxying. It also acts as the cluster CA for multi-machine deployments.
  • Automatic TLS โ€” Let's Encrypt via HTTP-01 or DNS-01, manual upload, or a self-signed dev fallback; renewal works in single-process mode too.
  • Databases โ€” SQLite (default), PostgreSQL, or MySQL 8+/MariaDB, all behind one interface with a migration system to move between them.
  • Headless-friendly โ€” scoped API tokens (Authorization: Bearer wjt_โ€ฆ, per-resource scopes), HMAC-signed SSRF-safe webhooks, and token-gated Prometheus metrics.
  • Native mail server โ€” an optional, fully sandboxed first-party plugin: inbound SMTP, direct-MX delivery, and DKIM signing.

๐Ÿš€ Deploy your way

The same codebase runs three ways โ€” switch anytime, no data migration:

Mode What it is Best for
๐Ÿงฑ Monolith Everything in one process, one port The simplest deploy โ€” a small VM or container
๐Ÿ”€ Split (default) Gateway + backend + frontend on one host Scaling services independently
๐ŸŒ Separate The three services on different machines, joined over mTLS Larger, distributed setups
# The whole thing, one process:
npx create-wordjs@latest my-site          # then open the printed wizard URL

# Or, from a source checkout:
npm run install:all
npm run dev:mono      # monolith on https://localhost:3000 (self-signed)
npm run dev           # or the 3-service split
Architecture & run-mode details
graph TD
    User((User)) --> Gateway[Gateway :3000]
    Gateway --> Frontend[Next.js Frontend :3001]
    Gateway --> Backend[TypeScript Backend :4000]
    Backend --> DB[(SQLite / PostgreSQL / MySQL)]
    Backend --> Plugins{Isolated Plugins}
Loading
  • Gateway โ€” clustered Node/Express reverse proxy: routing, load-balancing, health-check eviction, mTLS internal channel, SSE-aware proxying, and the cluster CA.
  • Backend โ€” the core engine (content, users, roles, the plugin/theme system, mail, certificates, and the sandbox). TypeScript, compiled to JS for production.
  • Frontend โ€” the public site and the Next.js admin, including the Puck visual builder.

Monolith runs the backend (with its isolated plugins) and the Next.js frontend in one process on :3000 โ€” no gateway proxy, no cluster โ€” while still handling TLS, security headers, compression, and SEO rewrites locally. Split runs them as three cooperating processes behind the gateway. Separate spreads those three across machines: create-wordjs gateway --host <ip> makes the first box the cluster CA and prints ready-to-paste join commands with single-use, role-bound tokens; each other box enrolls over mutual TLS with no cert hand-copying.

See the Separate-mode guide for the walkthrough.


๐Ÿ“š Documentation

๐Ÿ—๏ธ Architecture ๐Ÿ› ๏ธ Development & Build โŒจ๏ธ CLI & Setup
๐Ÿ”Œ Plugin Tutorial ๐Ÿงฉ Plugins Reference ๐Ÿงฑ Plugin Isolation
๐ŸŽจ Themes ๐Ÿ–ฅ๏ธ Frontend ๐Ÿ›ฐ๏ธ Gateway
๐Ÿ—„๏ธ Database ๐Ÿ—ƒ๏ธ Plugin Database Access โœ‰๏ธ Mail Server
๐Ÿš€ Deployment ๐Ÿงฉ Separate Mode ๐ŸŒ Multi-Node Ops
๐Ÿ“ฅ Import from WordPress ๐Ÿ”” Notifications ๐Ÿ“ก REST API
๐Ÿ” Security Policy ๐Ÿ›ก๏ธ Security Architecture ๐Ÿงญ Product Positioning

Live API reference (Swagger/OpenAPI) is served at http://localhost:4000/api/v1/docs (admin only).


๐Ÿงญ Project status

Beta ยท pre-production ยท primarily solo-maintained.

WordJS recently completed rounds of security hardening (fixing a CSRF bypass, committed secrets, and XSS sinks, among others). The plugin sandbox has had multiple internal red-team passes โ€” but there is no independent third-party audit yet. An external audit is strongly recommended before any production or internet-facing deployment, and the residual risks are documented plainly in SECURITY.md and POSITIONING.md.

The whole ecosystem is first-party: the marketplace ships 31 plugins and 64 themes, but there's no third-party author community or public review pipeline yet. Use it to build, learn, and experiment โ€” do your own review before trusting it with real data or real users.


๐Ÿ”’ Security

The plugin sandbox is designed to fail closed, with defense-in-depth layers (see What's inside and Security Architecture). Beyond plugins, WordJS ships TOTP two-factor auth with an admin-enforced MFA-by-role policy, JWT revocation, per-(IP + account) login throttling, constant-time secret comparison, origin-pinned CSRF protection, and SSRF-safe outgoing webhooks.

Before exposing WordJS to the internet: have it independently audited, rotate every secret, and set a strong gatewaySecret (the gateway refuses management endpoints while the default is in place). Found a vulnerability? Please follow the disclosure process in SECURITY.md.

Tech stack
  • Runtime: Node.js (โ‰ฅ 20.9; Node 20/22 LTS recommended)
  • Backend: TypeScript โ€” compiled with tsc for production, ts-node for dev
  • Frontend: Next.js (React 19)
  • Editor: Puck ยท Styling: vanilla CSS + Tailwind
  • Communication: REST + JWT + scoped API tokens + WebSockets/SSE
  • Gateway: Express + Node cluster, http-proxy, mTLS internal channel
  • Sandbox: child_process OS-process isolation + acorn code scanning + runtime require proxies + layered memory caps (cgroup / Windows Job Object / RSS-poll)
  • TLS: acme-client (Let's Encrypt HTTP-01 / DNS-01)
  • Database: SQLite (better-sqlite3 / sql.js), PostgreSQL (pg), or MySQL/MariaDB (mysql2)
  • Tooling: ESLint + Prettier, node:test, GitHub Actions CI
Run from source & backend scripts
npm run install:all       # install root + sub-packages
npm run dev               # split: gateway + backend + frontend
npm run dev:mono          # or everything in one process, one port

Public site on port 3000, admin at /admin โ€” dev:mono self-signs a localhost certificate (https://localhost:3000; WORDJS_HTTP=1 for plain HTTP), and the split gateway switches to HTTPS once setup writes ssl.enabled. First-run setup (database + admin user) runs in the browser wizard, or via npm run setup.

In production the backend is compiled (tsc โ†’ dist/) and run as plain JS. From backend/:

Script Purpose
npm run build Compile to dist/ (strict config)
npm run typecheck Strict type-check (tsc --noEmit), enforced in CI
npm test Test suite (node --test)
npm run lint / format ESLint / Prettier

CI (.github/workflows/ci.yml, Node 22) runs the strict type-check, the compiled build, a dependency license gate, unit tests, integration tests against real postgres:16 + redis:7 containers, and the frontend lint/type-check/tests/build.


๐Ÿ”ฎ Roadmap

  • ๐Ÿงฉ Third-party marketplace โ€” open the catalog to community authors, where "sandboxed & reviewed" is a verifiable trust badge.
  • โ˜๏ธ Media CDN โ€” S3-compatible object storage.
  • ๐ŸŒ Multi-site โ€” manage multiple domains from one install.
  • ๐Ÿ›ก๏ธ More kernel hardening โ€” building on the default-on Linux sandbox layer.

๐Ÿ“œ License

MIT โ€” see LICENSE. Third-party dependency notices are in THIRD-PARTY-NOTICES.md.


Built with care by a small, independent project. Contributions, bug reports, and security disclosures are welcome.

Donate

About

The CMS where a plugin can't take over your site: OS-sandboxed plugins, per-capability grants. SSR, no PHP.

Topics

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages