API Reference
Architecture overview and endpoint reference for LinkDen's tRPC API.
API Reference
LinkDen's API is built with tRPC v11 on Hono, running on Cloudflare Workers. Every call is end-to-end type-safe -- no code generation required.
Architecture
Next.js Frontend (apps/web)
|
| tRPC Client (HTTP requests)
|
v
Hono Server (apps/server)
|
|-- Better Auth (session validation)
|-- tRPC Router (packages/api)
|
v
Drizzle ORM (packages/db)
|
| SQL queries
|
v
Cloudflare D1 (SQLite)- Hono -- Lightweight web framework for edge runtimes. Zero cold start on Cloudflare Workers.
- tRPC v11 -- End-to-end type safety. Router definitions live in
packages/api. - Better Auth -- Email/password authentication. Session cookies validated on protected procedures.
- Drizzle ORM -- Type-safe SQL for Cloudflare D1. Schema lives in
packages/db/src/schema/.
Authentication
LinkDen uses Better Auth with email/password sign-in.
Session Flow
- Create an admin account during first-time setup at
/admin/setup. - Better Auth issues a secure session cookie.
- Sign in at
/admin/loginon subsequent visits. - The cookie is sent with every API request to authenticate protected routes.
Environment Variables
| Variable | Description |
|---|---|
BETTER_AUTH_SECRET | Secret key for session signing |
BETTER_AUTH_URL | Base URL for the auth server (API server URL) |
CORS_ORIGIN | Trusted origin for the frontend |
Generate a secret with: openssl rand -base64 32
Tip: If you hit 401 errors, double-check that
CORS_ORIGINmatches your frontend URL exactly -- including protocol, no trailing slash.
Endpoint Reference
All endpoints live at /trpc/<router>.<procedure>. Public procedures need no auth. Protected procedures require a valid session cookie.
Blocks
Manage content blocks on your page.
| Procedure | Type | Auth | Description |
|---|---|---|---|
blocks.list | Query | Protected | Get all blocks ordered by position |
blocks.get | Query | Protected | Get a single block by ID |
blocks.create | Mutation | Protected | Create a new block |
blocks.update | Mutation | Protected | Update block fields by ID |
blocks.delete | Mutation | Protected | Delete a block by ID |
blocks.reorder | Mutation | Protected | Batch update block positions |
blocks.toggleEnabled | Mutation | Protected | Toggle block visibility |
Settings
Manage site-wide key-value configuration.
| Procedure | Type | Auth | Description |
|---|---|---|---|
settings.get | Query | Protected | Get a single setting by key |
settings.getAll | Query | Protected | Get all settings as key-value map |
settings.update | Mutation | Protected | Upsert a single key-value pair |
settings.updateBulk | Mutation | Protected | Upsert multiple key-value pairs |
Contacts
Handle contact form submissions.
| Procedure | Type | Auth | Description |
|---|---|---|---|
contacts.list | Query | Protected | List submissions (filterable by read status) |
contacts.get | Query | Protected | Get a single submission by ID |
contacts.markRead | Mutation | Protected | Mark submission as read |
contacts.markUnread | Mutation | Protected | Mark submission as unread |
contacts.delete | Mutation | Protected | Delete a submission |
contacts.unreadCount | Query | Protected | Count of unread submissions |
Analytics
Track page views and clicks. All queries accept an optional period parameter: "7d", "30d", or "90d".
| Procedure | Type | Auth | Description |
|---|---|---|---|
analytics.overview | Query | Protected | Total views and clicks for period |
analytics.viewsOverTime | Query | Protected | Daily view counts |
analytics.clicksOverTime | Query | Protected | Daily click counts |
analytics.topLinks | Query | Protected | Top 10 links by clicks |
analytics.referrers | Query | Protected | Top 10 referrer domains |
analytics.countries | Query | Protected | Top 20 countries by views |
Social
Manage social network entries for Social Icons blocks.
| Procedure | Type | Auth | Description |
|---|---|---|---|
social.list | Query | Protected | List all networks (optional activeOnly filter) |
social.toggle | Mutation | Protected | Toggle a network on/off by slug |
Wallet
Configure Apple Wallet passes.
| Procedure | Type | Auth | Description |
|---|---|---|---|
wallet.getConfig | Query | Protected | Get wallet settings |
wallet.updateConfig | Mutation | Protected | Update wallet settings |
wallet.generatePreview | Query | Protected | Preview data for pass generation |
vCard
Manage and generate vCard contact files.
| Procedure | Type | Auth | Description |
|---|---|---|---|
vcard.getConfig | Query | Protected | Get vCard config and data |
vcard.updateConfig | Mutation | Protected | Update vCard fields |
vcard.preview | Query | Protected | Generate .vcf string |
Backup
Import and export all data.
| Procedure | Type | Auth | Description |
|---|---|---|---|
backup.export | Query | Protected | Export all data as JSON |
backup.import | Mutation | Protected | Import data ("merge" or "replace" mode) |
Version
| Procedure | Type | Auth | Description |
|---|---|---|---|
version.current | Query | Public | Returns current version |
version.checkUpdate | Query | Public | Check for available updates |
Public
Public-facing endpoints -- no authentication needed.
| Procedure | Type | Description |
|---|---|---|
public.getPage | Query | Full page data: profile, blocks, theme, settings |
public.submitContact | Mutation | Submit contact form (with optional CAPTCHA) |
public.trackView | Mutation | Record a page view |
public.trackClick | Mutation | Record a link click |
public.getVCard | Query | Download vCard if enabled |
public.getSetupStatus | Query | Check if setup is complete |
All input is validated with shared Zod schemas from packages/validators.