Features Pricing Build Docs Demos About Register or sign in
Before you start

Viewing the page you built

You have an HTML file with panes in it. You double-click it, the page opens, and every pane reports an error. Nothing is wrong with your page, and nothing is wrong with your key — the browser has not let the requests leave. This page explains why, and fixes it in one command.

What you will see

Two symptoms, and they arrive together.

In the page itself, each pane draws its frame and then says:

In the pane

This page was opened as a local file, so the browser blocks its requests to the LightPane API. Serve it over http:// instead — a local web server is enough.

And in the browser's developer tools, if you look, something about CORS or a NetworkError when attempting to fetch resource. That message sends most people off debugging their key, their account, or their markup. None of those are the problem.

The part that catches people out: this happens before you have a key, too. A pane with no access key shows mock data, and mock data also comes from the API — so a brand-new page you have not connected to anything still looks broken when you open it from disk. Serve it properly and the same file fills with example data immediately, no account required.

What CORS is, and why LightPane relies on it

Browsers treat a website's address as a boundary. A page served from one address is not allowed to quietly read data from another, unless that other address says it is allowed. Without that rule, any page you opened could read your webmail in the background, using your own logged-in session to do it.

The rule has a name — Cross-Origin Resource Sharing, CORS — and the important thing about it is where it is enforced. It is the browser's rule, applied in the browser, before the request leaves your machine. It is not a setting on our side that we could switch off for you, and it is not something your page can opt out of.

What LightPane does with it is deliberately permissive. Your dashboard lives on your address, not ours — an intranet page, a status site, a file on a laptop — so our data API says yes to every address. The access key in your page is the credential; no cookie, no login, no session is involved, so there is nothing for another site to borrow. That is why a page on your own domain works, and why http://localhost works just as well.

The one thing it cannot say yes to is no address at all. A file opened by double-clicking it has no website address — the browser sends its origin as the literal word null, and there is nothing there to permit. So the fix is not to change a setting. It is to give your page an address, and that is all "serve it locally" means.

Where we are strict

There is one place LightPane does restrict addresses: requests from the signed-in console at app.lightpane.io, which carry a session cookie rather than an access key. Those are limited to our own addresses, because a cookie can be borrowed by another site. Your page does not use that path, and does not need to.

On a Mac

Three steps, and you only need the first one once.

  1. Open Terminal. Press ⌘ and Space together, type terminal, and press Enter. A window with a text prompt appears. It is also in Applications → Utilities if you prefer to click.
  2. Point it at your folder. Type cd and a space, then drag the folder containing your HTML file from Finder onto the Terminal window — it fills in the path for you. Press Enter.
  3. Start the server. Type this and press Enter:
python3 -m http.server 8000

Now open http://localhost:8000/ in your browser. If your file is not called index.html, add its name — http://localhost:8000/dashboard.html.

Leave the Terminal window open while you work; the server runs for as long as it is there. Edit your file, reload the browser, and you see the change. When you are finished, press Control and C in the Terminal window to stop it.

If macOS offers to install developer tools the first time you run that command, accept. Python comes with the Mac but the command-line tools around it are a separate one-off download. If you would rather not, use the no-terminal option below.

On Windows

There is a shortcut here worth knowing, which saves typing a path.

  1. Open the folder containing your HTML file in File Explorer.
  2. Click in the address bar at the top — the strip showing the folder name — so the path becomes editable. Type cmd over it and press Enter. A command prompt opens, already pointed at that folder.
  3. Start the server:
py -m http.server 8000

Then open http://localhost:8000/, adding your filename if it is not index.html. Press Control and C in the command prompt to stop it.

If py is not recognised, try python -m http.server 8000. If that opens the Microsoft Store instead of running anything, Python is not installed on this machine — install it from the Store, or use the no-terminal option below.

On Linux

Open a terminal — Control Alt T on most desktops, or search the applications menu for "terminal" — then change to your folder and start the server:

cd ~/path/to/your/folder
python3 -m http.server 8000

Open http://localhost:8000/, and Control C to stop. Python 3 is present on every current distribution; if it somehow is not, your package manager has it as python3.

Without a terminal

If you are editing the page in Visual Studio Code — a free editor on all three platforms — you do not need a terminal at all. Install the Live Server extension from the Extensions panel, then right-click your HTML file and choose Open with Live Server. It serves the folder and opens a browser for you, and reloads the page every time you save.

One difference worth noting: Live Server picks its own address, usually http://127.0.0.1:5500 rather than port 8000. That only matters if your access key names the addresses it will accept — see below.

If you already have Node.js installed, npx http-server -p 8000 is the equivalent one-liner.

Checking it on a phone or tablet

You cannot realistically run a web server on a phone or an iPad, and you do not need to. But looking at the page on a real phone is worth doing before you call it finished, because panes respond to the width of the container they are placed in and a narrow screen is where a layout gives itself away. Size and resize behaviour covers what to expect.

With the server already running on your computer, and the phone on the same Wi-Fi, open http://your-computer:8000/ on the phone, where your-computer is its address on the local network:

PlatformFind the address with
macOS ipconfig getifaddr en0 — or System Settings → Network → Wi-Fi → Details
Windows ipconfig, and read the IPv4 Address line
Linux hostname -I

It will look something like http://192.168.1.42:8000/.

Only on a network you trust

A local server like this has no password, and while it is running anyone else on the same network can open the folder you are serving — including your HTML file, which has your access key in it. That is fine for a few minutes on your own home or office Wi-Fi. It is not fine on café, conference or hotel Wi-Fi. Stop the server when you have finished looking.

If your access key names a site

An access key can be restricted to the addresses it will work from, which is a good idea for a key that ends up in a published page. If you have done that, a key restricted to https://dash.example.com will be refused at http://localhost:8000 — and this looks different from the problem at the top of this page. The request leaves, and comes back denied, rather than being blocked before it goes.

Two ways round it, both fine:

  • Add http://localhost:8000 as a second allowed address on the key while you are building. Keys allow several.
  • Leave the key unrestricted until the page is hosted, then restrict it to where it ended up.

The matching is exact, which is the part that costs people an afternoon. All of these are different addresses, and only the one you list will work:

Written asResult
http://localhost:8000 Correct. The scheme and the port are both part of the address.
localhost:8000 Refused when you save it — an address needs its http://.
http://localhost A different address from the same name on port 8000. Will not match.
https://example.com for dash.example.com Will not match. A subdomain is never covered by its parent; list each one.

Access keys and their allowed addresses are managed in the console, under Access keys.

Putting it somewhere permanent

When the page is ready, it is plain files — your HTML, your CSS, and one script tag pointing at lightpane.io. There is no build step and no server-side code, so anything that can serve a static file will host it. This is not a hosting guide, but to narrow the choice:

  • Where your other internal pages live. Usually the right answer, and the least work — an existing web server, an intranet, a SharePoint document library, a shared drive served over HTTP.
  • S3 and CloudFront, if you are already in AWS. A bucket of static files behind a distribution, which is how lightpane.io itself is served.
  • GitHub Pages, if the page lives in a repository anyway. Commit it and it is published.
  • Netlify, Cloudflare Pages or similar, if you want a URL in a couple of minutes with no infrastructure to own.

Two things to get right wherever it goes. Serve it over https, which every option above does by default. And remember that the access key is readable by anyone who can open the page and view its source — that is unavoidable for a page that fetches its own data, so host the page where you would host an internal page, and restrict the key to that address.

A pane is read-only by design, so a key cannot change anything in your cloud account. But it can read what it has been granted, and a published page publishes that.