Skip to content

v0.6.1: LLM multi-provider, bookmark folders, free limits#7

Merged
devohmycode merged 3 commits intomasterfrom
0.6.1
Feb 27, 2026
Merged

v0.6.1: LLM multi-provider, bookmark folders, free limits#7
devohmycode merged 3 commits intomasterfrom
0.6.1

Conversation

@devohmycode
Copy link
Owner

@devohmycode devohmycode commented Feb 27, 2026

Summary

  • LLM multi-provider: Support for multiple LLM providers configuration
  • Bookmark folders: Organize bookmarks into folders with drag & drop support
  • Draw documents: New SuperDraw file management with Supabase sync
  • Free plan limits reduced: Feeds 50→20, folders 10→5
  • Logout data reset: All user data (localStorage) is fully cleared on sign out with page reload
  • Lockfile regenerated: pnpm-lock.yaml updated for new tiptap and other dependencies

Test plan

  • Verify LLM provider switching works correctly
  • Create/move/delete bookmark folders
  • Add feeds up to the new 20 limit on a free account and verify the upgrade modal appears
  • Create folders up to the new 5 limit and verify the upgrade modal appears
  • Log out and verify all localStorage data is cleared and page reloads cleanly
  • Log back in and verify sync restores data from Supabase

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Drawing mode with document management and folder organization for visual schema creation.
    • Added Bookmark folders to organize and filter saved bookmarks by category.
    • Cloud-based LLM service now supports multiple AI providers (Groq, Mistral, Gemini) for improved reliability.
  • Pro Features

    • Editor and Drawing modes are now available exclusively to Pro subscribers.
  • Style

    • Added AMOLED theme support for bookmark and content cards.
    • Enhanced visual indicators for Pro-only features with lock badges.

devohmycode and others added 3 commits February 26, 2026 12:07
…lders

- Clear all superflux_* localStorage keys on sign out and reload page
- Reduce free feed limit from 50 to 20
- Reduce free folder limit from 10 to 5
- Regenerate pnpm-lock.yaml for new dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@qodo-code-review
Copy link

Review Summary by Qodo

Multi-provider LLM, bookmark/draw folders, reduced free limits, and logout data reset

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Add multi-provider LLM support (Groq, Mistral, Gemini) with automatic failover
• Implement bookmark and draw document folder organization with drag-and-drop
• Reduce free plan limits (feeds 50→20, folders 10→5) and lock editor/draw modes
• Clear all localStorage data on logout and reload page for data privacy
• Add draw document persistence with Supabase sync and content autosave
Diagram
flowchart LR
  A["LLM Config"] -->|"Multi-provider<br/>Groq/Mistral/Gemini"| B["Cloud Failover"]
  C["Bookmarks"] -->|"Folder Support"| D["BookmarkPanel"]
  E["Draw Docs"] -->|"Folder Support"| F["SuperDraw"]
  G["Free Plan"] -->|"Reduced Limits<br/>20 feeds, 5 folders"| H["Pro Lock"]
  I["Logout"] -->|"Clear All<br/>localStorage"| J["Page Reload"]
  B -->|"Auto-retry"| K["Successful Response"]
  D -->|"Sync to Supabase"| L["Persistence"]
  F -->|"Sync to Supabase"| L
Loading

Grey Divider

File Changes

1. src/services/llmService.ts ✨ Enhancement +137/-6

Multi-provider LLM with automatic failover

src/services/llmService.ts


2. src/services/drawDocService.ts ✨ Enhancement +112/-0

Draw document Supabase persistence layer

src/services/drawDocService.ts


3. src/services/bookmarkService.ts ✨ Enhancement +22/-0

Add folder field and update method

src/services/bookmarkService.ts


View more (12)
4. src/services/licenseService.ts ⚙️ Configuration changes +2/-2

Reduce free plan limits for feeds and folders

src/services/licenseService.ts


5. src/index.css Formatting +17/-5

Add locked mode tab styling and AMOLED theme support

src/index.css


6. src/App.tsx ✨ Enhancement +298/-7

Integrate draw docs, bookmark folders, and pro mode gating

src/App.tsx


7. src/components/DrawFileList.tsx ✨ Enhancement +439/-0

New draw document file list with folder management

src/components/DrawFileList.tsx


8. src/components/BookmarkSourceList.tsx ✨ Enhancement +272/-0

New bookmark folder sidebar with expandable folders

src/components/BookmarkSourceList.tsx


9. src/components/SourcePanel.tsx ✨ Enhancement +104/-19

Add bookmark and draw mode UI with pro gating

src/components/SourcePanel.tsx


10. src/components/BookmarkPanel.tsx ✨ Enhancement +99/-4

Add folder filtering and context menu for bookmarks

src/components/BookmarkPanel.tsx


11. src/components/SuperDraw.tsx ✨ Enhancement +53/-15

Refactor to use document-based persistence

src/components/SuperDraw.tsx


12. src/components/FeedPanel.tsx ✨ Enhancement +11/-1

Add save-as-bookmark action to feed items

src/components/FeedPanel.tsx


13. src/components/SettingsModal.tsx ✨ Enhancement +20/-8

Update LLM provider UI for multi-provider cloud mode

src/components/SettingsModal.tsx


14. src/contexts/AuthContext.tsx 🐞 Bug fix +5/-15

Clear all localStorage on logout and reload page

src/contexts/AuthContext.tsx


15. pnpm-lock.yaml Additional files +1938/-1

...

pnpm-lock.yaml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Feb 27, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (3) 📎 Requirement gaps (0)

Grey Divider


Action required

1. callMistral() raw fetch 📘 Rule violation ⛯ Reliability
Description
An external network request to Mistral is performed using raw fetch() instead of
src/lib/tauriFetch.ts helpers. This can break requests in Tauri mode and bypass repository-wide
header/proxy handling.
Code

src/services/llmService.ts[R160-174]

+  const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+      'Authorization': `Bearer ${config.mistralApiKey}`,
+    },
+    body: JSON.stringify({
+      model: config.mistralModel,
+      messages: [
+        { role: 'system', content: systemPrompt },
+        { role: 'user', content: userMessage },
+      ],
+      temperature: 0.3,
+    }),
+  });
Evidence
The checklist requires routing all external HTTP requests through tauriFetch helpers (PR
Compliance ID 7). The new callMistral() implementation calls fetch() directly against
https://api.mistral.ai/....

AGENTS.md
src/services/llmService.ts[160-174]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`callMistral()` performs an external HTTP request using raw `fetch()`, which violates the requirement to route external requests via `src/lib/tauriFetch.ts` helpers.

## Issue Context
This repo uses `tauriFetch` to ensure networking works in both Tauri and browser modes, and to centralize header/proxy handling.

## Fix Focus Areas
- src/services/llmService.ts[160-174]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Failover text not French 📘 Rule violation ✓ Correctness
Description
New UI text includes the English word Failover in Settings. This violates the requirement that
modified UI strings be written in French.
Code

src/components/SettingsModal.tsx[R948-954]

+                      <span className="ollama-status-text" style={{ fontSize: '11px', opacity: 0.7 }}>
+                        Failover: {[
+                          llmConfig.groqApiKey && 'Groq',
+                          llmConfig.mistralApiKey && 'Mistral',
+                          llmConfig.geminiApiKey && 'Gemini',
+                        ].filter(Boolean).join(' → ')}
+                      </span>
Evidence
PR Compliance ID 9 requires new/modified UI strings to be in French. The new Settings UI shows
Failover: which is English.

AGENTS.md
src/components/SettingsModal.tsx[948-954]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Settings UI includes English text (`Failover:`), but UI strings must be written in French.

## Issue Context
The compliance checklist enforces French for new/modified UI strings.

## Fix Focus Areas
- src/components/SettingsModal.tsx[948-954]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unused import breaks build 🐞 Bug ✓ Correctness
Description
BookmarkPanel.tsx imports useRef but never uses it; with noUnusedLocals: true this will fail
TypeScript compilation.
Code

src/components/BookmarkPanel.tsx[1]

+import { useState, useEffect, useCallback, useRef } from 'react';
Evidence
The project enables TypeScript unused-local checking, and BookmarkPanel.tsx adds useRef in the
import list without using it anywhere in the file, which triggers a compile error under
noUnusedLocals.

src/components/BookmarkPanel.tsx[1-4]
tsconfig.app.json[25-31]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`src/components/BookmarkPanel.tsx` imports `useRef` but does not use it. With `noUnusedLocals: true`, this causes a TypeScript compilation failure.

### Issue Context
The repo’s `tsconfig.app.json` enforces unused local checks.

### Fix Focus Areas
- src/components/BookmarkPanel.tsx[1-4]
- tsconfig.app.json[25-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. DrawFileList ignores storage errors 📘 Rule violation ⛯ Reliability
Description
The new DrawFileList persistence functions swallow localStorage write errors with empty catch
blocks, creating silent failures and potential data loss. This violates the requirement to avoid
ignored errors and handle failure points with meaningful context.
Code

src/components/DrawFileList.tsx[R23-44]

+export function saveDrawDocs(docs: DrawDoc[]) {
+  try { localStorage.setItem(STORAGE_KEY, JSON.stringify(docs)); }
+  catch { /* ignore */ }
+}
+
+export function loadDrawFolders(): string[] {
+  try {
+    const raw = localStorage.getItem(FOLDERS_KEY);
+    return raw ? JSON.parse(raw) : [];
+  } catch { return []; }
+}
+
+export function saveDrawFolders(folders: string[]) {
+  try { localStorage.setItem(FOLDERS_KEY, JSON.stringify(folders)); }
+  catch { /* ignore */ }
+}
+
+interface DrawFileListProps {
+  docs: DrawDoc[];
+  folders: string[];
+  selectedDocId: string | null;
+  selectedFolder: string | null;
Evidence
PR Compliance ID 3 requires robust error handling and explicitly calls out ignored errors and silent
failures as failure criteria. The new persistence helpers ignore exceptions without logging or
fallback behavior.

Rule 3: Generic: Robust Error Handling and Edge Case Management
src/components/DrawFileList.tsx[23-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Draw docs/folders persistence ignores localStorage write errors, causing silent failures.

## Issue Context
The compliance checklist requires robust error handling and avoiding ignored errors.

## Fix Focus Areas
- src/components/DrawFileList.tsx[23-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Bookmarks list not updated 🐞 Bug ✓ Correctness
Description
When adding a bookmark while already in bookmark mode, the app creates the bookmark but doesn’t
update bookmarkList nor trigger BookmarkPanel to refetch, so the folder sidebar/counts and list
stay stale until a mode switch/login refresh.
Code

src/App.tsx[R229-258]

      tags: [],
      note: null,
      is_read: false,
+      folder: null,
      source: 'desktop' as const,
    });
    if (bk) {
      setSelectedBookmark(bk);
    }
  }, [user]);

+  const handleSaveItemAsBookmark = useCallback(async (item: FeedItem) => {
+    if (!user) return;
+    const id = crypto.randomUUID();
+    await addBookmark(user.id, {
+      id,
+      url: item.url,
+      title: item.title,
+      excerpt: item.excerpt || null,
+      image: item.thumbnail || null,
+      favicon: null,
+      author: item.author || null,
+      site_name: item.feedName || null,
+      tags: item.tags ?? [],
+      note: null,
+      is_read: false,
+      folder: null,
+      source: 'desktop' as const,
+    });
+  }, [user]);
Evidence
SourcePanel calls onAddBookmark from the bookmark URL form, but
handleAddBookmark/handleSaveItemAsBookmark don’t update bookmarkList. The only code that
populates bookmarkList is triggered by brand-mode change to bookmark or by login. Meanwhile,
BookmarkPanel maintains its own fetched list and only loads on mount/user change, so it won’t
automatically reflect newly added bookmarks either.

src/components/SourcePanel.tsx[925-934]
src/App.tsx[178-258]
src/App.tsx[592-607]
src/components/BookmarkPanel.tsx[46-55]
src/App.tsx[1128-1194]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Creating a bookmark while already in bookmark mode adds it to Supabase, but the UI does not refresh `bookmarkList` (used by `BookmarkSourceList` counts/sidebar) and `BookmarkPanel` won’t refetch either, so the new bookmark may not appear until switching modes or reloading.

### Issue Context
- `SourcePanel` calls `onAddBookmark` when submitting the bookmark URL form.
- `handleAddBookmark` / `handleSaveItemAsBookmark` do not update `bookmarkList`.
- `bookmarkList` is only refreshed on login or when switching to bookmark mode.
- `BookmarkPanel` fetches its own `bookmarks` only on mount/user change.

### Fix Focus Areas
- src/App.tsx[178-258]
- src/App.tsx[592-607]
- src/App.tsx[1128-1194]
- src/components/SourcePanel.tsx[925-934]
- src/components/BookmarkPanel.tsx[46-55]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between 4ff6cbd and 9dab24f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • src/App.tsx
  • src/components/BookmarkPanel.tsx
  • src/components/BookmarkSourceList.tsx
  • src/components/DrawFileList.tsx
  • src/components/FeedPanel.tsx
  • src/components/SettingsModal.tsx
  • src/components/SourcePanel.tsx
  • src/components/SuperDraw.tsx
  • src/contexts/AuthContext.tsx
  • src/index.css
  • src/services/bookmarkService.ts
  • src/services/drawDocService.ts
  • src/services/licenseService.ts
  • src/services/llmService.ts
 _________________________________________________
< Keeping your code so clean, you can eat off it. >
 -------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

✏️ Tip: You can disable in-progress messages and the fortune message in your review settings.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 0.6.1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@devohmycode devohmycode merged commit 7ab6085 into master Feb 27, 2026
1 check was pending
Comment on lines +160 to +174
const response = await fetch('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${config.mistralApiKey}`,
},
body: JSON.stringify({
model: config.mistralModel,
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userMessage },
],
temperature: 0.3,
}),
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. callmistral() raw fetch 📘 Rule violation ⛯ Reliability

An external network request to Mistral is performed using raw fetch() instead of
src/lib/tauriFetch.ts helpers. This can break requests in Tauri mode and bypass repository-wide
header/proxy handling.
Agent Prompt
## Issue description
`callMistral()` performs an external HTTP request using raw `fetch()`, which violates the requirement to route external requests via `src/lib/tauriFetch.ts` helpers.

## Issue Context
This repo uses `tauriFetch` to ensure networking works in both Tauri and browser modes, and to centralize header/proxy handling.

## Fix Focus Areas
- src/services/llmService.ts[160-174]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +948 to +954
<span className="ollama-status-text" style={{ fontSize: '11px', opacity: 0.7 }}>
Failover: {[
llmConfig.groqApiKey && 'Groq',
llmConfig.mistralApiKey && 'Mistral',
llmConfig.geminiApiKey && 'Gemini',
].filter(Boolean).join(' → ')}
</span>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. failover text not french 📘 Rule violation ✓ Correctness

New UI text includes the English word Failover in Settings. This violates the requirement that
modified UI strings be written in French.
Agent Prompt
## Issue description
Settings UI includes English text (`Failover:`), but UI strings must be written in French.

## Issue Context
The compliance checklist enforces French for new/modified UI strings.

## Fix Focus Areas
- src/components/SettingsModal.tsx[948-954]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback } from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Unused import breaks build 🐞 Bug ✓ Correctness

BookmarkPanel.tsx imports useRef but never uses it; with noUnusedLocals: true this will fail
TypeScript compilation.
Agent Prompt
### Issue description
`src/components/BookmarkPanel.tsx` imports `useRef` but does not use it. With `noUnusedLocals: true`, this causes a TypeScript compilation failure.

### Issue Context
The repo’s `tsconfig.app.json` enforces unused local checks.

### Fix Focus Areas
- src/components/BookmarkPanel.tsx[1-4]
- tsconfig.app.json[25-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant