A .json Lottie is not a page — hand it to a client and they get a wall of numbers. What it takes to turn one into something that opens in any browser, and why the answer is smaller than the tooling suggests.
The animation is finished. It exports cleanly, it is small, it loops the way you wanted. You send the file to the client and get back: this didn't open, it's just code?
Nothing is broken. You sent them a description of an animation rather than the animation.
A .json Lottie is a set of instructions — layers, shapes, keyframes, easing — written for a player to interpret. That design is the reason the format is good: it stays sharp at any size, it is a fraction of the weight of a video, it can sit on a transparent background, and a developer can drop the same file straight into an app.
It also means the file is only half of a viewing experience. The other half is the player, and the player is not in the file.
Your tools have one built in, which is why the problem is invisible from your side. After Effects with Bodymovin previews it. LottieFiles previews it. Your handoff tool previews it. Everywhere you look at it, something is quietly supplying the missing half. Your client's laptop is the first place with no player in the room.
Give the file a player, and give the pair an address.
Concretely, one HTML file that sits next to the .json:
<!doctype html>
<meta charset="utf-8">
<title>Loading sequence — v3</title>
<script src="https://unpkg.com/@lottiefiles/dotlottie-wc@0.9.27/dist/index.js" type="module"></script>
<body style="margin:0;display:grid;place-items:center;min-height:100vh;background:#111">
<dotlottie-wc src="./animation.json" autoplay loop
style="width:480px;height:480px"></dotlottie-wc>
</body>
That is the whole thing. Put it in a folder with animation.json, zip the folder, upload the zip. The ./animation.json reference resolves because both files travel together and get served from the same address — relative paths only survive if the files that satisfy them go along.
Two details worth knowing before you hit a wall with them:
The link is the deliverable, but a review goes badly without three lines of context, because the person opening it does not know what they are meant to be checking:
If the feedback is going to be granular, letting them comment on the page itself beats a thread of screenshots, mostly because the comment stays attached to the thing it is about.
Worth being straight about, because the wrap-it-in-a-page approach is not always the right one:
Reach for the real Lottie when the review is about the asset itself — does it hold up at the size it will actually run at, is the transparency clean, does the loop point work, is this the file a developer can ship. A video cannot answer any of those, because a video is a recording of one rendering at one size.
Unreleased brand work should not be publicly findable while it is still being argued about. Put the page at an unguessable address with a no-index tag, so it exists for the people you sent it to and nowhere else. Add a password if it is under embargo, and an expiry if it is tied to a launch date that will pass.
And keep the address stable across revisions. Motion work goes through versions — v3 becomes v4 becomes v4-final — and if every revision mints a new URL, the client ends up reviewing v3 while telling you they are looking at the latest. Replacing the file behind the same link removes that entire category of confusion.
The animation was never the problem. The file was always correct — it just arrived without the thing that draws it.
Ten lines of HTML and a zip turn a description of an animation back into an animation, at an address anyone can open, on any device, with nothing installed. That is a smaller fix than the amount of tooling built around this problem suggests.
Client-side encryption tools turn your page into an encrypted file, so the protection and the artifact are the same object — every edit means re-running the tool and re-uploading. What that actually costs, the salt setting that decides whether your old share links survive, and when a hosted password is the better trade.
Running the studio out of one folder per client is a good structure for making the work. It stops at the point where the client has to open it — a private repo needs a GitHub account, and Pages built from one is public by default. What the handover step actually needs, and how to add it without breaking the folder.
You need one page live for a webinar, a resource hub, or a campaign — not a whole website. Here's how to stand up that page from a single HTML file: a private, no-index link in seconds, with expiry, custom domain, and an honest line on where registration capture belongs.
miinideck turns a single HTML file into an unguessable link with optional password and expiry. Default-private, never indexed.