Imported from github.com/cyguin/sniplet https://sniplet-sand.vercel.app
Find a file
2026-06-03 17:36:27 -07:00
src gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00
tests test: add vitest tests for types, handler, adapters, api, and index 2026-05-18 23:18:33 -07:00
.DS_Store feat!: v0.2.0 — [...]cyguin route, --cyguin-* theming, SQLite + Postgres adapters 2026-04-04 23:59:51 -05:00
.gitignore scrub: never track .gsd/ — tool state per-machine 2026-05-19 15:07:02 -07:00
AGENTS.md gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00
DECISIONS.md gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00
lefthook.yml chore: add lefthook pre-commit hooks 2026-06-03 17:36:27 -07:00
LICENSE chore: normalize cyguin package metadata 2026-04-21 09:26:39 -05:00
package-lock.json test: add vitest tests for types, handler, adapters, api, and index 2026-05-18 23:18:33 -07:00
package.json test: add vitest tests for types, handler, adapters, api, and index 2026-05-18 23:18:33 -07:00
README.md gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00
STATE.md gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00
tsconfig.json feat!: v0.2.0 — [...]cyguin route, --cyguin-* theming, SQLite + Postgres adapters 2026-04-04 23:59:51 -05:00
tsup.config.ts gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00
vitest.config.ts gsd: pre-implementation lint/format cleanup 2026-05-16 13:36:13 -07:00

@cyguin/sniplet

Pastebin for code. Drop-in snippet sharing for Next.js apps.

npm install @cyguin/sniplet

Share code snippets via URL — burn-on-read, expiry, syntax highlighting. No account required. Self-hosted on your own database.


Quick Start

1. Install

npm install @cyguin/sniplet

2. Add the route — app/api/snips/[...cyguin]/route.ts:

import { createSnipletHandler } from "@cyguin/sniplet/next";
import { SQLiteAdapter } from "@cyguin/sniplet/adapters/sqlite";

(globalThis as any).__SNIPLET_CONFIG__ = createSnipletHandler({
  adapter: SQLiteAdapter({ path: "./data/sniplet.db" }),
  options: {
    defaultExpiry: "7d",
    rateLimit: { window: "1m", max: 30 },
  },
});

export {
  handler as GET,
  handler as POST,
  handler as DELETE,
} from "@cyguin/sniplet/next";

Wait — the handler export doesn't exist yet. The real pattern in Next.js App Router is:

// app/api/snips/[...cyguin]/route.ts
import { createSnipletHandler } from "@cyguin/sniplet/next";
import { SQLiteAdapter } from "@cyguin/sniplet/adapters/sqlite";

const handler = createSnipletHandler({
  adapter: SQLiteAdapter({ path: "./data/sniplet.db" }),
});

export async function GET(
  req: Request,
  { params }: { params: Promise<{ cyguin: string[] }> },
) {
  return handler(req, params as any);
}
export async function POST(
  req: Request,
  { params }: { params: Promise<{ cyguin: string[] }> },
) {
  return handler(req, params as any);
}
export async function DELETE(
  req: Request,
  { params }: { params: Promise<{ cyguin: string[] }> },
) {
  return handler(req, params as any);
}

3. Drop in the components:

// app/snips/create/page.tsx
"use client";
import { SnipCreate } from "@cyguin/sniplet/react";

export default function CreatePage() {
  return (
    <SnipCreate
      apiBase="/api/snips"
      onSuccess={(id, url) => {
        navigator.clipboard.writeText(url);
        window.location.href = `/snips/${id}`;
      }}
      theme="dark"
    />
  );
}
// app/snips/[id]/page.tsx
"use client";
import { SnipView } from "@cyguin/sniplet/react";

export default function SnipPage({ params }: { params: { id: string } }) {
  return <SnipView id={params.id} apiBase="/api/snips" theme="dark" />;
}

API Routes

Method Route Description
GET /api/snips/[...cyguin] Get a snip by ID
GET /api/snips/options List expiry options
POST /api/snips Create a new snip
DELETE /api/snips/[...cyguin] Delete a snip

Theming

All components default to the cyguin dark theme and use --cyguin-* CSS custom properties. Set them on a parent element or CSS selector:

/* Dark (default) */
:root {
  --cyguin-bg: #0a0d17;
  --cyguin-bg-subtle: #101521;
  --cyguin-border: #252b3a;
  --cyguin-fg: #f1f3f6;
  --cyguin-fg-muted: #888888;
  --cyguin-accent: #f5a800;
  --cyguin-accent-dark: #c47f00;
  --cyguin-accent-fg: #0a0a0a;
  --cyguin-radius: 6px;
  --cyguin-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

Or pass theme="light" prop:

<SnipCreate theme="light" />
<SnipView theme="light" />

Adapters

SQLite (default)

import { SQLiteAdapter } from "@cyguin/sniplet/adapters/sqlite";

createSnipletHandler({
  adapter: SQLiteAdapter({ path: "./data/sniplet.db" }),
});

Postgres

import { PostgresAdapter } from "@cyguin/sniplet/adapters/postgres";

createSnipletHandler({
  adapter: PostgresAdapter({ connectionString: process.env.DATABASE_URL! }),
});

Exports

Import What you get
@cyguin/sniplet Types: Snip, CreateSnipInput, SnipletAdapter, error classes
@cyguin/sniplet/next createSnipletHandler, SnipletConfig, SnipletOptions, ExpiryOption
@cyguin/sniplet/react SnipCreate, SnipView
@cyguin/sniplet/adapters/sqlite SQLiteAdapter
@cyguin/sniplet/adapters/postgres PostgresAdapter

Requirements

  • Next.js 14+ (App Router)
  • React 18+
  • Node.js 20+

License

MIT