---
title: Droplets
category: concept
slug: droplets
summary: "Single-file HTML/Markdown apps with versioning, sharing, and CDN hosting."
---
# Droplets

Single-file HTML/Markdown apps with versioning, sharing, and CDN hosting.

A Droplet is Drop's core unit — a single-file app you can drag onto the dashboard or push from the CLI and get a CDN-hosted URL for. HTML and Markdown are both first-class; Markdown gets a branded stylesheet automatically.

Every Droplet has a stable `slug`, a versioned history, an access mode, and a place to live (your personal scope or a [Space](/docs/spaces)).

## Lifecycle

1. **Create** — deploy an `.html` or `.md` file. The first deploy publishes `v1` immediately.
2. **Iterate via drafts** — `drop create --draft` (or the in-browser pencil) writes to a private workspace only you can see. Multiple drafts stack; nothing is visible to viewers until you publish.
3. **Publish** — promote a draft to a new version. Squashes any sibling drafts.
4. **Roll back** — restore any prior version by number; CloudFront is invalidated immediately.
5. **Unpublish / republish** — temporarily hide a Droplet without deleting it; restore the previous published version when ready.

## Access modes

A Droplet's "Internal Access" picks who at Hi Marley can read it:

- **PRIVATE** — only the owner. The default for Droplets created outside any Space.
- **SPACE** — every current member of the owning Space, live. Only valid when the Droplet is in a Space; the default in that case.
- **SPECIFIC** — a curated list of @himarley emails (per-person grants). Only selectable outside a Space; use the "also share with specific people" affordance to add supplemental grants on top of any mode.
- **EVERYONE** — any signed-in Hi Marley employee with the URL. Triggers a confirmation dialog showing the audience size.

Audience-expanding changes ask for an explicit confirmation; audience reductions never block.

External sharing — magic-link URLs with optional password, expiry, and SSO gating — is layered on top via **Share Links** and lives outside the internal-access model.

## Versioning

Every publish creates a new `DropletVersion` row and a versioned S3 path (`{slug}/v{N}/index.html`). The live copy at `{slug}/index.html` is overwritten and CloudFront is invalidated. `drop versions {slug}` lists the full history; `drop rollback {slug} {N}` restores any prior version.

## Drafts

Drafts are per-viewer — your drafts on a Droplet are invisible to everyone else, including the owner. The chokepoint is `lib/drafts.ts`; nothing else in the codebase touches draft state directly. See the [drafts API surface](/docs/api-reference) for full endpoint detail.


## Operations

### Create a Droplet

Deploy an HTML or Markdown file. First deploy auto-publishes `v1`. Pass `--space` to land it inside a Space; pass `--tag` (repeatable) for taxonomy.

**CLI**

```bash
drop create dashboard.html \
  --name "Claim Dashboard" \
  --slug claim-dashboard \
  --description "Real-time claim metrics for the ops team" \
  --tag ops --tag dashboard
```

**MCP**

```json
{
  "tool": "drop_create",
  "arguments": {
    "name": "Claim Dashboard",
    "slug": "claim-dashboard",
    "description": "Real-time claim metrics for the ops team",
    "html": "<!DOCTYPE html>..."
  }
}
```

**HTTP**

```bash
# Step 1 — request a presigned upload URL
curl -X POST https://drop.himarley.ai/api/cli/deploy \
  -H "Authorization: Bearer $DROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"slug": "claim-dashboard", "name": "Claim Dashboard"}'

# Step 2 — PUT the file to the presigned URL (returned above)
curl -X PUT "$UPLOAD_URL" --data-binary @dashboard.html

# Step 3 — confirm the upload (publishes v1, invalidates CDN)
curl -X POST https://drop.himarley.ai/api/apps/claim-dashboard/deploy/confirm \
  -H "Authorization: Bearer $DROP_TOKEN"
```

### Update a Droplet

Same as create — the CLI auto-detects whether the slug exists and publishes a new version. Use `--draft` to land in your private workspace instead.

**CLI**

```bash
# Publish a new version
drop create dashboard.html --slug claim-dashboard --notes "Updated chart colors"

# Save as a draft for review first
drop create dashboard.html --slug claim-dashboard --draft

# Promote the draft when ready
drop publish claim-dashboard
```

**MCP**

```json
{
  "tool": "drop_redeploy",
  "arguments": {
    "slug": "claim-dashboard",
    "html": "<!DOCTYPE html>...",
    "notes": "Updated chart colors"
  }
}
```

### Set the access mode

Switch between PRIVATE, SPACE, SPECIFIC, and EVERYONE. Audience-expanding changes (e.g. PRIVATE → EVERYONE) return `409 CONFIRMATION_REQUIRED` on the first call; re-issue with `confirmed: true` to apply.

**CLI**

```bash
# Web UI: Drop Bar → Access panel → pick the audience
# MCP / HTTP surfaces below
```

**MCP**

```json
{
  "tool": "drop_set_access",
  "arguments": {
    "slug": "claim-dashboard",
    "internalAccess": "EVERYONE",
    "confirmed": true
  }
}
```

**HTTP**

```bash
curl -X PUT https://drop.himarley.ai/api/apps/claim-dashboard/access \
  -H "Authorization: Bearer $DROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"internalAccess": "EVERYONE", "confirmed": true}'
```

### Roll back a version

Restore any prior version by number. Creates a new version pointing at the old S3 object and invalidates CloudFront.

**CLI**

```bash
drop versions claim-dashboard
drop rollback claim-dashboard 3
```

**MCP**

```json
{
  "tool": "drop_rollback",
  "arguments": {
    "slug": "claim-dashboard",
    "version": 3
  }
}
```

**HTTP**

```bash
curl -X POST https://drop.himarley.ai/api/apps/claim-dashboard/versions/3/rollback \
  -H "Authorization: Bearer $DROP_TOKEN"
```

