apps.header.allAppsCount
Typr
apps.detail.types.app from max.prime's Repository
apps.detail.sections.overview
Readme
View on GitHubSelf-host Typr
Typr's self-hosted image serves the browser application; it is not a project server. Projects, settings, browser Git data, and sync bindings remain in each browser's IndexedDB and OPFS by default. The container has no project or appdata volume, and replacing it does not migrate or delete browser data.
Self-hosted Typr and Typr Companion are separate images and repositories:
ghcr.io/max-prime-math/typrserves the Typr PWA.ghcr.io/max-prime-math/typr-serveris the optional native Companion.
Both are unauthenticated trusted-environment services. Run them only on a trusted machine, trusted LAN, or private VPN. Never expose either service to the public Internet. A reverse proxy and TLS improve transport and browser compatibility; they do not add application authentication or make public exposure safe. Any optional client-side sign-in screen is a convenience layer, not a network security boundary.
Choose an image
The full and lite variants contain the same application files and disable Google Drive at build time. Browser-local storage remains the default in both.
| Variant | Moving tag | Exact tag | Compiler assets | Network needed to load the pinned compiler core |
|---|---|---|---|---|
| Full | latest (latest-full is explicit) |
X.Y.Z or X.Y.Z-full |
Exact release bundled in the image | No |
| Lite, R2 | latest-lite |
X.Y.Z-lite |
Exact release proxied from assets.typr.ca through the Typr origin |
Yes |
| Lite, local | latest-lite |
X.Y.Z-lite |
Exact release mounted read-only at /compiler-assets |
No |
For reproducible deployment and rollback, replace moving tags with the complete
X.Y.Z and X.Y.Z-lite tags or a registry digest. Bare tags always select the
full image. X.Y, X, and latest are moving full aliases; their -full and
-lite forms make the variant explicit. sha-<12 characters> is an immutable
full-image diagnostic alias and the suffixed SHA aliases select an explicit
variant. Do not mix an asset directory from one release with another image:
lite/local validates the manifest, exact file set, sizes, and SHA-256 hashes
before it becomes healthy.
"Full" means the pinned Typst compiler and BusyTeX bundles are included. Some user-selected packages, external images, links, GitHub operations, and optional services can still require a network connection.
Docker Compose
The default compose.yaml runs the full image on loopback:
docker compose up -d
curl -fsS http://127.0.0.1:8080/healthz
Open http://127.0.0.1:8080. The Compose file uses a non-root image, read-only
root filesystem, bounded no-exec tmpfs, dropped capabilities, no-new-privileges,
and PID/memory/CPU limits.
Run the lite image with its pinned R2 source by selecting it in the same Compose file:
TYPR_IMAGE=ghcr.io/max-prime-math/typr:X.Y.Z-lite docker compose up -d
To run the same lite image with a local compiler release, first download and
extract the exact release directory described by that image's release notes.
Put both persistent selections in .env so every later Compose command uses the
same variant and mount:
TYPR_IMAGE=ghcr.io/max-prime-math/typr:X.Y.Z-lite
TYPR_COMPILER_ASSETS_DIR=/srv/typr/compiler-assets
docker compose -f compose.yaml -f compose.local-assets.yaml up -d
One way to obtain the exact pack without broad host mounts is to copy it from the matching full image. Use the same complete version for both image variants:
mkdir -p /srv/typr/compiler-assets
docker create --name typr-asset-source ghcr.io/max-prime-math/typr:X.Y.Z
docker cp typr-asset-source:/compiler-assets/. /srv/typr/compiler-assets
docker rm typr-asset-source
The directory must contain manifest.json, core/busytex/..., and
typst/typst_ts_web_compiler_bg.wasm at its root. It must be mounted read-only;
the container rejects writable or nested writable mounts, symlinks, special
files, missing files, extra files, wrong sizes, and wrong hashes.
Set TYPR_IMAGE to an exact image tag or digest before a Compose command to pin
or roll back. Put the selection in a local .env file so every later Compose
command keeps the same variant:
TYPR_IMAGE=ghcr.io/max-prime-math/typr:X.Y.Z-lite
Update that selected variant with:
docker compose pull
docker compose up -d
Use the same -f arguments for lite/local. There is no in-container updater.
Export project backups before an update even though replacing the container
does not itself touch browser data.
Network and browser-origin rules
The Compose examples bind 127.0.0.1 by default. This is the safest single-host
configuration, and browsers treat loopback HTTP as a secure-context exception.
To listen on a LAN interface, set TYPR_BIND_ADDRESS deliberately—for example,
TYPR_BIND_ADDRESS=192.168.1.20—and enforce trusted-LAN/VPN access with the host
firewall. Do not bind a publicly reachable interface.
Plain HTTP on a non-loopback LAN address is not a secure context. Normal editing and IndexedDB storage can still work, but service-worker installation/offline updates, File System Access/local-folder sync, and other secure-context features may be unavailable. Trusted HTTPS is required for the full cross-device PWA experience.
Browser storage belongs to the exact origin: scheme, hostname, and port. Moving
from http://nas:8080 to https://typr.example, changing a port, or changing a
hostname creates a different storage silo. Export a Typr project backup from the
old origin before changing the URL, then import it at the new origin. Clearing
site data can remove the browser's only project copy.
An HTTPS Typr page cannot call a plain HTTP/WS Companion because the browser blocks mixed content. For cross-device Companion use, give both services trusted HTTPS endpoints restricted to the LAN/VPN, forward Companion WebSocket upgrades, and add the exact Typr origin to the Companion allowlist. HTTPS is not permission to expose either endpoint publicly.
Private HTTPS with Tailscale on Unraid
On Unraid, use the official Tailscale plugin on the host and Tailscale Serve as the private HTTPS reverse proxy. Keep the per-container Use Tailscale switch off for both Typr images: Unraid's injected container hook needs a different privilege and mount model than these non-root, read-only containers.
For example, if Typr is published on host port 7080, run this from an Unraid
terminal:
tailscale serve --bg --https=8444 http://127.0.0.1:7080
tailscale serve status
Open the resulting https://UNRAID-NAME.TAILNET.ts.net:8444 URL only from a
device joined to the authorized tailnet. Use a different private HTTPS port for
Companion as documented in its Unraid guide. Changing from the LAN URL to the
Tailscale URL creates a new browser-storage origin, so export projects from the
old origin before moving. Tailscale Serve stays within the tailnet;
Funnel must remain disabled because these services must never be public.
Optional Typr Companion and mapped workspace
Typr works without Companion. A fresh self-hosted browser profile makes no Companion or mapped-workspace request. To opt in, install Companion from its separate repository, enter its URL under Settings → Editor → Typr Companion, and apply it.
The optional host workspace is mounted into the Companion container—not the Typr web container. When an administrator enables that single scoped directory, a user may explicitly link the selected browser-local project under Settings → Sync and run a manual synchronization. Unlinking never deletes server files, and browser autosave continues if Companion is unavailable.
Unraid
templates/typr.xml is the Typr web template. It uses
the full image and needs only port 8080; project files are not stored in Unraid
appdata. To use lite, manually select its Repository tag and then choose R2 mode
or an exact read-only compiler pack in the advanced fields; never map project
files or a broad share there. templates/typr-companion.xml
is the canonical Community Applications template for the independently maintained
Typr Companion; install it when
native LaTeX or a mapped workspace is wanted. Keeping both templates in this
repository groups both apps under one Community Applications repository profile.
For private Tailscale access, leave each container's Use Tailscale switch off
and follow the host-level Serve setup above.
Before Community Applications submission, validate both templates on a real
Unraid host, including install, health, browser access, update, rollback, and
removal. Put a maintained support destination in each template's Support
field; an optional profile Forum field may point to the same destination. Then run
npm run test:unraid -- --submission-ready plus the portal's Validate and Scan
actions. Portal approval makes them Community Applications listings; the same
files remain usable as direct user templates before approval.
Verify and remove
docker compose ps
curl -fsS http://127.0.0.1:8080/healthz
docker compose logs typr
Remove the container with docker compose down, using the same -f arguments
used to start it. This removes no browser projects. To remove a browser project
copy, use Typr's project controls or the browser's site-data controls only after
exporting any required backup.
apps.marketingCta.appInstallTitle
apps.marketingCta.appInstallDescription
apps.detail.sections.requirements
apps.detail.sections.categories
apps.detail.sections.related
apps.detail.related.exploreCategories
apps.detail.related.exploreAllapps.detail.sections.links
apps.detail.sections.details
ghcr.io/max-prime-math/typr:latestapps.detail.sections.runtime
- apps.detail.details.webui
http://[IP]:[PORT:8080]/- apps.detail.details.network
bridge- apps.detail.details.shell
sh- apps.detail.details.privileged
- false
- apps.detail.details.extraParams
--restart=unless-stopped --user=101:101 --read-only --tmpfs=/tmp:rw,nosuid,nodev,noexec,size=33554432 --cap-drop=ALL --security-opt=no-new-privileges:true --pids-limit=64 --memory=256m --memory-swap=256m --cpus=1
apps.detail.sections.configuration
Host port for the Typr web interface. Container port must remain 8080.
- apps.detail.config.target
- 8080
- apps.detail.config.default
- 8080
- apps.detail.config.value
- 8080
The full image uses local. For a lite image, use r2 without a mount or local with the exact matching read-only compiler pack.
- apps.detail.config.target
- TYPR_COMPILER_ASSETS_MODE
- apps.detail.config.default
- local
- apps.detail.config.value
- local
Optional exact compiler-release directory for lite/local only. Never map /, /mnt, /mnt/user, an appdata root, project files, or the Docker socket.
- apps.detail.config.target
- /compiler-assets