> ## Documentation Index
> Fetch the complete documentation index at: https://docs.slideless.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# What is Slideless?

> Host and share HTML presentations — a single file or a folder with assets — with public links, view tracking, versioning, and update-in-place.

export const AccentChip = ({label}) => {
  const wrap = {
    display: "inline-flex",
    alignItems: "center",
    gap: "4px",
    fontFamily: '"JetBrains Mono", ui-monospace, monospace',
    fontWeight: 700,
    fontSize: "12px",
    letterSpacing: "0.08em",
    textTransform: "uppercase",
    color: "inherit"
  };
  const bracket = {
    color: "#29ff8d",
    fontWeight: 800
  };
  return <span style={wrap}>
      <span style={bracket}>[</span>
      {label}
      <span style={bracket}>]</span>
    </span>;
};

export const OffsetCard = ({title, body, href, icon}) => {
  const card = {
    display: "block",
    background: "#ffffff",
    color: "#0a0a0a",
    border: "1.5px solid #0a0a0a",
    borderRadius: "6px",
    padding: "24px 22px",
    boxShadow: "4px 4px 0 #000",
    textDecoration: "none",
    transition: "transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.25s cubic-bezier(0.16, 1, 0.3, 1)",
    height: "100%"
  };
  const label = {
    fontFamily: '"JetBrains Mono", ui-monospace, monospace',
    fontWeight: 800,
    fontSize: "14px",
    letterSpacing: "-0.01em",
    textTransform: "uppercase",
    marginBottom: "8px",
    display: "flex",
    alignItems: "center",
    gap: "8px"
  };
  const iconSpan = {
    display: "inline-block",
    width: "18px",
    height: "18px",
    background: "#29ff8d",
    border: "1.5px solid #0a0a0a",
    borderRadius: 0
  };
  const desc = {
    fontFamily: '"Inter", ui-sans-serif, system-ui, sans-serif',
    fontWeight: 400,
    fontSize: "14px",
    lineHeight: 1.5,
    color: "#3f3f46",
    margin: 0
  };
  const onEnter = e => {
    e.currentTarget.style.transform = "translate(-2px, -2px)";
    e.currentTarget.style.boxShadow = "6px 6px 0 #000";
  };
  const onLeave = e => {
    e.currentTarget.style.transform = "none";
    e.currentTarget.style.boxShadow = "4px 4px 0 #000";
  };
  const content = <>
      <div style={label}>
        <span style={iconSpan} aria-hidden="true" />
        {title}
      </div>
      <p style={desc}>{body}</p>
    </>;
  if (href) {
    return <a href={href} style={card} onMouseEnter={onEnter} onMouseLeave={onLeave}>
        {content}
      </a>;
  }
  return <div style={card} onMouseEnter={onEnter} onMouseLeave={onLeave}>
      {content}
    </div>;
};

export const BrutalButton = ({href, label, variant = "primary"}) => {
  const isPrimary = variant === "primary";
  const base = {
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "6px",
    padding: "10px 20px",
    fontFamily: '"JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace',
    fontWeight: 800,
    fontSize: "13px",
    letterSpacing: "0.06em",
    textTransform: "uppercase",
    textDecoration: "none",
    border: "2px solid #0a0a0a",
    borderRadius: 0,
    boxShadow: "4px 4px 0 #000",
    cursor: "pointer",
    whiteSpace: "nowrap",
    transition: "background 0.12s cubic-bezier(0.16, 1, 0.3, 1), transform 0.08s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.08s cubic-bezier(0.16, 1, 0.3, 1)"
  };
  const primary = {
    background: "#29ff8d",
    color: "#070710"
  };
  const secondary = {
    background: "#ffffff",
    color: "#0a0a0a"
  };
  const bracketOnLight = {
    color: "#29ff8d",
    fontWeight: 800,
    fontSize: "14px",
    lineHeight: 1
  };
  const bracketOnLime = {
    color: "#070710",
    fontWeight: 800,
    fontSize: "14px",
    lineHeight: 1
  };
  const bracketStyle = isPrimary ? bracketOnLime : bracketOnLight;
  const onEnter = e => {
    e.currentTarget.style.background = isPrimary ? "#4df8a0" : "#f3f0e0";
  };
  const onLeave = e => {
    e.currentTarget.style.background = isPrimary ? "#29ff8d" : "#ffffff";
    e.currentTarget.style.transform = "none";
    e.currentTarget.style.boxShadow = "4px 4px 0 #000";
  };
  const onDown = e => {
    e.currentTarget.style.transform = "translate(3px, 3px)";
    e.currentTarget.style.boxShadow = "0 0 0 #000";
  };
  const onUp = e => {
    e.currentTarget.style.transform = "none";
    e.currentTarget.style.boxShadow = "4px 4px 0 #000";
  };
  return <a href={href} style={{
    ...base,
    ...isPrimary ? primary : secondary
  }} onMouseEnter={onEnter} onMouseLeave={onLeave} onMouseDown={onDown} onMouseUp={onUp}>
      <span style={bracketStyle}>[</span>
      <span>{label}</span>
      <span style={bracketStyle}>]</span>
    </a>;
};

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", margin: "8px 0 28px" }}>
  <BrutalButton href="/quickstart" label="Quickstart" variant="primary" />

  <BrutalButton href="/cli/overview" label="CLI overview" variant="secondary" />
</div>

## Overview

Slideless turns an HTML deck — either a single self-contained HTML file or a folder with images, video, 3D assets, CSS, JS — into a public, trackable, updatable presentation URL. You upload the deck with one CLI command, get back a link, and share it. Anyone with the link opens the presentation in any browser. No install, no login, no app account.

The product solves a specific problem: presentation files are heavy, locked to specific apps, and lose information the moment you send them. A `.pptx` requires PowerPoint or Keynote, depends on installed fonts, breaks animations across versions, and the moment you email it you lose all visibility into who saw it. Slideless turns the deck into a hosted page — a URL you can drop into Slack, paste into an email, or post on a website.

## How you use it

The primary way to interact with Slideless is the [`slideless` CLI](/cli/overview):

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
npm install -g slideless
slideless auth signup-request --email you@example.com
slideless auth signup-complete --email you@example.com --code 123456 --first-name "Alex"

# A folder with assets…
slideless push ./my-deck --title "Q4 Pitch"

# …or a single HTML file
slideless push ./deck.html --title "Q4 Pitch"

# Then mint a public viewer URL for anyone.
slideless share <presentationId>
```

You get back a `shareUrl`. Send it to anyone. They open it in any browser, relative asset paths in your HTML (`./hero.jpg`, `./video/demo.mp4`, `./three/scene.js`) resolve natively — exactly like serving your folder from a static webserver.

Signup happens from the terminal via a one-time code emailed to you. No dashboard round-trip required. If you already have a key, `slideless login` accepts it directly; see the [quickstart](/quickstart) for both paths.

To update the deck without changing the URL, run `slideless push` again from the same folder:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
slideless push ./my-deck
```

The CLI reads the `slideless.json` file written on the first push to know which presentation to update. Same URL, new content, view counts preserved. Unchanged files (images, video, bundles) are deduplicated by content hash — only modified files re-upload.

## What happens behind the scenes

1. The CLI hashes every file in your deck (SHA-256) and asks the backend which hashes it already has.
2. Only the missing blobs upload (multipart, hash-verified server-side).
3. A manifest listing every file's path + hash + size + content-type is committed to Cloud Storage as an immutable version. `currentVersion` bumps by 1.
4. A Firestore record tracks the owner, title, share tokens, and view counters.
5. Recipients open the share URL. Slideless serves the entry HTML + assets from private Cloud Storage, inside a sandboxed iframe with ETag caching and Range support (for video seeking).
6. Each view increments a per-token counter so you can see who's looking. Every token resolves to either `latest` (auto-follows updates) or a `pinned` version you set explicitly.

## What you can do

| Capability                                        | How                                                                                                                            |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Generate decks with AI and publish them           | Claude marketplace skills (`generate-presentation`, `push-presentation`, `share-presentation`) call the CLI under the hood     |
| Include images, video, 3D models, shaders         | Put them in the deck folder, reference relatively (`./hero.jpg`, `./three/scene.js`)                                           |
| Upload from a script or CI pipeline               | `slideless push ./my-deck --title "..." --strict --json`                                                                       |
| Update a published deck without breaking the link | `slideless push` from the same folder. Same URL, view count preserved, unchanged files deduplicated                            |
| Freeze a recipient on a specific version          | `slideless pin <presentationId> <tokenId> --to-version N`                                                                      |
| Track who's viewing                               | `slideless list` for totals, `slideless get <presentationId>` for per-token counts                                             |
| Send different links to different recipients      | `slideless share <id> --name "<label>"` mints per-recipient tokens, each with its own `versionMode`                            |
| Collaborate with a teammate                       | `slideless invite <id> --email <addr>` grants push + pull access                                                               |
| Manage everything from a UI                       | Dashboard at [https://app.slideless.ai](https://app.slideless.ai) (browsing, preview, token management, collaborators, delete) |

## What Slideless is not

* **Not a slide editor.** You bring the HTML. Slideless hosts and shares it. Use Claude (or Reveal.js, or hand-written HTML, or any AI generator) to author.
* **Not a PowerPoint converter.** Upload `.html` or a folder, not `.pptx`.
* **Not a CMS.** It's purpose-built for one thing: making a deck shareable as a URL.
* **Not a dashboard editor.** v3 uploads are CLI-driven. The dashboard handles browsing, previewing, token management, collaborators, and deletion — not content editing.

## Architecture

| Layer             | What it does                                                                                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **CLI**           | `slideless` npm package, the primary interface to every operation                                                                                                                          |
| **Public viewer** | [https://app.slideless.ai/share/\[presentationId](https://app.slideless.ai/share/\[presentationId)] renders any HTML inside a sandboxed iframe with viewer chrome                          |
| **Dashboard**     | [https://app.slideless.ai](https://app.slideless.ai) for sign in, browse presentations, create API keys, manage share tokens                                                               |
| **HTTP API**      | Cloud Functions in `europe-west1` (the CLI wraps these; see [Advanced: HTTP API](/api-reference/overview) if you need to call them directly)                                               |
| **Plugin skills** | Open Plugin v1 repo at [https://github.com/slideless-ai/plugin](https://github.com/slideless-ai/plugin), installable via `npx plugins add slideless-ai/plugin`. Skills delegate to the CLI |

## <AccentChip label="Next steps" />

<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: "16px", margin: "20px 0" }}>
  <OffsetCard href="/quickstart" title="Quickstart" body="Upload your first presentation in five minutes." />

  <OffsetCard href="/cli/overview" title="CLI overview" body="Why the CLI is the recommended way in." />

  <OffsetCard href="/why-slideless/portable" title="Why Slideless" body="The case for HTML over PowerPoint." />

  <OffsetCard href="/api-reference/overview" title="HTTP API" body="Raw endpoint reference for when you can't use the CLI." />
</div>
