webcpp brings to C++ the libraries that other languages use for the web. Each is a header-only C++20 library, a port of a widely used original at an exact version or a library of webcpp’s own, built and tested with b2, natively and for WebAssembly, and documented on a page of its own, with its API reference. webcpp follows Boost’s guidelines and model; its source is at webcpporg/webcpp.
Libraries
Each library’s name leads to its page: the guide that teaches it, its guarantees, its API reference and how it is tested.
| Library | Description | Ports |
|---|---|---|
Boost.Asio for native, browser and WASIp2/P3 targets, with explicit platform capabilities and shipped Wasm implementations. |
original |
|
Beast-compatible HTTP and WebSocket interfaces for WebAssembly and native applications. |
original |
|
Boost.Cobalt coroutine applications on native, browser and WASI targets. |
original |
|
webcpp’s configuration, which every webcpp library includes first: the target a program is built for, whether webcpp has exceptions, and webcpp’s version. |
original |
|
A JSON document for C++20 that behaves as JavaScript does, in one relocatable image. |
original |
|
IDNA2008 and UTS 46 for C++20: Punycode, ToASCII and ToUnicode, and label validity, over generated Unicode 17.0 tables. |
original |
|
Validators and Boost.URL grammar rules for the string formats of JSON Schema, for C++20. |
original |
|
A generic Pratt parser engine for C++20, with a decimal calculator built on it. |
original |
|
Serverless WebRTC rooms for C++20, wire compatible with Trystero. |
Trystero 0.26.0, in JavaScript (MIT) |
|
Header-only helpers for C++ built as WebAssembly components: the HTTP handler a component exports on wasip2 and wasip3, and the macros a program writes its main between. |
original |
|
A header-only, deterministic actor system: actors that handle one message at a time, with fuel per execution, timers and a lifecycle. |
original |
|
A header-only port of XState’s state machines and actors: machines read from XState’s JSON config, stepped by XState’s pure functions or run as actors on xactor. |
XState 5.33.2, in TypeScript (MIT) |
Test matrix
Every library is tested on every target it declares, natively and for WebAssembly: on wasm32-wasip2 and wasm32-wasip3 with wasmtime, and with Emscripten, whose programs node runs. The test matrix shows each test and example of each library by lane, with the log of every failure.
Getting started
With Boost 1.92 or newer and b2 installed, a checkout of the superproject
builds and tests every library. trystero needs three libraries that webcpp
does not build yet, which its page says how to install: without them, b2
test builds and tests every other library and leaves trystero out, saying
so once for each library it did not find:
git clone --recursive https://github.com/webcpporg/webcpp
cd webcpp
b2 test
A b2 project uses a library through /webcpp/<name>//<name>; CMake or a
plain compiler uses the headers that b2 install --prefix=<dir> copies to
<dir>/include/webcpp/. The
README lists the
prerequisites and how to configure them,
CODING-GUIDELINES.md
holds the rules for porting a library to webcpp and the decisions of its
design, and AGENTS.md
says how to work in the tree.
Releases
The release notes of each version of webcpp, newest first: what came into the collection, what changed in each library, and what went out.
webcpp 0.1.0
New Libraries
-
asio: Boost.Asio with browser event-loop suspension, WASIp2/P3 networking and optional source-built TLS, from R.
-
beast: HTTP messages and WebSocket applications for native, WASI and browser targets, with socket transports, browser WebSocket and fetch, WASI host HTTP and supplied byte streams, from R.
-
cobalt: Boost.Cobalt coroutine applications for native, browser and WASI targets, with explicit source distribution and optional corrected SSL integration, from R.
-
config: webcpp’s configuration, which every library includes first: the target, exceptions and the version, from R.
-
document: a header-only JSON document for C++20 that behaves as JavaScript does, exact in decimal, in one relocatable binary image, with a JavaScript module, from R.
-
idna: a header-only library of internationalized domain names for C++20: Punycode, UTS 46 and IDNA2008 validity over Unicode 17.0.0 tables, from R.
-
lexical: header-only validators of JSON Schema’s string formats for C++20, allocating nothing, each also a Boost.URL grammar rule, from R.
-
pratt: a header-only Pratt-parsing engine for C++20, with a decimal calculator built on it, from R.
-
trystero: a port of Trystero 0.26.0, serverless WebRTC rooms wire-compatible with the original, for C++20, from R.
-
wasi: a header-only HTTP handler for C++20 programs built as WebAssembly components, covering WASI 0.2 and WASI 0.3, from R.
-
xactor: a header-only, deterministic actor system for C++20, from R.
-
xstate: a header-only port of XState’s state machines and actors for C++20, from R.
Updated Libraries
None.
Removed Libraries
None.
Tools and build
-
Fixed clean CMake consumer audits rejecting system libraries and phony dependency rules.
-
Changed CI to consume verified prepared environments without rebuilding images in PR jobs.
-
Added verified archive caches and isolated container availability from unrelated CI lanes.
-
Fixed parallel builds truncating OpenSSL headers while compilers read them.
-
Fixed driven-test execution and descendant cleanup on Windows.
-
Fixed driven-test executable reuse for Windows and WASI builds.
-
Improved lint preparation by separating OpenSSL headers from archive builds and upstream tests.
-
Fixed the WASIp2 test launcher interrupting large finite workloads after 60 seconds.
-
Fixed Chrome provisioning and browser/TLS profile coverage in Asio CI lanes.
-
Added source-built OpenSSL and Cobalt SSL targets for WASIp2.
-
Added explicit browser pthread profiles with main-thread handoff tests.
-
Changed lint to verify WASIp3 ABI snapshots before excluding upstream headers.
-
Fixed embedded CA headers using an unowned namespace and include path.
-
Added source-built Boost.Context for native stackful coroutine applications.
-
Added negative link tests and explicit reference-source build discovery.
-
Added hash-verified Beast application inputs and browser CI dependencies.
-
Added isolated CA trust tests with pinned full Chrome and a Wasmtime host fixture.
-
Fixed duplicate source paths selecting conflicting targets in the lint database.
-
Updated Wasmtime to 50.0.1 for every library’s WASI targets.
-
Fixed WASIp3 network tests lacking the required runtime capabilities.
-
Fixed OpenSSL source builds with symlinked compilers and Windows checkouts.
-
Fixed serial Windows OpenSSL builds exhausting the parallel-build time budget.
-
Added native MSVC OpenSSL build recipes with B2 runtime settings.
-
Fixed Cobalt lint builds requiring pre-existing generated Boost overlays.
-
Fixed source distributions rejecting pinned site and third-party dependencies.
-
Changed release checks to accept the tested compiler subset.
-
Added agent skills with validated metadata for common contributor workflows.
-
Breaking change: changed wasip2 programs to build with exceptions, as wasip3 does; whether a program uses them is its developer’s choice.
-
Added emscripten as a tested target (Emscripten 6.0.11 under Node): tests, link-only programs and driven tests, in CI and in own lanes.
-
Added the lint rule
bare-throw: a library header raises only throughboost::throw_exception. -
Added the lint rule
path.exists native: a Jam file’spath.existstakes a native path, which Windows needs. -
Added the lint rule
octal escapes: no octal escape of a C++ literal runs into a digit, which MSVC refuses. -
Changed the lint to analyse every aggregate, test and example without exceptions too, so a library keeps compiling without them.
-
Changed CI to run one own-lane job per library, lane and target, installing Node only where needed;
b2 declared-lanesprints each lane’s kind. -
Fixed an own lane that served nothing or missed a target passing silently; it now fails by name.
-
Fixed
serve.pyleaving wasmtime running when it is killed. -
Changed the lint’s compilation database to include every program an own lane builds, served programs included.
-
Fixed the Node package installer leaving a stray link or a traceback when an install is killed or refused.
-
Added the names
target,has,no,lib,versionandtest, alone or before_, to those no library may take. -
Added the lint rule refusing an unescaped
__X__in a Doc Comment’s code span. -
Added each version’s release notes to the index page, newest first.
-
Added the lint rule
changelog: every changelog line keeps its form. -
Added
b2 check-release,b2 whats-newandb2 dist, which check, announce and package a release. -
Added
third_party/, third-party code pinned as submodules: first the JSON Schema Test Suite, which a test reads on every target through/webcpp/third_party//json-schema-test-suite. -
Changed the lint to never read third-party code under
third_party/libs/. -
Added
webcpp.generated, which checks a library’s generated files against their Python generator, andupdate-generated, their only writer. -
Added
--filestotools/oracle/compare.py, which compares two files byte for byte. -
Added
/webcpp//boost_url, Boost.URL built from Boost’s sources for every target, read fromBOOST_SOURCEor.local/boost-source; another Boost version’s tree is refused. -
Changed the CI’s Boost action to keep the sources of Boost’s compiled libraries;
install.sh source <dir>fills a local tree. -
Changed the lint to never analyse a source outside the tree, such as Boost’s.
-
Added
/webcpp//boost_charconv, Boost.Charconv built from Boost’s sources for every target. -
Added
/webcpp//boost_locale, Boost.Locale without ICU built from Boost’s sources for every target; a program that uses it needs exceptions. -
Added
/webcpp//boost_cobalt, Boost.Cobalt built from Boost’s sources for native programs, which need exceptions. -
Fixed a lane’s alias and a library’s generated files running the configuration check of Boost, which neither needs.
-
Added
webcpp.data, which gives a test a directory of the host’s at the same path on every target, through wasmtime’s--diron WASI. -
Added
b2 siteandb2 site-serve: the whole site, every library’s page and the report under its header, intobin/site/, every link checked, then served. -
Added the site’s tests,
b2 /webcpp/site//test, and a CI lane that runs them. -
Changed CI to publish the site, never indexed, at https://webcpporg.github.io/; the old address https://webcpporg.github.io/webcpp/ redirects there.
-
Added
/webcpp//emscripten-reference, which reads a library’s reference as Emscripten’sem++compiles it, with the emsdk of-sWEBCPP_EMSDK=<dir>or.local/emsdk. -
Changed the lint to analyse headers and programs that build only on emscripten, with the options
em++gives them, or only against a native dependency. -
Changed the CI’s docs and lint jobs to install emsdk only when a library declares emscripten.
-
Changed the lint’s analysis without exceptions to leave out, by name, a header whose headers-alone call declares
<exception-handling>on. -
Changed the lint’s
*thisrule to allow an assignment operator however its signature is split, a prefix increment or decrement, and a function markedlint-std. -
Changed the lint’s
io_context::runrule to find anio_contextnamed through a namespace alias, and to accept a reason afterlint-run:. -
Changed the lint’s world rule to name
getentropy,getrandom,arc4random,RAND_bytesand<sys/random.h>. -
Changed the lint’s licence rule to check
.js,.adocand.htmlfiles too. -
Added
webcpp.external, which finds a library webcpp does not build through-s<VARIABLE>=<dir>,.local/or the system, and leaves out a library that needs a missing one. -
Added
webcpp-require-external=on, which stops the build on a missing external library instead, as the CI and the lint build. -
Changed the index to name a library a build leaves out, with the reason and no link.
-
Changed
b2 installto put each library’s licence files beside its headers. -
Added
{library-root}, through which a library’s page shows a tagged region of a file its own git tracks, a test’s or an example’s as C++. -
Added doc-check rules: a rendered page holds no em dash, no link inside inline code, and no replacement of Asciidoctor’s inside inline code.
-
Changed every library’s reference to list only a derived class’s own members (
inherit-base-members: never). -
Changed a page’s counts to read with a thousands separator, as 1,111.
-
Changed the CI’s GCC 14 and Clang 18 lanes to run in a container built from Ubuntu’s archive snapshot, with no network but the loopback.
-
Added a pinned chrome-headless-shell to the CI, for the own lanes whose driver meets a browser.
-
Added the CI actions
secp256k1,libdatachannelandopenssl, which build trystero’s external libraries, pinned, with each lane’s compilers. -
Changed the Node package installer to run
npm ciwithDO_NOT_TRACK=1, so that no install script reports an install. -
Changed CI to run the lint and the tests of the tools in eight shards each, at once.
-
Added
--shard K/Nto the tests of the tools, which runs the K-th of N slices of a suite’s cases. -
Fixed the site refusing the report’s page of a failure: its title now fits in 70 characters, and no line of its output ends in whitespace.
-
Changed the libraries’ CI to check out the superproject’s submodules without theirs, so a pinned third-party repository’s own submodules are not fetched.
-
Added
webcpp-suspend, an emscripten program’s suspension variant:jspi, the default, orasyncify, built with JavaScript-based exceptions. -
Added
/webcpp//node-test, which every test and example links, with<webcpp/test/exit_status.hpp>: under Node, a test whosemainnever finishes fails, and one past its bound of 120 s stops. -
Changed
webcpp::test::exit_statusto end a test under Node at once, with the first status it is given. -
Added a refusal of
-sMODULARIZEand-sEXPORT_ES6on a test or example that Node runs, which would pass having run nothing. -
Fixed a test passing under Node when its
mainnever ran, or when-sMODULARIZEcame among other flags of one value. -
Added
webcpp.variantsandwebcpp.size-table: a page’s program in both suspension variants, its manifest for the page’s loader, and its sizes, kept by the CI. -
Added the tag rule
webcpp.suspend-tag, which names an emscripten program Boost’s way, with its suspension variant. -
Changed
webcpp.variantsto refuse a build that asks for JavaScript exceptions, which would link thejspivariant with them. -
Fixed the lint stopping on a program built with JavaScript-based exceptions, such as an
asyncifyvariant’s. -
Fixed a test ending through
webcpp::test::exit_statusprinting Emscripten’s notice that the runtime is kept alive. -
Changed the lint rule
bare-throwto leave alone the JavaScript of anEM_JSfunction or anEM_ASMblock.
Compilers tested
-
GCC 15
-
Emscripten 6.0.11 (node)