TownSquare documentation
Add a little life to your website
TownSquare is a small shared place you drop into your site. Visitors can see each other, wander around, and say hello in real time. This guide covers how to add one and look after it. You don't need to be technical to follow along.
Two ways to use it
There are two ways to put a TownSquare on your site. Most people want the first one.
| Register | Self-host | |
|---|---|---|
| Best for | Most site owners | Developers |
| Run a server? | No, it's hosted for you | Yes, your own |
| What you do | Fill a short form, paste a snippet | Deploy and configure |
| Coding | None | Some |
Register is the easy path. You don't run anything yourself. You enter your website's address and copy a small snippet into your page. The live square is hosted for you. The Get started section below is about this path.
Self-hosting means running the TownSquare server yourself. You get full control, but it takes some setup and a bit of code. If that sounds like you, jump to Self-hosting.
Get started
Adding TownSquare takes about a minute:
- Open the registration page and enter your website's address.
- Click create. You get two things: a snippet and an admin token.
- Paste the snippet into your page, wherever you want the square to appear.
That's it. Your square is live, and visitors start showing up.
Keep your admin token somewhere safe. It's how you moderate the square later. There's no account behind it and no way to recover it.
Use the square
Walk with the arrow keys, click or tap the ground, or swipe sideways on a touch screen. The action buttons let you jump, offer a high-five, and throw crumbs for the birds. When crumbs land, a little flock flies to the spot, hops around to eat, and then leaves. Everyone currently in the same square sees the visit.
Keyboard shortcuts are J for jump, H for high-five, B for bird crumbs, and T for chat. Feeding has a short cooldown so repeated clicks cannot fill the scene with animations.
Manage your square
Open your admin page and sign in with your admin token. From there you can:
- see whether your site is connected, and who's around right now
- copy the embed snippet again any time
- customize the colors and scene to match your site (see Customize the look)
- mark visitors as verified site owners and customize their owner badge (see below)
- keep things friendly by removing a visitor, turning off chat, or pausing the square
- clear recent in-memory chat messages
Moderation changes take effect live. Disabling the site closes the square for everyone; turning chat back on or re-enabling the site brings it back.
Mark a visitor as a site owner
Visitors are anonymous, so by default nothing tells the owner apart from everyone else. You can give your own character a verified badge, a 👑 crown:
-
Open your own site so you show up as a live visitor. Add
#townsquare-ownerto the address and the square shows a hint with your visitor number (You're visitor #N …). - On your admin page, find that visitor in the active list.
- Click Make owner. Your character gets the crown live for everyone in the square, and keeps it on every future visit from that browser. Click Owner ✓ to remove it and its saved owner profile.
- In Site owner, customize the owner's display name, character colour, and badge colour. You can edit an owner while they are offline; the saved profile is restored when that browser reconnects.
The badge is issued by the server, so it can't be faked by typing a name or picking a colour. Hover over or focus the crown to see the Site Owner label. Ownership and the saved owner profile are tied to the specific browser you marked, so another browser can't claim it. Because TownSquare stays accountless, a new device or cleared browser storage means marking owner once more (one click). You can mark more than one browser if you want the badge on several devices.
Customize the look
Out of the box your square uses TownSquare's default look: a warm, neutral palette that already follows light and dark mode. You don't have to change anything. When you want it to feel more like your site, your admin page has a customization panel with a live preview. Both the scene and the colors are managed from there and apply to your live square on their own, with nothing to re-paste.
Scene
Choose how many benches, trees, lamps, and birds appear, and where they sit. Scene changes are saved on the TownSquare server and tied to your site key, so anyone in your square sees the new layout right away, and you never touch the snippet on your site.
Colors
Pick a color for each part of the scene (sky, ground, buttons and tags, ink, accent, and the tree trunk and leaves) and tune light and dark separately. Your choices are saved on the TownSquare server and served to your site automatically. The embed snippet already links a small per-site stylesheet, so when you change a color in the admin page it shows up on your site within a few minutes, with nothing to copy or re-paste.
If you added a hand-copied Customization CSS block to your site in the past, you can remove it and re-paste the current snippet from your admin page. Keep it only if you want to manage colors yourself (see below) — a block on your own page overrides the served colors and won't follow later edits in the admin page.
Bring your own CSS (advanced)
Served colors are the easy path, not a lock-in. If you want more control
than the swatches give you, the admin page still has a
Custom CSS override section you can copy, or you can
write your own rules targeting the visual tokens on
#townsquare-root. They apply to both light and dark:
| Token | Controls |
|---|---|
--scene | Sky (background above the ground line) |
--ground-fill | Ground band (was --page) |
--action-zone-fill | Action zone below the scene |
--surface | Buttons and tags |
--ink | Text and line work |
--you | Accent (your own character) |
--tree-trunk | Tree trunks |
--tree-canopy | Tree leaves |
--other | Other line work |
--ground-line | Ground line (was --ground) |
The old --page and --ground names still work as
aliases, but prefer the new ones. The widget and the served stylesheet
never write these tokens inline, so your own CSS can always take over. The
served stylesheet sets them at a raised specificity (a doubled
#townsquare-root#townsquare-root selector), so match that in
your own rules — or just copy the Custom CSS override
block from the admin page, which already does. Technical owners get full
control while everyone else stays on the simple path.
Livestream overlay (Supporter)
Supporter sites can show their live TownSquare in streaming apps and production systems that support browser sources. OBS is one common example, not a requirement. The overlay is watch-only: it follows the live square, but it does not add another active visitor or let the stream interact with chat.
Open your admin page, go to Add-ons, and look for Livestream overlay. If you do not see it, your site does not have Supporter enabled yet.
- Choose the overlay theme.
- Choose Transparent for a normal overlay, or Solid color when your stream setup handles chroma keying better than transparency.
- Save the settings.
- Copy the browser-source overlay URL.
The copied URL includes the selected theme and background settings. If you change those settings later, copy the updated URL into your streaming app again.
Streaming app setup
- Add a browser source or web source to your scene/layout.
- Paste the copied overlay URL into the source URL field.
- Set the source size to your canvas, such as
1920 x 1080or1280 x 720. - Place the source above the camera, screen share, or other scene layer where you want the square to appear.
If transparent background does not work in your streaming app, switch the
overlay to a solid color such as #00ff00, then use a
chroma-key or color-key filter. In OBS, that filter is called
Chroma Key.
For a longer walkthrough, read Put your TownSquare in a livestream overlay.
Supporter and Plus
TownSquare's core stays free and useful forever. Supporting the project is optional, and there are two ways to do it.
- Supporter is a thank you for one-time support. It includes accessories, Telegram notifications, scene cats, the livestream overlay, and the Guest Notes board.
- Plus is for monthly support. It includes everything in Supporter, private visitor and message statistics, and ongoing Plus features.
See the TownSquare support page for the full comparison, payment links, and activation instructions.
For developers
Self-hosting
Everything below is optional. Most people are better off registering, which needs no server. Self-hosting is for developers who want to run TownSquare on their own infrastructure.
You're deploying one small Node process (Node.js 18 or newer). It does three things:
- serves the widget and the registration and admin pages
- handles realtime presence and chat over a WebSocket
- answers
/healthzfor health checks
It defaults to host 127.0.0.1, port 8787, and WebSocket path /live.
Run the server
Locally
npm install
npm start
With Docker
docker build -t townsquare .
docker run --rm -p 8787:8787 -e HOST=0.0.0.0 townsquare
Once it's running, your own /register page works just like the
hosted one: site owners register, get a snippet and admin token, and you can
manage every site from /service-admin (set
SERVICE_ADMIN_PASSWORD to enable it).
Configuration
Everything is set through environment variables. The common ones:
| Variable | Purpose |
|---|---|
HOST / PORT | Where the server listens. |
PUBLIC_ORIGIN | Public origin used in generated snippets and admin links. |
DATA_DIR | Where the registered-site list is stored (defaults to .data/). |
SERVICE_ADMIN_PASSWORD | Enables the service admin page. |
REGISTRATIONS_PER_HOUR | Per-IP registration limit (default 20; 0 disables). |
AUTH_FAILURES_PER_HOUR | Per-IP failed sign-in throttle (default 30; 0 disables). |
INACTIVE_DISCONNECT_MS | Drop away/inactive visitors (default 30 min; 0 disables). |
TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID | Get a Telegram ping on each chat message. |
For local runs, copy .env.example to .env; the
server loads it on startup. Real environment variables win over
.env values.
Embed in code
If you'd rather mount TownSquare yourself instead of using the registration flow, load the stylesheet and module, then mount it into any element:
<link rel="stylesheet" href="https://your-townsquare-host/widget.css" />
<div id="townsquare-root"></div>
<script type="module">
import { mountTownSquare } from "https://your-townsquare-host/townsquare.mjs";
mountTownSquare(document.getElementById("townsquare-root"), {
serverOrigin: "https://your-townsquare-host",
socketPath: "/live",
theme: "host"
});
</script>
Your page decides where the square appears. TownSquare takes care of what happens inside it. The mount options are intentionally small:
| Option | Purpose |
|---|---|
serverOrigin | The TownSquare origin to load assets from and connect to. |
socketPath | WebSocket path on that origin (defaults to /live). |
siteKey | Only needed when one hosted server runs several registered sites. |
theme | Use "host" to follow common host-page dark mode signals. Defaults to "auto". |
connections | Neighbouring towns linked at the edges, e.g. [{ side: "left", label: "Maple Lane", url: "https://maplelane.dev" }]. Each grows a signpost visitors can walk over to. |
The registration snippet from your own /register page is the
standard way to embed a site. On top of the manual mount above it also
links /api/sites/<siteKey>/style.css, so colors set in
the admin page are served to the site live, and it keeps TownSquare in
sync with common host-page dark mode signals such as
html.dark, data-theme, and
data-color-mode.
For a hand-rolled mount that skips that stylesheet, restyle the square by
setting the palette tokens on #townsquare-root in your own
stylesheet — or add the style.css link above to get the
served colors. See Customize the look for the
full token list. The widget writes no inline palette styles, so your CSS
always wins.
Production notes
For a real deployment, put TownSquare behind a reverse proxy (nginx, Caddy, or similar) that:
- forwards normal HTTP traffic
- allows WebSocket upgrades on
/live - keeps the origin stable so asset and socket URLs line up
On a custom socket path like /townsquare/live, pass it
explicitly with socketPath. The repo ships a deploy helper at
scripts/deploy.sh (copy .env.deploy.example to
.env.deploy.local first). By default it deploys the local
production tag. Use --tag <git-tag> for another
tag, and use --ref only when deploying an explicit branch or
commit. The server also exposes a health endpoint at
/healthz that simply returns ok.
Self-hosting is kept lean on purpose. There are no accounts, no token recovery, and no billing. The goal is a single-site server that's clean and easy to run, with the hosted model layered on top later.