BIGWORDS.PAGE reference

BIGWORDS.PAGE shows a message as large as the screen allows. Everything about the display is in the URL, so sharing the link shares the display. There are no accounts and no backend, and nothing is stored anywhere.

The editor is the easiest way to make a display. All of the URL parameters are documented here, so generating links is easy too.

Try it: https://bw.teddysc.me/#Hello%20World

How the URL works

All state lives in the URL fragment, the part after #. Browsers never send the fragment to a server, so:

  • the server never sees or logs your message,
  • changing the fragment updates the display without reloading the page,
  • one static page serves every possible display.
https://bw.teddysc.me/#Hello%20World&bg=000000&fg=ffffff&anim=pulse

After the #:

#Hello%20World&bg=000000&fg=ffffff&anim=pulse
 └─ message ─┘ └──────── parameters ────────┘

The message is everything before the first unencoded &. Each segment after it is a key=value parameter.

The editor uses the same fragment at a different path:

Viewer:  https://bw.teddysc.me/#Hello%20World&anim=pulse
Editor:  https://bw.teddysc.me/editor#Hello%20World&anim=pulse

Pages

Path What you get
/ (no fragment) Home page with examples
/#… (any fragment) Viewer: fullscreen, no controls
/editor Editor with live preview. Without a fragment it opens a starter message.
/docs This reference

Any non-empty fragment opens the viewer, even with no message. https://bw.teddysc.me/#&bg=ff0000 is a solid red screen.

Encoding

Use standard percent-encoding.

Character Write it as Notes
Space %20
New line %0A The only way to make a line break
& %26 Required in the message, since & starts a parameter
# %23 Required in the message
% %25 Required for a literal percent sign
| %7C Optional
{ } %7B %7D Optional
\ %5C Optional

You can type spaces and emoji into the address bar as they are. The browser encodes them, and a link copied from the address bar has them encoded. New lines, &, # and % in the message always have to be written encoded. The editor always produces fully encoded URLs.

Messaging apps and other tools that turn URLs into links usually stop the link before punctuation at the very end, so #Hello! gets linked as #Hello. Encode punctuation at the end of a URL, such as ! as %21 or . as %2E. The editor does this for you.

Parameters

Param What it does Values Default
(message) The text to display Any percent-encoded text. Supports the markdown subset, {countdown}, || slide breaks and \ escapes. (empty)
bg Background color auto, or 6-digit hex without # (000000) auto
fg Text color auto, or 6-digit hex without # (ffffff) auto
font Font 0–6, see Fonts 0
size Font size auto, pixels (48), or with a unit (5vh, 8vw) auto
size-min Smallest auto size. Text that needs to be smaller runs off the screen. Pixels (12) or with a unit (2vh, 3vw) (none)
size-max Largest auto size Pixels (72) or with a unit (15vh, 10vw) (none)
wrap Break long lines between words to fit the width, see Wrapping on, off on
pad Padding, in percent 5, 5,10 or 5,10,5,10, see Padding 5
anim Animation none, pulse, flash, shake, bounce, scroll, crawl, typewriter, fadein, rainbow none
speed Animation speed slow, normal, fast normal
ratio Fix the display to an aspect ratio W:H (16:9, 4:3, 1:1, 9:16, 21:9…) (fill the screen)
qr Show a QR code A percent-encoded URL, or a Wi-Fi, phone, text, email or location code, see QR code (none)
qrpos QR code position tl, tr, bl, br, below br
qrsize QR code size, in percent of the display's shorter side Whole number from 10 to 50 25
img Show an image A percent-encoded public image URL (none)
imgpos Image position bg, full, above, below bg
refresh Reload the image every N seconds Whole number from 1 to 86400 (larger values count as 86400) (none)
until Countdown target ISO 8601 date and time (2026-12-31T23:59:00) (none)
timer Countdown length, from when the page opens. Use until or timer, not both. Seconds (14400), or d, h, m, s amounts (4h, 1h30m) (none)
cdfmt Countdown format label, colon label
zero What happens at zero freeze, hide, or a replacement message, which can use formatting and line breaks like the main one freeze
interval Seconds per slide Number from 0.2 to 86400, to hundredths (2, 1.5, 0.25). Smaller values count as 0.2, larger ones as 86400. 5
trans Slide transition slide, none, fade, up, zoom, see Slides slide
wake Keep the screen awake on, off on
dbg Show debugging information, see Debug 0 (off), 1, 2, 3 0

An invalid value (bad hex, unknown font, impossible date…) quietly falls back to that parameter's default. The viewer never shows an error.

Formatting

Messages support a small part of Markdown. A message without any formatting shows as plain text.

Write Get
**text** or __text__ Bold
*text* or _text_ Italic
***text*** or ___text___ Bold italic
~~text~~ Strikethrough
`text` Code: monospace on a faint box, shown exactly as typed
# text at the start of a line Heading, 2× the base size
## text at the start of a line Heading, 1.5× the base size
%0A Line break

Other Markdown, such as lists, links and images, shows as plain text. In a URL, write a heading's # as %23: https://bw.teddysc.me/#%23%20Gate%2012%0ABoarding%20now

Formatting can span lines. Bold, italic and strikethrough carry over line breaks, so **WELCOME HOME,%0AGRANDMA!** is bold on both lines. A blank line or a heading ends them, and a marker without a matching one is shown as typed.

Underscores inside words are left alone, as in standard Markdown, so names like Home_Guest_5G, snake_case or first_name@example.com show exactly as typed. Only an underscore at a word boundary starts or ends emphasis.

Code is shown exactly as typed. Nothing inside backticks is treated as formatting, a slide break, {countdown} or an escape, which makes it the easy way to show passwords and codes with symbols in them. A code span has to open and close on the same line. Browsers may write a typed backtick as %60 in the address bar; both forms work.

https://bw.teddysc.me/#Price:%20~~$20~~%20**$15** · https://bw.teddysc.me/#Wi-Fi:%20Home_Guest_5G%0APassword:%20%60x*7|q%60

Special tokens

Token Meaning
{countdown} Replaced by the live countdown when until or timer is set. Works in any slide. Shown literally if neither is set.
|| Slide break

Escapes

A backslash makes the next character literal.

Write Shows
\|\| or \|| || (not a slide break)
\{countdown} {countdown}
\*not italic\* *not italic*
\# not a heading # not a heading
\~\~not struck\~\~ ~~not struck~~
\`not code\` `not code`
\_not italic\_ _not italic_
\\ \

A backslash before any other character is dropped. In a URL you can type the backslash as-is or as %5C.

Processing order: percent-decode → escapes and code spans → split slides on || → markdown → {countdown} → restore escaped characters.

Fonts

font Font License
0 Your device's system font —
1 Inter SIL OFL 1.1
2 Montserrat SIL OFL 1.1
3 Roboto Slab Apache 2.0
4 Bebas Neue SIL OFL 1.1
5 JetBrains Mono SIL OFL 1.1
6 Caveat SIL OFL 1.1

All fonts ship with the site, each next to its license file. A font is only downloaded, from this site, when a display uses it. Nothing is loaded from third-party font services.

Size

With size=auto (the default), the text grows to the largest size at which the whole block fits inside the display minus its padding. Headings count at their full size. Long lines wrap between words to fit, see Wrapping. The size is recalculated whenever the window is resized or rotated, and each slide is fitted on its own.

Value Meaning
48 48 pixels
5vh 5% of the screen height
8vw 8% of the screen width
auto Fit to the screen (size only)
  • size-max caps the size, however much room there is.
  • size-min sets a floor. If the text would have to shrink below it, it stays at the minimum and runs off the edges of the screen, centered.
  • With neither, the size scales freely with the screen.
  • Both only apply with size=auto. A fixed size is used as given.
  • 0 counts as not set, so size=0 is auto.

Example: https://bw.teddysc.me/#Big%20but%20not%20huge&size-max=12vh

Wrapping

With wrap=on (the default, Word wrap in the editor), lines break between words wherever they need to, and auto-fit picks the largest size at which the wrapped text fits. Long messages come out much bigger, and the same link fills a phone held upright as well as a wide TV, since each screen wraps the text its own way. The breaks are balanced, so a wrapped line doesn't end on a single short word where the browser supports it.

  • Your own line breaks and headings stay: wrapping only adds breaks.
  • Lines break at spaces and after hyphens, as on any web page, and between characters in languages written without spaces, such as Chinese and Japanese. A word is never split anywhere else: one too long for the width makes the text smaller.
  • With a fixed size, text wraps at that size instead of running off the sides.
  • crawl wraps to the width as it scrolls up. scroll moves sideways, so it ignores wrap.

With wrap=off, each line of the message stays on one line, so long lines make the text smaller. Add line breaks (%0A) where you want them.

Compare wrapped and wrap=off.

Padding

pad is a percentage, written in CSS shorthand order. Top and bottom are a percentage of the display height; left and right are a percentage of its width. "Display" means the ratio region when one is set.

Form Example Meaning
One value pad=5 5% on every side
Two values pad=5,10 5% top and bottom, 10% left and right
Four values pad=5,10,5,10 Top, right, bottom, left

The three-value form isn't supported. Each value must be below 50.

Colors

auto follows the viewer's light or dark setting: white on black in dark mode (and when it can't be detected), black on white in light mode. Set bg and fg independently as 6-digit hex without the #. If you set only one, the other stays auto.

https://bw.teddysc.me/#Exit&bg=0a7a2f&fg=ffffff&font=4

Animations

anim Effect Example
none Static https://bw.teddysc.me/#Standing%20still&font=2
pulse Gentle breathing scale https://bw.teddysc.me/#ON%20AIR&bg=b00020&fg=ffffff&font=4&anim=pulse
flash Blinks on and off. Fast flashing can affect people with photosensitive epilepsy. https://bw.teddysc.me/#SALE&bg=ffd60a&fg=111111&font=4&anim=flash
shake Horizontal jitter https://bw.teddysc.me/#Wake%20up!&font=2&anim=shake
bounce Vertical bounce https://bw.teddysc.me/#Over%20here!&font=6&anim=bounce
scroll Marquee from right to left. The text is sized to the height, so set size-max. https://bw.teddysc.me/#Now%20boarding%20all%20rows&anim=scroll&size-max=30vh
crawl Scrolls from bottom to top. The text is sized to the width, so set size-max. https://bw.teddysc.me/#Thanks%20for%20coming%0ASee%20you%20next%20year&anim=crawl&size-max=12vh&font=3
typewriter Types each character, pauses, deletes quickly, repeats https://bw.teddysc.me/#Hello...&anim=typewriter&font=5
fadein Fades in once https://bw.teddysc.me/#Good%20evening&font=3&anim=fadein&speed=slow
rainbow Cycles the text through the color wheel, overriding fg https://bw.teddysc.me/#Happy%20Birthday!&anim=rainbow&font=6

speed=slow|normal|fast applies to all of them. Compare slow, normal and fast pulses.

Display ratio

Without ratio, the message fills the screen. With ratio=W:H it's drawn in a centered region of that shape, with the background color filling the rest. Useful for matching a projector or a video frame.

The editor also accepts a width × height in pixels and turns it into a ratio (1920 × 1080 → 16:9). Only the ratio goes in the URL.

Countdown

There are two kinds: until counts down to a date and time, and timer counts down for a length of time. Set one and put {countdown} in the message. If the message is empty, the countdown is shown on its own. Format and zero work the same for both.

Until a date and time

Set until to an ISO 8601 date and time. The time is the viewing device's local time, unless you add a zone such as Z or +02:00. The editor's date picker takes the time in your own time zone and writes it to the URL in UTC (with Z), so the countdown ends at the same moment everywhere.

For a length of time

Set timer to a length of time. The timer starts when the page opens, so reloading the page or opening the link again starts it over. Each device that opens the link runs its own timer. It keeps time while the tab is in the background or the screen is off.

timer Length
14400 A plain number is seconds: 4 hours
4h 4 hours
1h30m 1 hour 30 minutes
2d12h 2 days 12 hours
45s 45 seconds

Use any of d, h, m and s, in any order, with no spaces. Amounts add up and can go past the next unit, so 90m is 1 hour 30 minutes and 1d28h is 2 days 4 hours. The longest timer is 99 days.

https://bw.teddysc.me/#Break%20ends%20in%0A{countdown}&timer=15m&zero=Back%20to%20work!

until and timer can't be used together. If a link has both, the one that comes first is used and the other is ignored. The editor shows one at a time: pick Countdown or Timer at the top of its Countdown or timer section.

Format and zero

cdfmt Example
label (default) 2d 14h 06m 32s
colon 02:14:06:32

With label, units are dropped from the front once they reach zero: three hours shows as 3h 00m 00s, then 59m 59s, then 59s. Zeros after the first unit stay, so the countdown doesn't jump around as it ticks. colon always shows all four units.

zero One slide Several slides
freeze Stays at zero Every {countdown} stays at zero
hide The display goes blank (background only) Slides containing {countdown} drop out; the rest keep rotating. If none remain, the display goes blank.
a message The message replaces the display The message replaces each slide that contains {countdown}

https://bw.teddysc.me/#Doors%20open%20in%0A{countdown}&until=2027-01-01T19:00:00&zero=Welcome!

Slides

Separate slides with ||. All slides share every setting, and each is fitted on its own. A new slide comes in every interval seconds, using the transition set by trans:

trans The next slide…
slide Slides in from the right
none Replaces the last one at once
fade Fades in as the last one fades out
up Slides in from below
zoom Grows into place as the last one fades out

https://bw.teddysc.me/#Welcome!||Doors%20open%20in%0A{countdown}||Enjoy%20the%20show&until=2027-01-01T19:00:00&interval=8

https://bw.teddysc.me/#9:00%20Welcome||10:30%20Workshops||12:30%20Lunch&interval=3&trans=up

Transitions last 0.6 seconds, or less when slides change quickly, so a transition always finishes well before the next one starts. When the viewing device is set to reduce motion, slide, up and zoom fade instead.

Slides changing faster than about twice a second can affect people with photosensitive epilepsy.

The editor counts the URL's characters and warns as it nears about 2,000. Some messaging apps, email clients and proxies cut off longer links.

QR code

qr puts a QR code on the display, drawn in your browser with no outside service. Its value is the text the code holds, and how it starts decides what the scanning phone does:

Type qr starts with Phone action
Link Any URL, such as https:// Opens the link
Wi-Fi WIFI: Offers to join the network
Phone call tel: Offers to call the number
Text/SMS SMSTO: Opens a new text message
Email mailto: Opens a new email
Location geo: Opens a maps app (Android)
Plain text Anything else Shows the text

The editor's QR code section has a form for each type and writes the URL for you. If you build one yourself, encode the qr value like the rest of the URL, with %26 for &.

Placement and size

Param What it does Values Default
qrpos Where the code goes A corner (tl, tr, bl, br), or centered below the text (below) br
qrsize Size, in percent of the display's shorter side Whole number from 10 to 50 25

The code scales with the screen. Larger codes scan from farther away, and a long qr value makes a denser code, which needs a larger size. The code is always black on white with a quiet zone, so it scans whatever your colors are.

qr=<URL>: any URL, such as https://example.com/menu. Inside it, write & as %26, # as %23 and % as %25 (so an escaped space, %20, becomes %2520).

https://bw.teddysc.me/#Scan%20me&qr=https://bw.teddysc.me/docs&qrpos=below

Wi-Fi

qr=WIFI:T:<security>;S:<network>;P:<password>;;

Phones that scan it offer to join the network. Each field ends in ;, the fields can come in any order, and the whole value ends with one more ;.

Field Meaning Values Required
T Security WPA (also covers WPA2 and WPA3), WEP, or nopass for an open network Yes
S Network name (SSID), exactly as the phone lists it Text Yes
P Password Text Yes, unless T:nopass; leave it out then
H Hidden network true No; leave it out for a visible network

In the network name and password, first put a \ before any \, ;, ,, : or ". Then encode the result for the URL: spaces become %20 and each \ becomes %5C. For the network Cafe Guest with the password latte;art:

Step Value
Fields T:WPA; S:Cafe Guest; P:latte\;art;
Code text WIFI:T:WPA;S:Cafe Guest;P:latte\;art;;
In the URL qr=WIFI:T:WPA;S:Cafe%20Guest;P:latte%5C;art;;

https://bw.teddysc.me/#Free%20Wi-Fi%0AScan%20to%20join&qr=WIFI:T:WPA;S:Cafe%20Guest;P:latte%5C;art;;&qrpos=below&qrsize=35

An open network: qr=WIFI:T:nopass;S:Library;;. A hidden one: qr=WIFI:T:WPA;S:Back%20Office;P:secret123;H:true;;.

The password is in the link and in the code, so anyone with the link or a view of the screen can read it.

Phone call

qr=tel:<number>

The number is required. Use the international form, such as +15551234567, so it works from any country; the + can be typed as is. Spaces and dashes in the number are ignored, so tel:+1-555-123-4567 works too.

https://bw.teddysc.me/#%23%20Lost%20dog%0AMax,%20brown%20terrier%0ACall%20555-123-4567&qr=tel:+15551234567&qrpos=below&qrsize=30

Text/SMS

qr=SMSTO:<number>:<message>

Field Meaning Required
Number The number to text, as for Phone call Yes
Message Filled in for the sender to edit before sending. It can contain :. Leave it out along with the : before it for an empty message. No

https://bw.teddysc.me/#%23%20Found%20a%20cat?%0AText%20us&qr=SMSTO:+15551234567:I%20found%20your%20cat&qrpos=below&qrsize=30

Email

qr=mailto:<address>?subject=<subject>%26body=<message>

Field Meaning Required
Address Who the email goes to Yes
subject Filled-in subject No
body Filled-in message No

Leave out a field you don't need, and the ? too if there are none. The & between subject and body must be written %26.

https://bw.teddysc.me/#Questions?%0AEmail%20us&qr=mailto:hello@example.com?subject=Question%26body=Hi!&qrpos=below

Location

qr=geo:<latitude>,<longitude>

Field Meaning Values Required
Latitude North (+) or south (−) Decimal degrees, -90 to 90 Yes
Longitude East (+) or west (−) Decimal degrees, -180 to 180 Yes

Android opens it in a maps app. iPhone cameras may only show it as text, so for iPhones use a link to a map instead.

https://bw.teddysc.me/#Meet%20here&qr=geo:40.6892,-74.0445&qrpos=below

Plain text

Any value that isn't one of the above, such as qr=Table%2012, goes in the code as text, decoded like the rest of the URL (Table 12). The phone shows the text and does nothing else.

Image

img takes a public image URL (http, https or data:image).

imgpos Behavior
bg Fills the display, cropped as needed; text on top
full Fits inside the display, letterboxed; text on top
above / below Placed above or below the text, which fits into the space left

The image loads straight from its host, which is never told which page asked for it. Like any image on the web, the host does see the viewing device's IP address and browser, and with refresh it sees a request every time the image reloads. Some hosts refuse to serve images to other sites, so an image that opens fine in its own tab can still fail here. If an image fails, the viewer leaves it out and the editor shows a warning.

refresh=N loads the image again every N seconds, for an image URL that points at something that changes, such as a webcam snapshot or a chart. Only the image reloads: the text, slides and any timer carry on. The new image replaces the old one once it has fully loaded, and if it fails to load, the last one stays up. Each reload adds a throwaway _= query parameter to the image URL, so no cache can answer it with the old image.

Tips

  • Keep a slide up longer: repeat it. A||A||B shows A for two intervals. With trans=none the repeat is seamless.
  • Add a pause: leave a slide empty. A||||B shows a blank screen between A and B.
  • Keep every slide the same size: auto-fit sizes each slide on its own, so a short slide comes out bigger than a long one. Set size-max to about the size the longest slide gets, and they all match.
  • Show one word at a time: give each word its own slide, with a short interval and trans=none. https://bw.teddysc.me/#**You**%7C%7C**dropped**%7C%7C**your**%7C%7C**wallet**%7C%7C**wallet**&bg=000000&fg=ffffff&font=4&size-max=50vh&interval=0.2&trans=none
  • Show commands and codes exactly as typed: put them in backticks, so symbols like * and _ aren't read as formatting. Without them, the stars in this command would vanish and .jpg would turn italic. https://bw.teddysc.me/#%23%23%20Step%203%0A%60cp%20*.jpg%20*.png%20photos/%60
  • Open it on another screen: in the editor, the QR button next to the URL shows the display's link as a QR code. Scan it with the tablet or phone that will show the display.
  • Hide the browser: use the browser's full screen mode (F11 on Windows and Linux, Control-Command-F on a Mac), or install the app, which opens full screen where the device allows it.

Viewer behavior

  • Screen wake: with wake=on (the default) the viewer asks the browser to keep the screen on. It asks again whenever the tab becomes visible. Browsers without support ignore it.
  • Fullscreen: the viewer never asks for fullscreen and has no controls. Use your browser's or kiosk's own fullscreen mode.
  • Tab title: always BIGWORDS.PAGE, whatever the message.
  • Errors: never shown. Bad parameters use defaults; failed images are left out.

Debug

When a display doesn't look the way you expect, such as text smaller than it should be or something in the wrong place, dbg shows how the viewer laid it out. Each level adds to the one before:

dbg Shows
0 Nothing. The display as normal.
1 Outlines: the display (magenta), the padding (cyan), the text area (yellow), the text and each of its lines (green), the QR code (orange) and an image above or below the text (red), with a key along the top.
2 Also a panel with the measurements behind the text size: whether it's running in a browser or as an installed app, the screen, window and text area sizes, the font size and whether it was fitted or fixed, the size of the text and each line, the extra room left for letters that draw past their edges, whether the font has loaded, the link exactly as the browser received it, before any decoding, and the browser's user agent. It describes the slide on screen and updates whenever the text is fitted.
3 Also every size the fit tried, in order, with the size the text measured at each and whether it fit (✓ or ✗). The fit keeps the largest size that fits, so each ✓ should be smaller than every ✗.

https://bw.teddysc.me/#Wi-Fi:%20**Cafe%20Guest**%0APassword:%0A**latte;art**&dbg=3

The overlay shows only in the viewer, not in the editor's preview. A screenshot of it at level 3 is the most useful thing to include when reporting a display problem.

The editor

The editor shows a live preview that renders exactly what the viewer shows, plus controls for every parameter.

  • The address bar always mirrors the current state, without filling your history.
  • Editing the fragment in the address bar updates the controls.
  • The URL field below the preview is editable too: paste a link (or just its fragment) and press Enter to load it. In the installed app, which has no address bar, that's how to edit an existing link.
  • Copy URL copies the viewer URL (the same fragment without /editor). Open viewer shows it in the same tab, and Back returns to the editor; the icon next to it opens it in a new tab instead. The QR button next to the URL shows it as a QR code, so a phone or tablet can scan it to open the display.
  • Parameters left at their defaults are dropped from the URL to keep it short.

Install and offline

BIGWORDS.PAGE can be installed as an app from the browser: Install in Chrome or Edge, or Share → Add to Home Screen on iPhone and iPad. The app opens on the editor, fullscreen where the device allows it.

After the first visit, the site keeps a copy of itself, so displays, the editor and these docs work without a connection, whether installed or in a browser tab. Images from other sites (img) only show while online. When you're online, pages always load the latest version. Browsers can clear the copy for a site you haven't used in a while, especially in a tab; an installed app keeps it longer.

Privacy

The message and settings live only in the URL fragment, which browsers do not send to servers. BIGWORDS.PAGE's own code adds no analytics, cookies or tracking. A site that hosts it may add analytics of its own: check that site's notes, which may follow at the end of this page, or its privacy policy.

Self-hosting

The build is a folder of static files. Any static host works if it serves index.html for /, editor.html for /editor, docs.html for /docs, and 404.html with status 404 for any other path. Set SITE_URL to your own origin when building (for example SITE_URL=https://signs.example.com npm run build) to add canonical URLs, social cards and a sitemap. A Docker image based on Caddy is included in the repository:

docker compose up -d --build

The container listens on port 80 inside its network and publishes no ports by default. Put it behind your reverse proxy, which handles TLS.