# Local vs hosted .trex manifests

> Keep two manifests that differ by one line: localhost for dev, HTTPS for production. Why Tableau demands HTTPS, and how ext-host rewrites the URL.

Canonical: https://ext.tableauops.com/knowledge/local-vs-hosted-manifest
Updated: 2026-09-18
Author: Eric Summers


The only line in a `.trex` that does real work is the `<source-location><url>`. Local development and production want different values there, and the cleanest way to manage that is to keep two manifest files that differ by exactly that one line. The rest of the file is identical.

## Two files, one line apart

Name them `manifest.local.trex` and `manifest.hosted.trex`. The local one points Tableau at your dev server:

```xml
<source-location>
  <url>http://localhost:8765/bullet/index.html</url>
</source-location>
```

The hosted one points at your production HTTPS host:

```xml
<source-location>
  <!-- Replace YOURNAME/REPO with your GitHub Pages path. Must be HTTPS, not localhost. -->
  <url>https://YOURNAME.github.io/REPO/bullet/index.html</url>
</source-location>
```

Everything else, the encodings, the author block, the min-api-version, is the same in both. Keeping them as two named files means you never sideload the localhost manifest into a workbook you are about to share, which is the classic "works on my machine, blank for everyone else" bug.

## Tableau requires HTTPS, with localhost as the only exception

Tableau will not load a production extension over plain `http`, and a self-signed certificate fails too. The one exception is `http://localhost:<port>`, which Tableau Desktop allows for local development. That exception is exactly why an extension works on your machine and breaks the moment it is published: the localhost URL that Desktop happily loads is unreachable from anyone else's Tableau, and on Server or Cloud the URL must also be on the site's extension safe list.

So the local manifest is a Desktop-only convenience, and the hosted manifest is the one you actually distribute. Real certificates are free, so there is no reason to try to serve production over anything but HTTPS.

## Serve local files over HTTP, never file://

The local manifest points at a running static server, not at a file on disk. Serve your extension folder with any static server on your project's port (roll a fixed, non-default port per project and keep it overridable), and load the manifest against `http://localhost:<port>/...`. Opening the HTML via `file://` will not work: the Extensions API and relative asset loading both assume an HTTP origin.

## How ext-host rewrites the source location

When you host on ext-host, you do not hand-edit the URL between environments at all. You upload the extension's files and the host generates the `.trex` for you, synthesising the `<source-location>` to point at the copy it serves. When it provisions a copy from your `manifest.hosted.trex`, it rewrites `<source-location>` to the URL that copy lives at, and it injects any shared library files the extension needs. A single LOCAL switch on the extension flips the same stable hosted URL between redirecting Tableau to your dev server and serving the uploaded files, so the workbook and the `.trex` never change while you iterate. See [hosting a Tableau extension](/knowledge/hosting-a-tableau-extension) for the URL spaces that URL can take.

## FAQ

### Why does my extension work on Desktop but is blank when shared?

The shared `.trex` almost certainly still points at `http://localhost`. Desktop allows localhost as a development exception, but no one else's Tableau can reach your machine. Distribute the hosted manifest that points at an HTTPS URL.

### Can I use a self-signed certificate for the hosted URL?

No. Tableau rejects self-signed certificates for production extensions just as it rejects plain `http`. Use a real certificate; they are free. Only `http://localhost` is exempt, and only in Desktop.

### Do I have to keep two files by hand?

Not if you host on ext-host. It generates the `.trex` and rewrites `<source-location>` to the hosted copy, and the LOCAL switch flips between your dev server and the uploaded files without changing the workbook or the manifest. Hand-kept `manifest.local.trex` / `manifest.hosted.trex` is the pattern for self-hosting or GitHub Pages.

### If I change the URL, do I reload or re-add?

Re-add. The `<source-location>` lives in the manifest, and manifest changes never hot-reload. Reload only refreshes HTML, JS, and CSS. Any `.trex` edit needs a full remove and re-add in Tableau.


---
Try it live: Host an extension — https://ext.tableauops.com/login
