linkstash is a small experiment for collecting and sharing interesting links and short notes you find during the week.
Previously we used a self‑hosted parser (
lava), but the service now leverages the public defuddle.md converter. Append any URL as a path component (e.g.curl https://defuddle.md/stephango.com) and you'll get back Markdown with YAML frontmatter.
ashdetects links posted to a WhatsApp group (bridged to Matrix) and forwards them to the Vercel API.linkstashcalls the Markdown parser (defuddle.mdby default) and stores the markdown + rich frontmatter in Turso- The Vercel app lists saved links and renders the parsed Markdown in a Hacker News–style feed.
bun install
cp .env.example .env
bunx vercel devAUTH_KEY: Your authentication keyTURSO_DATABASE_URL: Your Turso database URLTURSO_AUTH_TOKEN: Your Turso auth token
The old
LAVA_URLvariable is no longer required; the service will hithttps://defuddle.md/automatically. You may still setLAVA_URLif you want to override the parser for testing or backwards compatibility.
POST /api/add- Add a new linkGET /api/links- Get all linksGET /api/health- Health checkGET /api/content/[key]- Get content by key
/admin— simple admin UI to delete links (protected byAUTH_KEY). This page lets you enter yourAUTH_KEYand delete individual links. Deletions call the server (DELETE /api/admin/link) and are gated by the sameAUTH_KEYused for adding links.
Below are quick curl examples for local development (assumes bunx vercel dev on http://localhost:3000) and that AUTH_KEY is set in your environment.
curl -X POST "http://localhost:3000/api/add" \
-H "Authorization: Bearer $AUTH_KEY" \
-H "Content-Type: application/json" \
-d '{"link": {"url": "https://example.com/article", "submittedBy": "bot"}}'- Success returns
{ "ok": true }. - Possible responses:
401 Unauthorized(bad/absent auth),400 Bad Request(missing link),500on server errors.
curl "http://localhost:3000/api/content/<key>"- Returns the saved
content(plain text / markdown) for the given linkid. - If not found you'll get a JSON
404response:{ "error": "Not found" }.
Note:
/api/linksis a lightweight index and returns the linkmetafields directly (spread into the response). It does not include the fullcontent. Sensitive fields such as submitter identifiers (submittedBy) and room identifiers (roomId) are stripped from API responses, but room comments (roomComment) are preserved and included in responses. Use/api/content/<key>to fetch the stored markdown or content for a link.
You can query link metadata by providing the url query parameter (the service will normalize the URL before matching):
curl "http://localhost:3000/api/links?url=https%3A%2F%2Fexample.com%2Farticle"- Returns the matching link record (JSON) or a
404if not present.