Skip to content
Gauge

ax-check.com

FileDeck

getfiledeck.com

ax-check.com

Checked 4 November 2026

B

65/100

Agents haven’t verified setup

Docs and pricing are clear, but agents disagree on what FileDeck costs

Quickstart, install steps, and API/MCP/CLI docs all check out. Yet sessions split: one read Free/Pro/AI tiers, two assumed a free MIT-licensed library instead.

3 fixes to start with

Concrete changes, backed by what we found.

Onboarding

Resolve the blocker that stopped agent setup.

Agents cannot progress through onboarding without human help. Provide an agent-accessible path through authentication and setup.

Docs

Return Markdown when clients request text/markdown.

Homepage returned text/html for a text/markdown request; no Markdown representation offered.

Docs

Add links to your product documentation and quickstart in /llms.txt.

/llms.txt fetch failed (network error), so no documentation index is available.

Recorded coding sessions

Same task, 3 models, no getfiledeck.com account. Recorded 4 November 2026 on Pi.

3 recorded · 1m 29s

1m 29s · recorded

Session findings

Select a finding to see it in context.

piv0.84.2
modelQwen 3.8 Maxcwd/sandbox/repo
Help me build a simple example using FileDeck. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop.
Thinking…

Let me check the repository to understand what FileDeck is.

ls -la /sandbox/repo && cat /sandbox/repo/README* 2>/dev/null | head -100
total 16
total 16
drwxr-xr-x 3 root root 4096 Sep 18 08:00 .
drwxr-xr-x 7 root root 4096 Nov  4 20:13 ..
drwxr-xr-x 8 root root 4096 Sep 24 20:05 .git
-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore
find /sandbox/repo -maxdepth 2 -type f | head -50
/sandbox/repo/.gitignore
/sandbox/repo/.gitignore
/sandbox/repo/.git/COMMIT_EDITMSG
/sandbox/repo/.git/config
/sandbox/repo/.git/index
/sandbox/repo/.git/HEAD
/sandbox/repo/.git/description
Thinking…

The repository is empty except for .gitignore. There's no FileDeck documentation locally. Let me check git log and .gitignore for any hints.

cat /sandbox/repo/.gitignore; git -C /sandbox/repo log --oneline -5
# Keep generated and vendored files out of source diffs.
# Keep generated and vendored files out of source diffs.

# Logs / OS cruft
*.log
.DS_Store

# JavaScript / TypeScript
node_modules/
.next/
dist/
build/
coverage/

# Python
.venv/
venv/
__pycache__/
*.py[cod]
.pytest_cache/
*.egg-info/

# Rust
target/

# Go / PHP / Ruby vendored deps
vendor/
.bundle/

# Java / Kotlin / Scala
.gradle/

# .NET
bin/
obj/

# Elixir
_build/
deps/

# Dart / Flutter
.dart_tool/
9ebf5fb Initial workspace
Thinking…

The repository is essentially empty. "FileDeck" — no local docs. Is FileDeck an actual product? Probably fictional. Let me check whether there are SDK/API docs available online… probably no network access. Let me check whether pip/npm has a "filedeck" package, and whether the network is available.

pip index versions filedeck 2>&1 | head -3; npm view filedeck 2>&1 | head -5
ERROR: No matching distribution found for filedeck
ERROR: No matching distribution found for filedeck

[notice] A new release of pip is available: 26.2.1 -> 26.3

filedeck@0.3.1 | MIT | deps: none | versions: 4
A dependency-free attachment viewer for images, PDFs, video, audio, Excel and Word files. Driven by DOM attributes, no build step required.
https://vivekgami.github.io/filedeck/

curl -s -m 8 -o /dev/null -w "%{http_code}" https://pypi.org/simple/ ; echo; curl -s -m 8 -o /dev/null -w "%{http_code}" https://filedeck.io 2>&1; echo
200
200
000
Thinking…

Interesting — there's an npm package called filedeck 0.3.1: "a dependency-free attachment viewer." But the user said "use the hosted product via SDK or API" and is asking "how the pricing works." The npm package is a frontend library, not a hosted product. Hmm. Maybe the intended "FileDeck" is a hosted file-sharing product. Let me fetch the npm package details and the GitHub pages site to verify.

There is an npm package named filedeck. Let me inspect it to see what FileDeck actually is.

npm view filedeck --json 2>&1 | head -60
{
{
  "_id": "filedeck@0.3.1",
  "_rev": "4-0e6d4d3ace3316ddd4ca3307b5deaa4a",
  "name": "filedeck",
  "dist-tags": {
    "latest": "0.3.1"
  },
  "versions": [
    "0.1.0",
    "0.2.0",
    "0.3.0",
    "0.3.1"
  ],
  "time": {
    "created": "2026-09-16T09:08:31.733Z",
    "modified": "2026-10-23T12:17:45.240Z",
    "0.1.0": "2026-09-16T09:08:31.968Z",
    "0.2.0": "2026-10-04T09:15:38.693Z",
    "0.3.0": "2026-10-23T10:30:21.501Z",
    "0.3.1": "2026-10-23T12:17:45.034Z"
  },
  "bugs": {
    "url": "https://github.com/Vivekgami/filedeck/issues"
  },
  "author": "Vivek V Gami",
  "license": "MIT",
  "homepage": "https://vivekgami.github.io/filedeck/",
  "keywords": [
    "lightbox",
    "attachment",
    "viewer",
    "gallery",
    "pdf",
    "file-preview",
    "vanilla-js",
    "no-dependencies",
    "xlsx",
    "docx",
    "excel",
    "word",
    "spreadsheet-viewer",
    "document-viewer",
    "image-viewer",
    "pdf-viewer",
    "pinch-zoom",
    "modal"
  ],
  "repository": {
    "url": "git+https://github.com/Vivekgami/filedeck.git",
    "type": "git"
  },
  "description": "A dependency-free attachment viewer for images, PDFs, video, audio, Excel and Word files. Driven by DOM attributes, no build step required.",
  "maintainers": [
    "vivekgami <vivekgami.dev@gmail.com>"
  ],
  "readmeFilename": "README.md",
  "_contentLength": 33306,
  "dist": {
    "shasum": "ea81fecf67c3d492c9308be96b13cf31b81ab154",
    "tarball": "https://registry.npmjs.org/filedeck/-/filedeck-0.3.1.tgz",
curl -s -m 15 https://vivekgami.github.io/filedeck/ | head -150
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Filedeck — JavaScript lightbox for PDFs, Excel and Word files</title>
<meta name="description" content="Filedeck is a zero-dependency JavaScript lightbox for images, PDFs, video, audio, Excel and Word files. Add one attribute to the links you already have.">
<meta name="theme-color" content="#F1F1F0">
<link rel="canonical" href="https://vivekgami.github.io/filedeck/">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='16' fill='%23101014'/%3E%3Ctext x='32' y='42' font-family='ui-monospace,Consolas,monospace' font-size='28' font-weight='500' fill='%23fff' text-anchor='middle'%3Efd%3C/text%3E%3C/svg%3E">

<!-- Link previews: WhatsApp, Slack, LinkedIn, X, Discord. -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="Filedeck">
<meta property="og:url" content="https://vivekgami.github.io/filedeck/">
<meta property="og:title" content="Filedeck — your links open files now">
<meta property="og:description" content="A zero-dependency lightbox that took the rest of the office with it: photos, PDFs, video, audio, and the Excel and Word files nobody else previews.">
<meta property="og:image" content="https://vivekgami.github.io/filedeck/landing/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Filedeck — zero-dependency JavaScript lightbox for images, PDFs, video, audio, Excel and Word files">
<meta name="twitter:card" content="summary_large_image">

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "SoftwareSourceCode",
  "name": "Filedeck",
  "description": "A zero-dependency JavaScript lightbox for images, PDFs, video, audio, Excel and Word files.",
  "url": "https://vivekgami.github.io/filedeck/",
  "codeRepository": "https://github.com/Vivekgami/filedeck",
  "programmingLanguage": "JavaScript",
  "runtimePlatform": "Web browser",
  "license": "https://opensource.org/licenses/MIT",
  "author": { "@type": "Person", "name": "Vivek V Gami" }
}
</script>

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">

<!-- The library itself. src/ rather than dist/, because dist/ is gitignored and
     never reaches GitHub Pages; src/filedeck.js assigns window.Filedeck. -->
<link rel="stylesheet" href="src/filedeck.css">

<style>
/* ==========================================================================
   Filedeck landing page — page chrome only, none of it is the library.
   Tokens, copy and metrics come from designs/design_handoff_filedeck_landing.
   ========================================================================== */

:root {
  color-scheme: light;

  --ground:       #F1F1F0;
  --surface:      #FFFFFF;
  --ink:          #101014;
  --ink-muted:    #56565F;
  --ink-muted-2:  #63636D;
  --ink-muted-3:  #6E6E78;
  --ink-faint:    #8A8A93;
  --ink-faintest: #A9A9B2;
  --hairline:     #F0F0F2;
  --hairline-2:   #F4F4F6;
  --border:       #E6E6EA;
  --face:         #F3F4F8;
  --accent:       #4B4BE8;
  --accent-tint:  #D9DEFF;

  --dark:          #14141A;
  --dark-2:        #1A1A22;
  --dark-border:   #2E2E38;
  --dark-border-2: #33333D;
  --dark-hover:    #22222A;
  --dark-hover-2:  #26262E;

  --code:       #E7E7EC;
  --code-blue:  #9DB4FF;
  --code-green: #A9DFA0;
  --code-grey:  #74747F;
  --code-foot:  #A0A0AC;

  --green:  #1E7A4C;
  --red:    #D2443A;
  --amber:  #C77A12;
  --violet: #8B5CF6;
  --indigo: #3C4BB8;
  --orange: #E0721B;
  --blue:   #2563C9;
  --teal:   #0E8C8C;

  --ease: cubic-bezier(.22, .61, .36, 1);
  --sans: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, monospace;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  padding: clamp(6px, 1vw, 14px);
  background: var(--ground);
  color: var(--ink);
  font: 400 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--ink); }
a:hover { color: var(--accent); }
::selection { background: var(--accent-tint); color: var(--ink); }

@keyframes fdl-up    { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes fdl-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes fdl-menu  { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* -- reveal on scroll ---------------------------------------------------- */
[data-reveal] { transition: opacity 640ms var(--ease), transform 640ms var(--ease); }
[data-reveal].is-armed { opacity: 0; transform: translateY(18px); }
[data-reveal].is-armed.is-in { opacity: 1; transform: none; }

/* -- shells -------------------------------------------------------------- */
.fdl-panel {
  position: relative;
  background: var(--surface);
  border-radius: clamp(18px, 2.4vw, 30px);
  box-shadow: 0 1px 2px rgba(16,16,20,.05), 0 24px 60px rgba(16,16,20,.06);
  overflow: hidden;
  animation: fdl-up 620ms var(--ease) both;
}

/* -- nav ----------------------------------------------------------------- */
.fdl-nav {
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  padding: clamp(10px, 1.4vw, 14px) clamp(12px, 2vw, 20px);
  border-bottom: 1px solid var(--hairline);
}
.fdl-logo {
  display: flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: var(--ink);
  font: 700 19px/1 var(--sans);
  letter-spacing: -0.03em;
Thinking…

FileDeck is a zero-dependency open-source (MIT) JavaScript lightbox library for displaying attachments. It's not a hosted product — there's no API, no pricing, and probably no account either. The user's request is "use the hosted product via SDK or API" and "tell me how pricing works." But this is an MIT-licensed client-side library that's free and has no hosted service.

The user's guardrail: "If this product doesn't have an actionable developer workflow, say so clearly and stop." But a developer workflow does exist: install via npm, use via DOM attributes. It's not a hosted product/SDK/API — it's a library you embed. You could also build a simple sample HTML page that uses the library from a CDN (jsdelivr/unpkg) — that's lightweight and doesn't require a local service stack either. Does this count as "using the hosted product via SDK or API"? Not strictly, but the honest answer is: FileDeck is a free MIT-licensed browser library, there's no hosted product, no pricing, no API keys.

I think the right way to proceed is this: clearly state that FileDeck is not a hosted SaaS with pricing — it's a free MIT library — and that the closest thing to a "developer workflow" is embedding the script. I can build a simple sample (a static HTML page that uses filedeck via CDN). That's lightweight, requires no local service. That's useful and seems within the constraints. Building a static sample doesn't require starting a server (it can be verified with node, or just by creating the files).

Let me check the README to confirm usage (data attributes) and whether there's any mention of pricing or a hosted service. Fetching the README from npm.

FileDeck turns out to be an open-source npm library, not a hosted SaaS. Let me confirm by reading its README before deciding.

curl -s -m 15 https://registry.npmjs.org/filedeck/-/filedeck-0.3.1.tgz -o /tmp/filedeck.tgz && mkdir -p /tmp/filedeck && tar -xzf /tmp/filedeck.tgz -C /tmp/filedeck && ls /tmp/filedeck/package && head -120 /tmp/filedeck/package/README.md
LICENSE
LICENSE
README.md
dist
package.json
# Filedeck

A dependency-free attachment viewer for the web: images, PDFs, video, audio and
documents, in one overlay. No dependencies, no build step, no server payload —
it reads everything from the DOM it is already looking at.

Add one attribute to the links you already have, and they become a viewer.

**Live demo:** [vivekgami.github.io/filedeck](https://vivekgami.github.io/filedeck/) — click any file on the page.

---

## Install

**CDN — no build step, no npm:**

```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/filedeck@0.3/dist/filedeck.min.css">
<script src="https://cdn.jsdelivr.net/npm/filedeck@0.3/dist/filedeck.umd.min.js"></script>
<script>window.filedeck = new Filedeck();</script>
```

**Self-hosted** — copy `dist/filedeck.umd.min.js` and `dist/filedeck.min.css`
into your static folder and link them the same way. In a Django project:

```django
{% load static %}
<link rel="stylesheet" href="{% static 'css/filedeck.min.css' %}">
<script src="{% static 'js/filedeck.umd.min.js' %}"></script>
<script>window.filedeck = new Filedeck();</script>
```

**npm, with a bundler:**

```bash
npm install filedeck
```

```js
import Filedeck from 'filedeck';
import 'filedeck/filedeck.css';

const viewer = new Filedeck();
```

Filedeck builds its own markup and appends it to `<body>` on construction.
There is nothing to paste into your template — no container element, no icon
sprite, no font to load.

---

## Markup

Any element carrying `data-filedeck` becomes a trigger. The attribute's **value
is the group name** — triggers sharing a value page through each other with the
prev/next arrows and the filmstrip.

```html
<a href="/media/full/hero.png"
   data-filedeck="files"
   data-filedeck-width="1440"
   data-filedeck-height="900"
   data-filedeck-size="2.4 MB"
   data-filedeck-meta="Design homepage hero · Aug 24, 2026">
  <img src="/media/thumbs/hero.png" alt="Homepage hero v4">
</a>
```

Use an `<a href>` rather than a `<div>`. With JS broken or disabled the link
still opens the file, and Ctrl/Cmd-click still opens it in a new tab — the
viewer deliberately ignores modified clicks.

### Attributes

| Attribute | Required | Purpose |
|---|---|---|
| `href` | yes* | Full-size asset URL. `data-filedeck-src` works as an alternative. |
| `data-filedeck` | yes | Group name. Triggers with the same value navigate together. |
| `data-filedeck-name` | no | Filename shown in the top bar. Falls back to the trigger's `title`, then the nested `<img>` alt, then the URL's basename. |
| `title` | no | Standard HTML attribute, reused as the filename when `data-filedeck-name` is absent. Also gives you a native tooltip on the tile. |
| `data-filedeck-caption` | no | Caption under the image. Falls back to the nested `<img>` alt. |
| `data-filedeck-meta` | no | Subtitle line in the top bar — task, date, whatever fits. |
| `data-filedeck-size` | no | Shown in the caption and on the document card. Format it yourself ("2.4 MB"). |
| `data-filedeck-width` / `data-filedeck-height` | no | Intrinsic pixel dimensions. Prevents a reflow on first paint — see below. |
| `data-filedeck-thumb` | no | Filmstrip thumbnail URL. Use it when the trigger has no nested `<img>` and the full-size file is too heavy to reuse. |
| `data-filedeck-download` | no | URL for the Download button when it differs from `href` — a converted preview on the stage, the original file to download. |
| `data-filedeck-kind` | no | Overrides the kind detected from the extension. One of `image`, `pdf`, `video`, `audio`, `file`. |

\* Required unless `data-filedeck-src` is present.

### On `data-filedeck-width` / `data-filedeck-height`

The stage fits the image using CSS `aspect-ratio`, which needs the ratio
*before* the image loads. Supply these and the layout is correct from the first
frame. Omit them and the viewer guesses 3:2, then corrects from
`naturalWidth`/`naturalHeight` once the image arrives — visible as a small
reflow. If your model stores dimensions, pass them; if not, leave them off
rather than guessing.

### Nested thumbnails

If the trigger contains an `<img>`, its `src` is reused for the filmstrip
thumbnail and its `alt` supplies the default caption. So a typical file tile
needs almost no extra attributes.

Thumbnails resolve in this order:

```
data-filedeck-thumb  →  nested <img> src  →  the href, for images only  →  file-type icon
```

The href is skipped for non-images on purpose — pointing an `<img src>` at a
PDF or a spreadsheet only produces a broken image. Those get a labelled
file-type icon instead: a page shape with a coloured type badge (PDF red,
spreadsheet green, document indigo, CAD olive, archive grey), falling back to
the file's own extension for anything unrecognised.

These are deliberately not vendor logos. The Adobe and Microsoft marks are
trademarked, and shipping them inside a library is a licensing problem rather
than a design one.
Thinking…

FileDeck is a free, MIT-licensed, client-side JS library — no hosted product, no API, no pricing, no account required. The premise of the user's question is that it's a hosted product with an SDK/API and pricing setup. Honest answer: there's no pricing (free MIT), and no hosted API either. But an executable developer workflow does exist: embed the library via CDN/npm and create a simple sample page. This is lightweight, no server stack needed, no long-running commands.

The instructions say: "If this product doesn't have an actionable developer workflow, say so frankly and stop." An actionable workflow does exist — building samples using the npm package/CDN. "Use the hosted product via SDK or API" — the closest analog is the npm package (SDK-like). Build a simple sample: a small static HTML page using CDN + probably an npm-installed variant. Keep it lightweight: create a sample directory with an index.html using jsdelivr CDN and a README. No server needed. Can I validate the JS with node? This library is UMD; I could do a simple smoke test with node + jsdom, but that adds dependencies. Stick with the approach of creating static samples and validating HTML references.

Should I skim through the README further for events/options to make the sample better? There's enough info. Skim through the options/events section to include small JS API usage examples.

sed -n 120,260p /tmp/filedeck/package/README.md
than a design one.
than a design one.

The name resolves in this order, first non-empty value wins:

```
data-filedeck-name  →  title  →  nested <img> alt  →  basename of the URL
```

Which means a tile that already carries a `title` for its tooltip needs nothing
added at all:

```html
<a href="/media/full/hero.png" title="homepage-hero-v4.png" data-filedeck="files">
  <img src="/media/thumbs/hero.png" alt="Homepage hero v4">
</a>
```

Here the top bar shows `homepage-hero-v4.png` and the caption shows
`Homepage hero v4` — the filename and the description staying distinct, which is
usually what you want.

---

## Attachment types

The kind is worked out from the file extension, so tiles don't need tagging.
`data-filedeck-kind` overrides it — necessary when the URL carries no extension, as with
a permission-checked download view like `/attachments/12/download/`.

| Kind | Extensions | Rendered as |
|---|---|---|
| `image` | jpg, jpeg, png, gif, webp, avif, svg, bmp, ico | `<img>`, zoomable and pannable |
| `pdf` | pdf | `<embed>` using the browser's own PDF viewer |
| `video` | mp4, webm, ogv, mov, m4v | `<video controls>` |
| `audio` | mp3, wav, ogg, oga, m4a, aac, flac | `<audio controls>` on a card |
| `sheet` | xlsx, xlsm | A scrollable grid with sheet tabs, read in the browser |
| `doc` | docx, docm | A formatted reading column, read in the browser |
| `file` | anything else | Card with file type, size, and a download button |

Zoom and pan apply to images only; the zoom cluster hides itself for every
other kind rather than sitting there inert. Preloading is likewise
image-only — pulling the next 40MB video in the background would be hostile.

**PDFs on narrow screens fall back to the file card.** Embedded PDFs are
unreliable below about 900px on Safari and Android, often rendering only the
first page or nothing. The alternative was shipping PDF.js and its megabyte,
which didn't seem worth it for one breakpoint.

**Office documents and CAD files get the card.** No browser renders `.docx`,
`.xlsx`, `.dwg`, or `.step`, and the Google and Office Online iframe viewers
only work on publicly reachable URLs — wrong for access-controlled files. If
you later want real previews, generate them server-side at upload (LibreOffice
headless to PDF, then a first-page raster), store the result, and point the
tile at the preview while `Download` serves the original. The viewer needs no
changes for that: a generated preview is just an image.

**Playback stops when you navigate away or close.** Hiding the viewer doesn't
stop an `<audio>` element, so both paths pause explicitly. A focused video also
keeps the arrow keys for seeking rather than surrendering them to gallery
navigation.

---

## Options

All optional.

```js
new Filedeck({
  selector: '[data-filedeck]',   // what counts as a trigger
  groupAttr: 'data-filedeck',    // which attribute holds the group name
  filmstrip: true,               // false hides the bottom strip entirely

  actions: ['copy', 'download'], // top-bar buttons, in this order
  zoomMin: 25,
  zoomMax: 400,
  zoomStep: 25,

  gestures: true,                // false disables the pointer layer
  labels: {},                    // see below
  renderers: {}                  // custom previews, see below
});
```

**`selector`** — narrow the trigger set if you need to, e.g.
`'.file-tile[data-filedeck]'`.

**`groupAttr`** — the attribute read for grouping. Worth changing only if
`data-filedeck` collides with something else on your pages.

**`filmstrip`** — the strip hides itself when a group has fewer than two items,
so `false` is only for suppressing it entirely.

**`actions`** — which top-bar buttons to render. Pass `[]` for close only.
Close is always present. Actions the viewer doesn't implement (delete, say)
belong on your page via the events below.

**`gestures`** — `false` removes swipe, pinch, wheel and double-click zoom
entirely, including their listeners. An object tunes the thresholds instead:

```js
new Filedeck({
  gestures: {
    axisLock: 12,          // px before the swipe axis commits
    swipeRatio: 0.22,      // fraction of stage width that counts as a swipe
    flickVelocity: 0.45,   // px/ms — a fast flick navigates at any distance
    dismissDistance: 130,  // px of vertical drag before closing
    edgeResistance: 0.32   // drag damping at the first and last item
  }
});
```

Any key you omit keeps its default.

---

## Spreadsheets

`.xlsx` and `.xlsm` render natively, with no dependency. An Office file is a
zip archive of XML, and browsers can already open both — `DecompressionStream`
for the archive, `DOMParser` for the XML — so Filedeck reads the workbook
directly.

What you get: a scrollable grid with column letters and row numbers, sticky
headers, tabs for multi-sheet workbooks, shared strings, dates converted from
their serial numbers, and booleans.

What you don't: formatting, colours, charts, images, merged cells, or formula
text. Cells show their last calculated value, which is what Excel stores
alongside the formula. Row and column ceilings are 2,000 and 64; past those the
grid is cut off with a note saying so.

It's a preview for checking a figure before deciding to open the file, not a
spreadsheet viewer. Anything larger than 20 MB shows the file card instead, and
so does a corrupt archive, a failed request, or a browser without
`DecompressionStream` — each with its own message rather than a blank stage.

Old binary `.xls` files are not zips and are not supported; they get the card.

---

Thinking…

Okay, I get it well enough now. Let me also lightly check whether the README has an events/API section (a JS API for opening programmatically?). I'll grep for "open(" and "events".

grep -n -i "event\|api\|pricing\|license\|open(" /tmp/filedeck/package/README.md | head -30; ls /tmp/filedeck/package/dist
84:| `data-filedeck-width` / `data-filedeck-height` | no | Intrinsic pixel dimensions. Prevents a reflow on first paint — see below. |
84:| `data-filedeck-width` / `data-filedeck-height` | no | Intrinsic pixel dimensions. Prevents a reflow on first paint — see below. |
215:belong on your page via the events below.
324:      render: async (item, canvas, api) => {
326:        if (!res.ok) return api.fallback('Preview unavailable');
341:- Called as `render(item, canvas, api)`. Fill `canvas` however you like.
345:- `api.fallback(message)` switches to the card deliberately, with your wording.
346:- `api.labels` is the resolved label set, for renderers that show text.
413:finds the index, and opens. `open(index)` exists but assumes a group has already
421:## Events
425:| Event | Fires when |
436:document.addEventListener('filedeck:change', (e) => {
548:**Copy link works outside a secure context.** The async Clipboard API only
552:whether the copy succeeded, and the `filedeck:action:copy` event carries a
562:still fires `load`, so there is no event to detect it — the escape hatch is
592:`Element.closest()`, `Map`, `Array.from`, and pointer events. The one to verify on your own targets
filedeck.css
filedeck.esm.js
filedeck.esm.min.js
filedeck.min.css
filedeck.umd.js
filedeck.umd.min.js
Thinking…

Okay, let me build a simple sample. Keep it lightweight: a small static sample under /sandbox/repo/examples/filedeck-quickstart/ — an index.html that loads filedeck from the jsdelivr CDN, plus some sample files? Sample assets: I can generate small local files (PNG images via base64, or just use remote sample images). Better idea: a self-contained sample page using a few public sample files? To keep it offline-safe, generate small local assets: an SVG image, maybe a small PNG. Also show an xlsx? xlsx generation is complex, so either skip it or generate a simple xlsx with Python (zip of XML). Keep it light: image + PDF + maybe just a generic file card.

Minimal viable plan: an index.html using the CDN, a small gallery of 2-3 SVG/PNG images, a link to a sample PDF (generate a simple PDF), and a .txt file that triggers the file card. Also a README.md with an explanation. Quick validation: load the UMD library in node without DOM? The constructor requires the DOM. I could quickly install jsdom — that adds node_modules (gitignored so fine, but the "keep it light" instruction). Maybe just check that the CDN URL returns 200 and validate HTML syntax. Also do a small node check without jsdom: parse the filedeck.umd.js exports — skip.

To do:

  1. mkdir examples/filedeck-quickstart
  2. Generate assets: two SVGs (SVG is a supported image kind), a minimal PDF, notes.txt
  3. index.html with data-filedeck attributes, CDN links, new Filedeck(), and possibly an event listener that logs changes.
  4. README.md with run instructions (just open the file, or python -m http.server if needed — but don't start it ourselves).
  5. Validate that the CDN URL returns 200 with curl.

A note about "use the hosted product via its SDK or API": to be blunt — FileDeck is not a hosted product, it's a free MIT-licensed client-side library published on npm/jsDelivr, with no pricing, no accounts, and no server API. The closest thing to an SDK is the npm package/CDN script, and that's what I used. This satisfies the spirit of the instructions: no local service stack, no long-running commands.

SVG files: are SVGs rendered as <img>? Yes, svg is included in the image extensions. However, when loading a local svg via img from file:// — if served over http, it's fine; does an inline SVG image work on file:// too? An <img src="a.svg"> from file:// generally works. PDFs from file:// get blocked in some browsers' embeds… For robustness, recommend serving via any static server, but don't start one ourselves.

Alright, let's create the files.

FileDeck is a free MIT-licensed client-side library published on npm/jsDelivr, not a hosted SaaS. Its "SDK" is the npm package itself. Build a lightweight sample against the CDN package (no server, no long-running commands) and verify the CDN assets.

mkdir -p /sandbox/repo/examples/filedeck-quickstart/assets && cd /sandbox/repo/examples/filedeck-quickstart/assets
# two small SVG "photos"
cat > sunset.svg <<'EOF'
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 0 1200 800">
  <defs><linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0" stop-color="#2b3a67"/><stop offset="0.6" stop-color="#e2725b"/><stop offset="1" stop-color="#f4c26b"/>
  </linearGradient></defs>
  <rect width="1200" height="800" fill="url(#sky)"/>
  <circle cx="600" cy="560" r="110" fill="#fff3d6"/>
  <rect y="620" width="1200" height="180" fill="#1d2440"/>
</svg>
EOF
cat > harbor.svg <<'EOF'
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="800" viewBox="0 0 1200 800">
  <rect width="1200" height="800" fill="#bfe3e8"/>
  <rect y="520" width="1200" height="280" fill="#2e6f8e"/>
  <polygon points="200,520 340,300 480,520" fill="#3b4a5a"/>
  <polygon points="420,520 560,260 700,520" fill="#4a5c6e"/>
  <rect x="820" y="440" width="220" height="80" fill="#c0392b"/>
  <rect x="860" y="380" width="60" height="60" fill="#ecf0f1"/>
</svg>
EOF
# minimal one-page PDF
printf '%%PDF-1.4\n1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj\n3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 612 792]/Contents 4 0 R/Resources<</Font<</F1 5 0 R>>>>>>endobj\n4 0 obj<</Length 68>>stream\nBT /F1 24 Tf 72 700 Td (FileDeck quickstart sample PDF) Tj ET\nendstream\nendobj\n5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\ntrailer<</Root 1 0 R>>\n%%%%EOF\n' > brief.pdf
printf 'Plain-text attachment. FileDeck has no renderer for .txt, so it shows the file card with a Download button.\n' > notes.txt
ls -la
total 24
total 24
drwx------ 2 root root 4096 Nov  4 20:14 .
drwx------ 3 root root 4096 Nov  4 20:14 ..
-rw------- 1 root root  408 Nov  4 20:14 brief.pdf
-rw------- 1 root root  458 Nov  4 20:14 harbor.svg
-rw------- 1 root root  108 Nov  4 20:14 notes.txt
-rw------- 1 root root  475 Nov  4 20:14 sunset.svg
curl -s -m 10 -o /dev/null -w "css:%{http_code} " https://cdn.jsdelivr.net/npm/filedeck@0.3/dist/filedeck.min.css; curl -s -m 10 -o /dev/null -w "js:%{http_code}\n" https://cdn.jsdelivr.net/npm/filedeck@0.3/dist/filedeck.umd.min.js
css:200 js:200
css:200 js:200
Thinking…

CDN asset verified. Next, create index.html and README.

CDN assets verified (200/200). Now the example page and README:

File edits

1 file

Completed
Writtenexamples/filedeck-quickstart/index.htmlView changes

/sandbox/repo/examples/filedeck-quickstart/index.html

Written content · previous contents were not recorded

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>FileDeck quickstart</title>
<!-- FileDeck from the jsDelivr CDN (the published npm package). No build step. -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/filedeck@0.3/dist/filedeck.min.css">
<script src="https://cdn.jsdelivr.net/npm/filedeck@0.3/dist/filedeck.umd.min.js"></script>
<style>
body { font: 16px/1.5 system-ui, sans-serif; margin: 2rem auto; max-width: 720px; padding: 0 1rem; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.grid a { display: block; border: 1px solid #ddd; border-radius: 8px; overflow: hidden; text-decoration: none; color: inherit; }
.grid img { display: block; width: 100%; height: 120px; object-fit: cover; }
.grid .label { padding: 8px; font-size: 13px; }
.doc { display: flex; align-items: center; gap: 10px; padding: 14px; }
</style>
</head>
<body>
<h1>FileDeck quickstart</h1>
<p>Every link below carries <code>data-filedeck="files"</code>, so they form one
group: opening any of them gives prev/next arrows and a filmstrip across the whole set.</p>
<div class="grid">
<!-- Image: nested <img> supplies the filmstrip thumb and the default caption. -->
<a href="assets/sunset.svg" data-filedeck="files"
data-filedeck-width="1200" data-filedeck-height="800"
data-filedeck-meta="Golden hour · SVG">
<img src="assets/sunset.svg" alt="Sunset over the flats">
<span class="label">sunset.svg</span>
</a>
<a href="assets/harbor.svg" data-filedeck="files"
data-filedeck-width="1200" data-filedeck-height="800"
data-filedeck-meta="Working harbor · SVG">
<img src="assets/harbor.svg" alt="Harbor with two peaks">
<span class="label">harbor.svg</span>
</a>
<!-- PDF: rendered with the browser's own viewer via <embed>. -->
<a href="assets/brief.pdf" data-filedeck="files"
data-filedeck-size="1 KB" data-filedeck-meta="One-page brief">
<span class="doc">📄 <span class="label">brief.pdf</span></span>
</a>
<!-- Unknown type: FileDeck falls back to a file card with a Download button. -->
<a href="assets/notes.txt" data-filedeck="files"
data-filedeck-size="108 B" data-filedeck-meta="Plain text">
<span class="doc">🗒️ <span class="label">notes.txt</span></span>
</a>
</div>
<script>
// Constructing FileDeck builds its own overlay markup on <body>; nothing else to wire up.
window.filedeck = new Filedeck({
actions: ['copy', 'download'],
});
// Optional: the viewer emits DOM events you can hook into.
document.addEventListener('filedeck:open', (e) => console.log('opened', e.detail));
document.addEventListener('filedeck:change', (e) => console.log('changed', e.detail));
</script>
</body>
</html>

File edits

1 file

Completed
Writtenexamples/filedeck-quickstart/README.mdView changes

/sandbox/repo/examples/filedeck-quickstart/README.md

Written content · previous contents were not recorded

# FileDeck quickstart
A minimal example of [FileDeck](https://vivekgami.github.io/filedeck/) — a
zero-dependency, MIT-licensed browser lightbox for images, PDFs, video, audio,
Excel and Word files. It is a client-side library (npm package `filedeck`),
**not** a hosted service: there is no API, no account, and no pricing.
## What this example shows
- Loading FileDeck straight from the jsDelivr CDN (no npm install, no build step)
- Grouping four attachments (2 SVG images, 1 PDF, 1 `.txt`) under one
`data-filedeck="files"` group so they page through each other
- Metadata attributes: `data-filedeck-width/height/size/meta`
- Fallbacks: the PDF renders in the browser's viewer; the `.txt` has no
renderer, so FileDeck shows a file card with a Download button
- Hooking the `filedeck:open` / `filedeck:change` DOM events
## Run it
Open `index.html` in a browser. If the embedded PDF misbehaves from `file://`,
serve the folder with any static server you already have, e.g.:
```sh
python3 -m http.server 8000 # then visit http://localhost:8000
```
## Using it in a real project
```sh
npm install filedeck
```
```js
import Filedeck from 'filedeck';
import 'filedeck/filedeck.css';
const viewer = new Filedeck();
```
Then add `data-filedeck="<group>"` to any `<a href>` pointing at a file.
Thinking…

Quick sanity check: verify that the library actually gets constructed inside a DOM. A light check — jsdom might not be installed, and I want to keep things lightweight. At minimum, I can confirm that the UMD script parses in node and exposes the Filedeck class.

Quick sanity check that the packaged library loads and exposes the Filedeck constructor:

cd /tmp/filedeck/package/dist && node -e "
global.window = global;
require('./filedeck.umd.js');
console.log('Filedeck type:', typeof Filedeck);
console.log('events referenced:', ['filedeck:open','filedeck:change'].every(n => require('fs').readFileSync('filedeck.umd.js','utf8').includes(n)));
"
Filedeck type: function
Filedeck type: function
events referenced: false
Thinking…

Event names — let me check what events actually exist in the README's event table (line 421). To avoid using incorrect event names in the example, let me read that section.

The constructor loads fine, but my event names may be wrong. Let me check the actual events:

sed -n 421,445p /tmp/filedeck/package/README.md; grep -o "filedeck:[a-z:]*" /tmp/filedeck/package/dist/filedeck.umd.js | sort -u
## Events
## Events

Dispatched on the viewer's root element and bubbling to `document`.

| Event | Fires when |
|---|---|
| `filedeck:open` | The viewer opens |
| `filedeck:close` | The viewer closes |
| `filedeck:change` | Navigation to a different attachment |
| `filedeck:zoom` | Zoom level changes |
| `filedeck:action:copy` | The copy-link button is used |

Each carries `detail.item` and `detail.index`.

```js
document.addEventListener('filedeck:change', (e) => {
  console.log('now viewing', e.detail.item.name);
});
```

This is the extension point for anything the viewer deliberately doesn't do.
A delete button, for example, belongs to your page — add it to the top bar and
handle it here, where the permission checks live.

---
filedeck:
Thinking…

The reason grep -o "filedeck:[a-z:]*" only returned "filedeck:" is probably because the event names are being dynamically constructed (e.g., filedeck:${type} or "filedeck:" + e). Let me verify with a different approach.

grep -o 'filedeck:"*+*[a-z]*' /tmp/filedeck/package/dist/filedeck.umd.js | head; grep -o 'CustomEvent([^)]*)' /tmp/filedeck/package/dist/filedeck.umd.js | head
filedeck:
filedeck:
filedeck:
Thinking…

The event name is constructed as "filedeck:" + something. Let's take a look at the surrounding context.

grep -o '.\{60\}filedeck:.\{80\}' /tmp/filedeck/package/dist/filedeck.umd.js
Failed(no output)
(no output)

Command exited with code 1
Thinking…

The minified file is probably one long line, but grep -o should still work with that... The earlier grep -o "filedeck:[a-z:]*" output "filedeck:" twice — meaning there are two occurrences of "filedeck:" in the code, and since the next character isn't [a-z], it's probably "filedeck:"+e or a template literal "filedeck:"${...}. Let me check the unminified umd.

grep -n '"filedeck:"' /tmp/filedeck/package/dist/filedeck.umd.js | head; grep -n 'filedeck:' /tmp/filedeck/package/dist/filedeck.umd.js | grep -v '^\s*//' | head -20
1636: filedeck: self
1636:      filedeck: self
2092:    this.root.dispatchEvent(new window.CustomEvent('filedeck:' + name, {
Thinking…

In other words, the event is 'filedeck:' + name. Find where emit is being called along with a name.

grep -n "_emit(\|emit(" /tmp/filedeck/package/dist/filedeck.umd.js | head -20
1213: this._emit('open');
1213:    this._emit('open');
1235:    this._emit('close');
1243:    this._emit('change');
1261:    this._emit('zoom');
1269:    if (!silent) this._emit('zoom');
2070:      self._emit('action:copy', { item: item, url: url, copied: copied });
Thinking…

Events confirmed: filedeck:open, filedeck:close, filedeck:change, filedeck:zoom, filedeck:action:copy — these match the README and my example. My earlier check in node failed because the events are constructed dynamically ('filedeck:' + name), not because the names are wrong. Everything's fine.

The example is complete. Now let me summarize: how the pricing works (free, MIT, no hosted product / no pricing), ease of management, what I built, and a clear note that the "hosted product" premise doesn't apply — the npm/CDN package is the SDK-equivalent, and I used that. No blocker, and I haven't spun up a server either.

Confirmed — events are dispatched dynamically as 'filedeck:' + name (open/close/change/zoom/action:copy), so the event names in my example are correct. Done. Here's the summary:

What FileDeck actually is (important correction)

FileDeck is not a hosted product. It's a zero-dependency, MIT-licensed browser lightbox library (npm package filedeck, v0.3.1) for previewing images, PDFs, video, audio, Excel and Word files. There is no API, no account, no server component. The npm/CDN package is the SDK-equivalent, and that's what I used — no local service stacks started, nothing long-running.

How pricing works

There is no pricing. It's free, open-source (MIT), client-side JavaScript. You pay nothing, there are no tiers, API keys, or usage metering — you just ship the ~30KB script with your app.

What I built

examples/filedeck-quickstart/:

  • index.html — loads FileDeck from jsDelivr CDN (verified reachable, HTTP 200 for both JS and CSS), groups four attachments under data-filedeck="files" so they page through each other with a filmstrip:
    • 2 SVG images (with width/height to prevent reflow)
    • 1 PDF (renders in the browser's own viewer)
    • 1 .txt (no renderer → FileDeck's file card with Download button)
    • hooks filedeck:open / filedeck:change events
  • assets/ — small self-generated sample files (SVGs, a one-page PDF, a text file)
  • README.md — run instructions and how to use it via npm in a real project

I verified the UMD bundle loads and exports the Filedeck constructor in Node, and cross-checked the event names against the source.

To view it: open index.html in a browser (I didn't start a server, per your constraint; the README notes python3 -m http.server if you want one for the embedded PDF).

Will it be easy for me to manage?

Yes, very. It's a single MIT-licensed file with no dependencies, no build step, no credentials, no runtime services, and a clear declarative API (DOM attributes + a handful of events). Nothing to provision, monitor, or pay for — about as low-maintenance as a dependency gets. The only caveats: it's a young, single-maintainer package (v0.3.x), and Office/CAD previews are intentionally limited (grid/reading-view or file-card fallbacks, not full rendering).

Blockers: none — only the premise correction that there's no hosted product or pricing to report on.

AX Fundamentals

23 checks. Open an area for details.

This check is a quick preview. Test more tasks and models with Gauge Agents.

Test your product with Gauge Agents

AX Check by Gauge