kipclip#
Find it, Kip it. Save and organize bookmarks using the AT Protocol community bookmark lexicon.
Features#
- AT Protocol OAuth authentication
- Save bookmarks to your personal data server (PDS)
- Automatic URL enrichment (title extraction)
- View and manage your bookmarks
- Reading List: filter bookmarks by a configurable tag (default: "toread")
- User settings stored in Turso database
- Uses community.lexicon.bookmarks.bookmark schema
Architecture#
- Frontend: React 19 + TypeScript + Tailwind CSS
- Backend: Fresh 2.x + AT Protocol OAuth on Deno Deploy
- Database: Turso/libSQL for OAuth session storage
- Bookmark Storage: User's PDS (not in appview database)
- Static Assets: Bunny CDN (
cdn.kipclip.com)
Project Structure#
kipclip-appview/
├── main.ts # Fresh app entry point (all routes)
├── dev.ts # Development server
├── lib/ # Backend utilities
│ ├── db.ts # Database client
│ ├── oauth-config.ts # OAuth configuration
│ ├── enrichment.ts # URL metadata extraction
│ └── ...
├── frontend/
│ ├── components/ # React components
│ ├── index.html # Entry HTML
│ ├── index.tsx # React entry
│ └── style.css # Custom styles
├── shared/
│ ├── types.ts # Shared TypeScript types
│ └── utils.ts # Shared utilities
└── tests/ # Test files
Setup#
Prerequisites#
- Deno installed
- Deno Deploy account
- Turso database
Environment Variables#
Configure these in the Deno Deploy dashboard:
COOKIE_SECRET=your-random-secret-string-at-least-32-chars # Required
TURSO_DATABASE_URL=libsql://your-db.turso.io
TURSO_AUTH_TOKEN=your-turso-auth-token
BASE_URL=https://kipclip.com # Optional, derived from request if not set
The COOKIE_SECRET is required for encrypting OAuth session cookies.
Local Development#
# Run local dev server
deno task dev
# Type check
deno task check
# Run quality checks (format, lint)
deno task quality
# Run tests
deno task test
Mascot#
The kipclip mascot is Kip, a friendly chicken. Mascot images are hosted on Bunny
CDN at cdn.kipclip.com/images/.
OAuth Flow#
kipclip uses @tijs/atproto-oauth for AT Protocol authentication.
- User enters their AT Protocol handle
- App redirects to
/login?handle=user.bsky.social - OAuth package handles authentication with user's PDS
- Session stored in Turso database (14 days)
- User can now view/add bookmarks
For implementation details, see the package documentation.
Dependencies#
- @tijs/atproto-oauth - OAuth orchestration
- @tijs/atproto-storage - SQLite session storage with Turso adapter
API Endpoints#
Bookmarks#
GET /api/bookmarks- List user's bookmarks from PDSPOST /api/bookmarks- Add new bookmark with URL enrichmentPATCH /api/bookmarks/:rkey- Update bookmark (tags, title, etc.)DELETE /api/bookmarks/:rkey- Delete a bookmark
Tags#
GET /api/tags- List user's tagsPOST /api/tags- Create a new tagPUT /api/tags/:rkey- Update tag (renames across all bookmarks)DELETE /api/tags/:rkey- Delete tag (removes from all bookmarks)
Auth#
GET /api/auth/session- Check current sessionPOST /api/auth/logout- Logout/login- OAuth login flow/oauth/callback- OAuth callback
Settings#
GET /api/settings- Get user settingsPATCH /api/settings- Update user settings
Sharing#
GET /api/share/:did/:encodedTags- Get shared bookmarks (public)GET /share/:did/:encodedTags/rss- RSS feed for shared bookmarks
Bookmark Schema#
Bookmarks are stored using the community lexicon:
{
subject: string; // URL being bookmarked
createdAt: string; // ISO 8601 datetime
tags?: string[]; // Optional tags
}
The app enriches bookmarks with page titles by fetching and parsing HTML metadata.
Development Guidelines#
- Keep code files under 500 lines
- Write testable code with dependency injection
- Tests are in
tests/directory - Use TypeScript for all code
License#
MIT