The linq Client UI is a static Next.js export — plain HTML, CSS, and JavaScript with no server-side runtime. It connects to a linq API server at runtime through a form in the browser, so no server URL is compiled into the build. One deployed UI can administer any number of linq instances, and you can add or switch servers without touching the deployment. Because the UI is purely a client, it can live anywhere: bundled into the same container as the API, or on a completely separate host.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/org-quicko/linq/llms.txt
Use this file to discover all available pages before exploring further.
Two deployment shapes
- Served by linq
- Standalone (any static host)
In the combined shape, the linq server builds and serves the Client UI from the same process. This is what the published Docker image and all eight main Compose stacks use by default.Build command (from the repo root):This writes
apps/client/out, compiled for the path set in LINQ_CLIENT_BASE_PATH (default /home). The server mounts this directory and serves it at that path on every host it answers.How the server mounts it:The static export is served by the server’s mountAdmin handler. With LINQ_APP_HOST unset, the UI is available at http://<any-host>:<port>/home/ (or whatever LINQ_CLIENT_BASE_PATH is set to). With LINQ_APP_HOST set, the handler restricts the UI to that one host only, letting the base path be / without reserving any slugs on shortening domains.In Docker, the Compose examples pass LINQ_CLIENT_BASE_PATH to the build stage. Because the path is baked into the static files during docker build, changing it requires a rebuild:The combined image build uses two stages: the first builds
apps/client/out; the second copies that output into the runtime image alongside the server sources. The Bun runtime executes the server directly — there is no server bundle step.Adding a server at runtime
Regardless of which shape you deploy, the UI opens with a form to add a linq server. No configuration file is needed — everything is stored in the browser’slocalStorage.
| Field | What to enter |
|---|---|
| Name | Any label, e.g. production or staging |
| Server URL | The base URL of your linq API, e.g. https://linq.example.com |
| API key | A linq_… key from your instance’s Keys page or server logs |
Docker images
Three Dockerfiles cover the container shapes for the Client UI:Dockerfile (published image)
docker/dockerfiles/Dockerfile — builds the API, redirects, and Client UI in one image. The UI is mounted at LINQ_CLIENT_BASE_PATH (default /, requires LINQ_APP_HOST at runtime). This is ghcr.io/org-quicko/linq / labsatquicko/linq.Dockerfile.server
docker/examples/dockerfiles/Dockerfile.server — API and redirects only, no Client UI build stage. The server returns 404 on the configured Client UI path and continues serving the API and redirects. Used by 09-server-only.yml.Dockerfile.client
docker/examples/dockerfiles/Dockerfile.client — standalone Client UI only. Runs serve-static.ts under plain Bun; no nginx, no Postgres, no environment variables needed. Used by 10-client-only.yml.10-client-only.yml
docker/examples/docker-compose/10-client-only.yml — Compose file for the standalone client container. The client’s published host port is ${LINQ_CLIENT_PORT:-3001}. Works standalone or layered on top of a server Compose file.LINQ_PORT=8080 and LINQ_CLIENT_PORT=8081 in .env, the API is on port 8080 and the standalone UI is on port 8081. Both containers listen on 3000 internally — each has its own network namespace, so there is no conflict.
LINQ_APP_HOST mode
WhenLINQ_APP_HOST is set, the UI answers only on that specific host, at /. Every other host continues serving short links normally. This lets you give the UI a clean root URL (https://linq.example.com/) while keeping https://link.example.com/<slug> for short links — from a single process and container.
linq image (built with LINQ_CLIENT_BASE_PATH=/) — or any image rebuilt with that same build arg. The app host must differ from LINQ_DEFAULT_DOMAIN and from every registered domain; linq refuses to start otherwise.
Behind a reverse proxy, route both hostnames to the same linq port and preserve the Host header — that is how linq distinguishes them. With Caddy sync enabled, linq pushes the app host’s route at boot automatically; see Automatic HTTPS with Caddy.
Archive any existing domain row whose host equals the intended
LINQ_APP_HOST before setting the variable. The UI claims every path on that host, so any links previously registered under it will stop resolving.Cross-origin API calls
The linq server enables CORS on all/api/* routes, accepting calls from any origin. The API key is the only thing that authorises a request; no cookie is ever involved. This means:
- A standalone UI on
https://app.example.comcan call an API onhttps://linq.example.comwithout any proxy. - The development UI on port 3001 calls the API on port 3000 across origins — exactly as a deployed standalone UI would.
- If you see requests fail with an opaque network error, suspect CORS configuration on the server, not a missing proxy.
No API URL is compiled into either UI shape. The combined shape compiles only its base path into the static files; the standalone shape always uses
/. Adding a server URL is a runtime step done in the browser.