16 };
17 } else {
18 const client = new Cerebras({ apiKey: Deno.env.get("CEREBRAS_API_KEY") });
19 const completion = await client.chat.completions.create({
20 messages: [
11## Setup
12
131. **Get your Readwise API token:**
14 - Go to https://readwise.io/access_token
15 - Copy your access token
23### HTTP Version (Recommended)
24
25The `readwise-http.ts` file provides a web interface and API endpoints:
26
27- **Dashboard:** Visit the root URL to see a simple web interface
28- **Sync API:** `POST /sync` - Triggers a sync of your shortlist
29- **Links API:** `GET /links?limit=50` - Retrieves saved links from database
30
31### Standalone Version
70- ✅ **SQLite compatibility:** Properly handles Val Town's SQLite format
71
72## API Examples
73
74### Sync shortlist
91## Environment Variables Required
92
93- `READWISE_TOKEN` - Your Readwise API access token
94
95## Recent Updates
28}
29
30interface ReadwiseApiResponse {
31 results: ReadwiseDocument[];
32 nextPageCursor: string | null;
60}
61
62// Fetch documents from Readwise API
63async function fetchReadwiseShortlist(): Promise<ReadwiseDocument[]> {
64 const token = Deno.env.get('READWISE_TOKEN');
78 }
79
80 console.log('Making Readwise API request with params:', queryParams.toString());
81
82 const response = await fetch(`https://readwise.io/api/v3/list/?${queryParams.toString()}`, {
83 method: 'GET',
84 headers: {
88
89 if (!response.ok) {
90 throw new Error(`Readwise API error: ${response.status} ${response.statusText}`);
91 }
92
93 const responseJson: ReadwiseApiResponse = await response.json();
94 fullData.push(...responseJson.results);
95 nextPageCursor = responseJson.nextPageCursor;
28}
29
30interface ReadwiseApiResponse {
31 results: ReadwiseDocument[];
32 nextPageCursor: string | null;
60}
61
62// Fetch documents from Readwise API
63async function fetchReadwiseShortlist(): Promise<ReadwiseDocument[]> {
64 const token = Deno.env.get('READWISE_TOKEN');
78 }
79
80 console.log('Making Readwise API request with params:', queryParams.toString());
81
82 const response = await fetch(`https://readwise.io/api/v3/list/?${queryParams.toString()}`, {
83 method: 'GET',
84 headers: {
88
89 if (!response.ok) {
90 throw new Error(`Readwise API error: ${response.status} ${response.statusText}`);
91 }
92
93 const responseJson: ReadwiseApiResponse = await response.json();
94 fullData.push(...responseJson.results);
95 nextPageCursor = responseJson.nextPageCursor;
145 }
146
147 fetch("/api/voicenotes", {
148 method: "POST",
149 body: formData,
20 try {
21 setLoading(true);
22 const response = await fetch(`/api/voicenotes/${voiceNoteId}`);
23 const data = await response.json();
24
26 setVoiceNote(data.voiceNote);
27 // Get audio URL
28 setAudioUrl(`/api/voicenotes/${voiceNoteId}/audio`);
29 } else {
30 setError(data.error || "Voice message not found");
148
149const groq = new Groq({
150 apiKey: Deno.env.get("GROQ_API_KEY") || "",
151});
152// Background transcription function
50## Tech Stack
51
52- **Backend**: Hono (TypeScript API framework)
53- **Database**: SQLite for voice note metadata
54- **Storage**: Val Town Blob storage for audio files
20
21// Mount routes
22app.route("/api/voicenotes", voiceNotesRoutes);
23app.route("/", staticRoutes);
24
15 try {
16 setLoading(true);
17 const response = await fetch("/api/voicenotes");
18 const data = await response.json();
19
120
121 try {
122 const response = await fetch(`/api/voicenotes/${voiceNoteId}`, {
123 method: "DELETE",
124 });