The Appview for the kipclip.com atproto bookmarking service
1# kipclip
2
3[](https://github.com/tijs/kipclip-appview/actions/workflows/test.yml)
4
5[](https://ko-fi.com/tijsteulings/tip)
6
7Find it, Kip it. Save and organize bookmarks using the AT Protocol community
8bookmark lexicon.
9
10## Features
11
12- AT Protocol OAuth authentication
13- Save bookmarks to your personal data server (PDS)
14- Automatic URL enrichment (title extraction)
15- View and manage your bookmarks
16- Reading List: filter bookmarks by a configurable tag (default: "toread")
17- User settings stored in Turso database
18- Uses
19 [community.lexicon.bookmarks.bookmark](https://github.com/lexicon-community/lexicon/blob/main/community/lexicon/bookmarks/bookmark.json)
20 schema
21
22## Architecture
23
24- **Frontend**: React 19 + TypeScript + Tailwind CSS
25- **Backend**: Fresh 2.x + AT Protocol OAuth on Deno Deploy
26- **Database**: Turso/libSQL for OAuth session storage
27- **Bookmark Storage**: User's PDS (not in appview database)
28- **Static Assets**: Bunny CDN (`cdn.kipclip.com`)
29
30## Project Structure
31
32```text
33kipclip-appview/
34├── main.ts # Fresh app entry point (all routes)
35├── dev.ts # Development server
36├── lib/ # Backend utilities
37│ ├── db.ts # Database client
38│ ├── oauth-config.ts # OAuth configuration
39│ ├── enrichment.ts # URL metadata extraction
40│ └── ...
41├── frontend/
42│ ├── components/ # React components
43│ ├── index.html # Entry HTML
44│ ├── index.tsx # React entry
45│ └── style.css # Custom styles
46├── shared/
47│ ├── types.ts # Shared TypeScript types
48│ └── utils.ts # Shared utilities
49└── tests/ # Test files
50```
51
52## Setup
53
54### Prerequisites
55
56- Deno installed
57- Deno Deploy account
58- Turso database
59
60### Environment Variables
61
62Configure these in the Deno Deploy dashboard:
63
64```bash
65COOKIE_SECRET=your-random-secret-string-at-least-32-chars # Required
66TURSO_DATABASE_URL=libsql://your-db.turso.io
67TURSO_AUTH_TOKEN=your-turso-auth-token
68BASE_URL=https://kipclip.com # Optional, derived from request if not set
69```
70
71The `COOKIE_SECRET` is required for encrypting OAuth session cookies.
72
73### Local Development
74
75```bash
76# Run local dev server
77deno task dev
78
79# Type check
80deno task check
81
82# Run quality checks (format, lint)
83deno task quality
84
85# Run tests
86deno task test
87```
88
89## Mascot
90
91The kipclip mascot is Kip, a friendly chicken. Mascot images are hosted on Bunny
92CDN at `cdn.kipclip.com/images/`.
93
94## OAuth Flow
95
96kipclip uses [@tijs/atproto-oauth](https://jsr.io/@tijs/atproto-oauth) for AT
97Protocol authentication.
98
991. User enters their AT Protocol handle
1002. App redirects to `/login?handle=user.bsky.social`
1013. OAuth package handles authentication with user's PDS
1024. Session stored in Turso database (14 days)
1035. User can now view/add bookmarks
104
105For implementation details, see the
106[package documentation](https://jsr.io/@tijs/atproto-oauth).
107
108### Dependencies
109
110- [@tijs/atproto-oauth](https://jsr.io/@tijs/atproto-oauth) - OAuth
111 orchestration
112- [@tijs/atproto-storage](https://jsr.io/@tijs/atproto-storage) - SQLite session
113 storage with Turso adapter
114
115## API Endpoints
116
117### Bookmarks
118
119- `GET /api/bookmarks` - List user's bookmarks from PDS
120- `POST /api/bookmarks` - Add new bookmark with URL enrichment
121- `PATCH /api/bookmarks/:rkey` - Update bookmark (tags, title, etc.)
122- `DELETE /api/bookmarks/:rkey` - Delete a bookmark
123
124### Tags
125
126- `GET /api/tags` - List user's tags
127- `POST /api/tags` - Create a new tag
128- `PUT /api/tags/:rkey` - Update tag (renames across all bookmarks)
129- `DELETE /api/tags/:rkey` - Delete tag (removes from all bookmarks)
130
131### Auth
132
133- `GET /api/auth/session` - Check current session
134- `POST /api/auth/logout` - Logout
135- `/login` - OAuth login flow
136- `/oauth/callback` - OAuth callback
137
138### Settings
139
140- `GET /api/settings` - Get user settings
141- `PATCH /api/settings` - Update user settings
142
143### Sharing
144
145- `GET /api/share/:did/:encodedTags` - Get shared bookmarks (public)
146- `GET /share/:did/:encodedTags/rss` - RSS feed for shared bookmarks
147
148## Bookmark Schema
149
150Bookmarks are stored using the community lexicon:
151
152```typescript
153{
154 subject: string; // URL being bookmarked
155 createdAt: string; // ISO 8601 datetime
156 tags?: string[]; // Optional tags
157}
158```
159
160The app enriches bookmarks with page titles by fetching and parsing HTML
161metadata.
162
163## Development Guidelines
164
165- Keep code files under 500 lines
166- Write testable code with dependency injection
167- Tests are in `tests/` directory
168- Use TypeScript for all code
169
170## License
171
172MIT