FestivalLuts is a free catalogue. Anyone signed in can publish a .cube or a Lightroom .xmp, it goes live immediately, and it stays free to download with no account and no email gate on the other side.
This page is the part nobody writes down: exactly which checks your file has to pass, why each one exists, and the export decisions that separate a LUT people keep from one they delete after the first clip.
What happens when you press upload
There is no approval queue. status is set to approved at the moment the row is written, so your page exists the second the upload finishes. Moderation here is reactive rather than gatekeeping — a LUT can be removed, an account banned, an IP banned — but nothing sits waiting for a human to look at it.
That has one consequence worth stating plainly: the checks below are the only thing standing between a broken file and a live page, so they are stricter than they would be if a person reviewed every upload.
| Limit | Value |
|---|---|
| Accepted extensions | .cube, .3dl, .look, .mga, .csp, .xmp |
| Parsed in depth | .cube and .xmp only |
| Maximum file size | 50 MB |
| Uploads per hour | 10 |
| Title | up to 100 characters |
| Description | up to 500 characters |
| Tags | up to 15, each up to 40 characters |
Only .cube and .xmp are read. The other four extensions are accepted and stored so a pack stays intact, but nothing here can parse them, so those files get no measured section on their page.
Every check a .cube has to pass
Each of these rejects the upload with a specific reason rather than a generic failure.
- It must be a 3D LUT. A 1D LUT — a per-channel curve with no
LUT_3D_SIZEline — is refused. A 1D curve cannot hold a hue shift, which is most of what a look is. - It must declare
LUT_3D_SIZE. Without it the file is not a valid 3D LUT, whatever the extension says. - The point count must match the declared size. A file that claims 33×33×33 must carry 35,937 rows. A mismatch means a truncated export, and truncated exports interpolate to garbage rather than failing loudly.
- Between 8×8×8 and 65×65×65. Below 8 there are not enough points to hold a look. Above 65 is past what Resolve and Lattice export, and a 65³ file is already 274,625 rows of text.
- It cannot be an identity transform. A LUT that returns every colour unchanged applies nothing. This catches the commonest broken export: a node tree that was bypassed when the LUT was generated.
- It cannot map everything to one colour. A constant output flattens the image to a single flat frame, which is the other common signature of a bad bake.
If your file is rejected, the message says which of these it failed and what to change.
Choosing a lattice size
This is the decision that most changes how your LUT behaves on someone else's footage, and it is not a matter of bigger being better.
A LUT is a function sampled onto a grid, with interpolation filling the gaps. How much the grid costs you depends entirely on how curved the function is between the points.
Baking this site's own S-Log3 → Rec.709 conversion at three sizes and comparing each against the analytic result along the neutral ramp, in 8-bit code values:
| Lattice | Mean error | Worst error |
|---|---|---|
| 17×17×17 | 1.98 | 5.74 |
| 33×33×33 | 0.44 | 3.30 |
| 65×65×65 | 0.11 | 0.89 |
Read that as two separate conclusions rather than one.
A log conversion needs 33³ or better. At 17³ a conversion is nearly two code values off on average and almost six at its worst — visible banding in a gradient, and a middle grey that lands in the wrong place. That curve bends hard, and a coarse grid cuts the corners.
A creative look does not. A look applied after a conversion is a comparatively gentle function, and 17³ carries it with room to spare while being roughly eight times smaller. Shipping a 65³ creative look is 7 MB where 100 KB would have been identical to the eye.
So: 17³ for looks, 33³ for conversions, 65³ only when you are delivering 10-bit and the frame is mostly gradient. That is the same position the catalogue itself takes, and the lattice measurements show the working for eight camera formats rather than one.
Export settings that matter
Bake the conversion or bake the look — not both, unless you say so. A creative look baked on top of a log conversion only works for people shooting that exact log format, and it silently double-converts for anyone who already has a CST in their node tree. If you do ship a combined LUT, put it in the title.
Check your export is not an identity. Bypassing a node before exporting produces a valid file that does nothing. The upload will catch it, but catching it here means you already wasted the render.
Name the log format, not the camera. A conversion is keyed to a curve and a gamut, not a body — one S-Log3 conversion is correct for every Sony recording S-Log3 in S-Gamut3.Cine. Naming a camera model implies a per-body LUT that does not need to exist, and it hides your LUT from people with a different body and the same format.
Do not name a festival or a brand in the title. Trademarks in a product title are a fight not worth having. Every LUT here that once named a real event was retitled for that reason, and the old URLs now redirect.
What the site does with your file after that
Your page is generated from the file itself, not from your description. The .cube is parsed and pushed through a set of probes, and the page reports what came back: how the tone curve moves through the midtones, where the black point lands, how far saturation travels, whether neutrals pick up a cast at shadow, mid or highlight, and whether any channel clips at the top.
For an .xmp, the develop settings are read directly and listed in the panels Lightroom puts them in — the tone sliders, the presence sliders, which of the eight colour-mixer bands moved, and whether the preset sets a white balance or hands that back to the camera.
None of that is written by hand, which means it cannot flatter your LUT and it cannot go stale. It also means a well-made file gets a page that describes it accurately, which is the whole reason to bother with the export settings above.
Sources
Every limit and check on this page is read from the code that enforces it: middleware/lutfile.js for the .cube validation, the 8 / 65 lattice bounds and the identity and constant-output tests; routes/luts.js for the accepted extension list, the title, description and tag caps, and the immediate approved status; server.js for the upload rate limit; and the project .env for the 50 MB file ceiling.
The lattice table was produced by baking toRec709('Sony S-Log3', …) from public/js/color-transforms.js onto 17³, 33³ and 65³ grids, sampling each with the trilinear interpolator in middleware/lutprofile.js — the same one the site uses to measure every published LUT — and comparing against evaluating the function directly. The error is the largest of the three channel differences, times 255, across a 41-step neutral ramp.