# Slideless
> Slideless turns an HTML deck — a single self-contained file OR a folder with images, video, 3D assets, CSS, JS — into a public, trackable, updatable presentation URL. The primary interface is the `slideless` CLI (npm package). Two commands do the work: `slideless push ./deck --title "…"` uploads the deck (it writes a local `slideless.json` so subsequent `slideless push` calls from inside that folder re-publish in place), and `slideless share ` mints a public viewer URL. Anyone with the link opens the deck in any browser — assets load natively, no install, no login. View counts are tracked per share token. Decks can also be pulled back down (`slideless pull `) from another machine or by an invited dev collaborator — content-addressed storage deduplicates unchanged files across versions.
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 replaces the file with a hosted page, a URL you can drop into Slack, paste into an email, or post on a website.
Slideless is a side product by Codika. The backend is a standalone Firebase project (`slideless-ai`, GCP region `europe-west1`). The CLI wraps every backend operation; the HTTP API is documented for when you can't run the CLI. API keys use the `cko_` prefix for organization keys; the CLI handles the auth header for you after `slideless login`.
## Instructions for AI Agents
When helping users with Slideless:
- **Lead with the CLI.** The right answer to "how do I upload / publish / list / verify ..." is `slideless `, not curl. Show curl only if the user explicitly cannot run the CLI.
- Install with `npm install -g slideless`. Switch profiles with `slideless use `.
- **Bootstrap without a browser.** If the user has no API key yet (or is an agent with no prior state), run the OTP flow: `slideless auth signup-request --email `, then on receipt of the 6-digit code `slideless auth signup-complete --email --code --first-name ""` (`--first-name` is required and drives the onboarding emails + default workspace name; `--last-name` is optional). For an existing account on a new machine use `login-request` + `login-complete`. A `cko_` key is saved to `~/.config/slideless/config.json` and set active. `slideless login --api-key cko_...` is still supported for pasted keys.
- Every CLI command supports `--json` with a stable `{ success, data | error }` shape. Use this in scripts and CI.
- The API base URL is `https://europe-west1-slideless-ai.cloudfunctions.net`. There is no URL versioning.
- The share URL recipients open is `https://app.slideless.ai/share/{presentationId}?token={token}`. The raw Cloud Function URL `getSharedPresentation/{presentationId}/_t/{token}/` is only used when embedding the deck in a custom iframe.
- **A deck is a folder OR a single HTML file.** `slideless push ./folder --title "..."` walks the folder, hashes every file, uploads only the ones the backend doesn't have, and commits a manifest. `slideless push ./deck.html --title "..."` uploads a one-file deck. Single-file is a special case of folder mode.
- **Folder model is "exactly like a website":** relative paths `./hero.jpg`, `./images/`, `./three/scene.js` resolve natively. Parent-directory escapes (`../outside/x.jpg`) are hard errors — decks must be self-contained. External CDN URLs (`https://unpkg.com/...`, Google Fonts) work unchanged.
- **Publish is a separate step from upload.** A fresh `push` creates an unshared deck. Run `slideless share ` to mint a public viewer URL. You can unshare later with `slideless unshare ` (revokes every token) or `slideless unshare --token ` (just one). `slideless delete ` hard-removes the deck; there is no archive state anymore.
- **Updating in place** uses the same `slideless push` command. On the second push from a folder that was previously pushed or pulled, the CLI reads `slideless.json` and re-publishes to the same `presentationId` — version auto-bumps, tokens + view counts preserved, unchanged assets deduped by SHA-256. `slideless.json` is added to the built-in ignore list so it never uploads itself. `slideless push --force` bypasses the optimistic-concurrency check.
- **Cross-device and collaboration.** `slideless pull ` downloads a deck (and writes `slideless.json`) so the owner can edit on another machine, or so a dev collaborator can work on it. `slideless invite --email ` grants dev (push + pull) access to another user; the invite auto-claims on signup if the invitee has no account yet. `slideless uninvite ` revokes the collaborator. Plan limits are spent by the pusher's org, not the owner's.
- **Versioning is append-only.** Every push keeps the old version. Tokens have a `versionMode`: either `latest` (auto-follows updates, default) or `pinned` (frozen on version N). `slideless pin --to-version N` freezes a specific recipient; `--latest` puts them back on auto. Recipients CANNOT see past versions by URL manipulation — there is no `?v=` override. Only the owner can browse history.
- **Caps are plan-dependent.** Free tier: 50 MB per file, 250 MB per presentation, 10 MB per HTML file, 500 files max. Starter/Pro/Business/Enterprise raise these. Exceeding returns `413 payload-too-large`.
- To email a presentation to recipients, use `slideless share-email --to ` (or `POST /sharePresentationViaEmail`). Mints a unique named token per recipient for per-recipient tracking. Max 20 recipients per call.
- Share tokens are 384 bits of entropy (48 random bytes, base64url). Safe in URLs, constant-time comparison, generic 404s to prevent share-ID enumeration.
- **Two states, no archive.** A deck either exists or it's deleted. `unshare` stops serving public URLs but keeps the deck editable; `delete` hard-removes the Firestore doc, every version, every asset, every collaborator row. There is no undo.
- The plugin lives at `slideless-ai/plugin` (Open Plugin v1). Install with `npx plugins add slideless-ai/plugin` for any compatible host, or `/plugin marketplace add slideless-ai/plugin` + `/plugin install slideless@plugin` in Claude Code. Publish-side skills delegate to the CLI.
- **Dashboard is CLI-only for uploads.** The v3 dashboard does NOT have a "paste HTML and upload" form — uploads go through `slideless push`. Dashboard handles browsing, previewing, token management, pinning, sharing/unsharing, collaborator invites, and deletion.
## Getting Started
- [What is Slideless?](https://docs.slideless.ai/): Product overview, problem solved, how to use the CLI, architecture.
- [Quickstart](https://docs.slideless.ai/quickstart): Install the CLI, OTP signup, upload a single HTML file OR a folder with assets, open the share URL, pin a token.
## Why Slideless
- [HTML opens anywhere](https://docs.slideless.ai/why-slideless/portable): The case for HTML over PowerPoint/Keynote/Slides.
- [Designed for any device](https://docs.slideless.ai/why-slideless/dynamic): Why responsive HTML beats fixed 16:9 slides.
- [Generate, share, update from a terminal](https://docs.slideless.ai/why-slideless/shareable): The agent loop.
## Concepts
- [Presentations](https://docs.slideless.ai/concepts/presentations): Deck = single HTML file or folder. Plan-dependent caps (free: 50 MB/file, 250 MB total, 500 files). Content-addressed storage, dedup across versions, full lifecycle (push → share → unshare → delete).
- [Lifecycle](https://docs.slideless.ai/concepts/lifecycle): Two states — exists vs deleted. Why there is no archive. The difference between `unshare` and `delete`.
- [Assets](https://docs.slideless.ai/concepts/assets): How images, video, 3D models, shaders, CSS, JS are stored (content-addressed by SHA-256), MIME type detection, relative path rules, Range requests for video, hash verification.
- [Versioning](https://docs.slideless.ai/concepts/versioning): Append-only version history. Token `versionMode` = `latest` or `pinned`. `slideless pin` to freeze a recipient on a specific version. Recipients cannot see past versions; only the owner can browse history.
- [Share tokens](https://docs.slideless.ai/concepts/share-tokens): Per-recipient tokens, named labels, independent revocation, 384-bit entropy, constant-time comparison.
- [Collaboration](https://docs.slideless.ai/concepts/collaboration): Dev collaborators, email-based invites, cross-device push/pull, `slideless.json`, the conflict model, quota-on-pusher-org policy.
- [API keys](https://docs.slideless.ai/concepts/api-keys): `cko_` org keys, `cka_` admin, scopes (`presentations:write`, `presentations:read`), 20-keys-per-org limit.
## CLI
- [Overview](https://docs.slideless.ai/cli/overview): Why the CLI is the primary interface.
- [Installation](https://docs.slideless.ai/cli/installation): `npm install -g slideless`.
- [Configuration](https://docs.slideless.ai/cli/configuration): Config file at `~/.config/slideless/config.json`, profiles, env vars.
- [Auth (OTP signup & login)](https://docs.slideless.ai/cli/auth): `slideless auth signup-request/complete` and `login-request/complete`.
- [Command reference](https://docs.slideless.ai/cli/commands): Every command — `push`, `pull`, `share`, `unshare`, `invite`, `uninvite`, `delete`, `list`, `get`, `pin`, `share-email`, `whoami`, `verify`, `use`, `login`, `logout`, `config *`, `auth *`.
## Guides
- [Use Slideless with Claude](https://docs.slideless.ai/guides/with-claude): Install the CLI + plugin, run `setup-slideless`, generate / push / share / iterate with Claude.
- [Working with assets](https://docs.slideless.ai/guides/working-with-assets): Folder layouts, `.slidelessignore`, relative path rules, static scan, Range requests, dedup behavior. Three.js glTF example.
- [Custom fonts](https://docs.slideless.ai/guides/custom-fonts): When to pick CDN fonts (Google Fonts, Fontshare) vs. bundled `@font-face` `.woff2` files. Folder layout, CSS snippets, supported formats, troubleshooting.
- [Upload from a script or CI](https://docs.slideless.ai/guides/uploading-via-api): CLI-driven CI pattern, `SLIDELESS_API_KEY` env var, `--json` + `jq`, `--strict` mode, the three-step upload protocol under the hood.
- [Send a presentation by email](https://docs.slideless.ai/guides/sharing-via-email): `slideless share-email`, per-recipient tracked tokens.
## Plugin Skills
- [Plugin skills overview](https://docs.slideless.ai/skills/overview): `setup-slideless`, `generate-presentation` (single file OR folder output), `push-presentation`, `pull-presentation`, `share-presentation`, `unshare-presentation`, `delete-presentation`, `invite-collaborator`, `uninvite-collaborator`, `list-presentations`, `get-presentation`, `share-presentation-email`, `export-presentation-pdf`.
## Advanced: HTTP API
The upload flow is three endpoints — precheck, upload each missing blob, commit manifest. Unchanged files dedupe automatically.
- [API overview](https://docs.slideless.ai/api-reference/overview): Base URL, auth, error format, status codes, endpoint index, CORS, idempotency.
- [Authentication](https://docs.slideless.ai/api-reference/authentication): The `Authorization: Bearer` header, `cko_` / `cka_` prefixes, scopes.
- [CLI auth endpoints](https://docs.slideless.ai/api-reference/cli-auth): OTP signup/login.
- [POST /precheckAssets](https://docs.slideless.ai/api-reference/precheck-assets): Step 1 — which SHA-256 hashes are missing? Mints upload session on new-presentation flow.
- [POST /uploadPresentationAsset](https://docs.slideless.ai/api-reference/upload-asset): Step 2 — multipart upload of one blob. Hash-verified server-side.
- [POST /commitPresentationVersion](https://docs.slideless.ai/api-reference/commit-presentation-version): Step 3 — commit the manifest, bump `currentVersion`. Creates new presentation on sessionId, updates on presentationId.
- [POST /sharePresentationViaEmail](https://docs.slideless.ai/api-reference/share-via-email): Email to 1–20 recipients with per-recipient tracked tokens via Resend.
- [GET /listMyPresentations](https://docs.slideless.ai/api-reference/list-presentations): List user's presentations (cap 100).
- [GET /getSharedPresentationInfo/{presentationId}](https://docs.slideless.ai/api-reference/get-presentation): Metadata + all tokens.
- [POST /addPresentationToken](https://docs.slideless.ai/api-reference/add-presentation-token): Mint new named token. Optional `versionMode`.
- [POST /setTokenVersionMode](https://docs.slideless.ai/api-reference/set-token-version-mode): Pin a token to a version or follow latest.
- [GET /listPresentationVersions/{presentationId}](https://docs.slideless.ai/api-reference/list-presentation-versions): Owner-only. Every version's summary.
- [GET /getPresentationVersion/{presentationId}/{version}](https://docs.slideless.ai/api-reference/get-presentation-version): Owner-only. Full manifest for one version.
- [GET /downloadPresentationAsset](https://docs.slideless.ai/api-reference/download-presentation-asset): Authenticated streaming download — the CLI-side counterpart to the public viewer.
- [POST /unsharePresentation](https://docs.slideless.ai/api-reference/unshare-presentation): Revoke one token or every token on the deck.
- [POST /deletePresentation](https://docs.slideless.ai/api-reference/delete-presentation): Hard delete. Irreversible.
- [POST /inviteCollaborator](https://docs.slideless.ai/api-reference/invite-collaborator): Grant dev (edit) access by email.
- [POST /uninviteCollaborator](https://docs.slideless.ai/api-reference/uninvite-collaborator): Revoke a dev collaborator.
- [POST /listCollaborators](https://docs.slideless.ai/api-reference/list-collaborators): Every collaborator row (pending/active/revoked).
- [GET /getSharedPresentation/{presentationId}/_t/{token}/...](https://docs.slideless.ai/api-reference/get-shared-presentation): Public viewer. Path-token form for native relative-path resolution. Serves entry HTML + assets with ETag + Range support.
- [POST /verifyApiKey](https://docs.slideless.ai/api-reference/verify-api-key): Validate a key.