Skip to content

caglarbozkurt/echo

Repository files navigation

echo

The agent-native way to share HTML, Markdown, and PDF documents.

Drop a file, get a short, optionally password-protected link.
Built for AI agents and humans — no hosting infrastructure required.

Live demo → · SKILL.md

License: MIT Next.js TypeScript Supabase Deployed on Vercel


Why echo

You generate HTML reports with Claude. Markdown writeups with Cursor. PDFs from a hundred different tools. Sharing them means either pasting raw content into chat (loses fidelity, can't password-protect), spinning up your own Vercel/Netlify project (slow, overkill for a single doc), or using something like Tiiny.host (works, but not built for AI workflows).

echo is the third option — purpose-built for the "I just generated this, give me a link" workflow, with a first-class agent surface (SKILL.md) so any agent runtime can publish without an MCP server.

Features

Feature What it does
Drop or paste Drag .md, .html, or .pdf files into the homepage, or paste raw Markdown/HTML
Markdown rendering Sanitized server-render in a paper-style card with a sidebar TOC and heading anchors
HTML rendering Runs inside a sandboxed iframe (sandbox="allow-scripts") — scripts can't escape to the parent origin
PDF rendering Streams to the browser's native PDF viewer via a dedicated bytes route
Password gate bcrypt-hashed passwords, HMAC-signed unlock cookies, per-doc 24-hour expiry
SEO opt-in Per-doc indexable flag — default noindex since docs are share-by-link
SKILL.md endpoint Drop-in instructions at /skill.md so Claude, Cursor, and other agents can publish without an MCP server

Architecture

flowchart LR
    subgraph Publish
        Form[Web form] -->|POST| API[/api/publish/]
        Agent[Agent + SKILL.md] -->|POST| API
        API --> DB[(Supabase<br/>Postgres)]
    end
    subgraph View
        Visitor[Visitor] -->|GET| Route[/d/slug/]
        Route --> DB
        Route --> Fork{format?}
        Fork -->|md| MD[Sanitized HTML<br/>+ TOC sidebar]
        Fork -->|html| HTML[Sandboxed<br/>iframe]
        Fork -->|pdf| PDF[Native PDF<br/>viewer]
    end
Loading

Stack

Quick start

1. Clone and install

git clone https://github.com/caglarbozkurt/echo.git
cd echo
npm install

2. Create a Supabase project

Sign up at supabase.com and create a new project (free tier is enough).

  • Open SQL Editor → paste the contents of db/schema.sql → run
  • Settings → API → copy the Project URL and secret key (sb_secret_…)

3. Environment

cp .env.example .env.local

Fill in .env.local:

SUPABASE_URL=https://<your-project>.supabase.co
SUPABASE_SERVICE_ROLE_KEY=sb_secret_…
ECHO_COOKIE_SECRET=…   # openssl rand -hex 32
NEXT_PUBLIC_BASE_URL=http://localhost:3000

4. Run

npm run dev

Open http://localhost:3000.

Deploy to Vercel

  1. Push your fork to GitHub
  2. vercel.comAdd NewProject → import the repo
  3. Add the same four env vars under Settings → Environment Variables
  4. Deploy. After the first deploy, set NEXT_PUBLIC_BASE_URL to your assigned production URL and redeploy once so the API responses and SKILL.md reference the correct host

API

POST /api/publish accepts JSON. No authentication required — same risk profile as the web form (also open).

curl -X POST https://<your-domain>/api/publish \
  -H "Content-Type: application/json" \
  -d '{
    "content": "# Hello",
    "format": "md",
    "password": "optional",
    "title": "optional",
    "indexable": false
  }'
# → { "slug": "abc123xy", "url": "https://<your-domain>/d/abc123xy" }

PDFs are sent base64-encoded:

curl -X POST https://<your-domain>/api/publish \
  -H "Content-Type: application/json" \
  -d "{
    \"content\": \"$(base64 -i my.pdf)\",
    \"format\": \"pdf\",
    \"title\": \"My PDF\"
  }"

Full parameter reference at /skill.md.

Use from an AI agent

SKILL.md is served dynamically at /skill.md with the production URL substituted in. It follows Anthropic's skill format, so any agent runtime that reads skills will pick it up:

mkdir -p ~/.claude/skills/echo
curl -sS https://echo-kappa-peach.vercel.app/skill.md \
  -o ~/.claude/skills/echo/SKILL.md

In a new session, asking "publish this writeup to echo" will auto-trigger the skill — Claude will call /api/publish and return the share URL.

Project layout

Click to expand the file tree
src/
├── app/
│   ├── page.tsx                 # Homepage: form, agent callout, log feed
│   ├── layout.tsx               # Metadata, OG tags, Analytics
│   ├── actions.ts               # Server action for the web form
│   ├── api/publish/route.ts     # JSON publish endpoint
│   ├── d/[slug]/
│   │   ├── page.tsx             # Render (md article / html iframe / pdf iframe)
│   │   └── pdf/route.ts         # PDF byte stream (Content-Type: application/pdf)
│   ├── published/[slug]/page.tsx
│   └── skill.md/route.ts        # Dynamic SKILL.md with host substitution
├── components/
│   ├── PublishForm.tsx          # Client: tabs, dropzone, format detection
│   ├── BrandHeader.tsx          # Sticky masthead with copy-link
│   ├── TableOfContents.tsx      # MD doc sidebar
│   ├── CopyButton.tsx
│   └── Footer.tsx
├── lib/
│   ├── supabase.ts              # Server-only client (service role)
│   ├── db.ts                    # getDocBySlug / insertDoc
│   ├── auth.ts                  # bcrypt + HMAC unlock tokens
│   ├── markdown.ts              # marked + sanitize-html, heading IDs, TOC
│   └── baseUrl.ts
└── config/log.ts                # Curated homepage log feed
db/
├── schema.sql                   # Single `documents` table
└── migrations/                  # Idempotent ALTER scripts
public/
├── example.md                   # The "what is echo" doc
└── robots.txt                   # /d/ crawlable, per-page noindex by default

Contributing

Issues, feature ideas, and small PRs are welcome. For anything non-trivial, please open an issue first. See CONTRIBUTING.md for the full guidelines.

License

MIT — built by Caglar Bozkurt.

About

The agent-native way to share HTML, Markdown, and PDF documents. Ships with a SKILL.md endpoint for Claude, Cursor, and other AI agents.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors