Fixes#1243
Add sibling loading.tsx files for all 6 async route segments that were
missing instant loading UI, causing blank screens during navigation on
slow networks or cold caches.
Routes covered:
- /docs/[[...slug]] — awaits getDocPage + MDX body
- /blog — awaits source.getPages()
- /blog/[slug] — awaits params + MDX body
- /changelog — awaits source.getPages()
- /free — awaits getModels() fetch
- /free/[model_slug] — awaits Promise.all([getModel, getAllModels])
Each loading.tsx is a Server Component returning an animate-pulse
skeleton that matches its route's layout (header, content area,
grid/table/timeline as appropriate). Uses the Skeleton component and
Tailwind classes already present in the project.
Follows the pattern established in:
- app/dashboard/[search_space_id]/logs/loading.tsx
- app/dashboard/[search_space_id]/new-chat/loading.tsx
Fixes#1246
Replace the useState/useEffect pattern that synced fuzzy search results
into local state on every search or searcher change with a single useMemo
that derives results directly during render.
Before:
const [results, setResults] = useState(allBlogs);
useEffect(() => {
setResults(searcher.search(search));
}, [search, searcher]);
After:
const gridItems = useMemo(() => {
const results = search.trim() ? searcher.search(search) : allBlogs;
...
}, [search, searcher, allBlogs, featuredSlug]);
This removes an extra re-render per keystroke and eliminates the stale
intermediate state that occurred between the search input change and the
effect firing.
The announcements page is a public, crawlable route but its page.tsx is
'use client', so it can't export metadata itself and falls back to the
root app/layout.tsx. Add a server-component layout.tsx under
app/(home)/announcements/ that exports route-specific metadata (title,
description, canonical, OpenGraph, Twitter) in the same shape as the
neighboring /blog, /changelog, /contact, /privacy, /terms routes.
page.tsx is unchanged.
Canonical URL matches app/layout.tsx's metadataBase
(https://surfsense.com).
Fixes#1244
- Revised metadata titles and descriptions across multiple pages to better reflect the open-source and privacy-focused nature of SurfSense.
- Enhanced user engagement by simplifying titles for the free AI chat feature and individual model pages.
The (home)/layout.tsx already wraps children in <main>. Having another
<main> inside each child page produces nested landmarks, which is
invalid HTML and confuses screen readers.
Changed the outermost wrapper from <main> → <div> in:
- surfsense_web/app/(home)/page.tsx (homepage)
- surfsense_web/app/(home)/free/page.tsx (free AI chat landing)
Other (home) descendants (login/register/privacy/terms/changelog/
announcements/blog/contact/free/[model_slug]) were already using <div>.
Closes#1191
- Introduced a `ProcessingMode` enum to differentiate between basic and premium processing modes.
- Updated `EtlRequest` to include a `processing_mode` field, defaulting to basic.
- Enhanced ETL pipeline services to utilize the selected processing mode for Azure Document Intelligence and LlamaCloud parsing.
- Modified various routes and services to handle processing mode, affecting document upload and indexing tasks.
- Improved error handling and logging to include processing mode details.
- Added tests to validate processing mode functionality and its impact on ETL operations.
- Added multiple new skills to skills-lock.json from the repository `aaron-he-zhu/seo-geo-claude-skills`.
- Introduced `fuzzy-search` dependency in package.json for improved search functionality.
- Updated pnpm-lock.yaml to include the new `fuzzy-search` package.
- Enhanced SEO metadata across various pages, including canonical links and descriptions for better search visibility.
- Improved layout and structure of several components, including the homepage and changelog, to enhance user experience.
- Introduced a new section in the README files for the Desktop App, highlighting its features: General Assist, Quick Assist, and Extreme Assist.
- Updated all language-specific README files to include details about the desktop app's capabilities and download instructions.
- Add autoComplete="username" and "current-password" to login form
- Add autoComplete="email" and "new-password" to register form inputs
- Add autoComplete="name" to profile display name input
- Add autoComplete="off" to connector search input
- Enables browser password managers and autofill functionality
- Replace window.location.href with router.push() + router.refresh() in UserDropdown logout
- Replace window.location.href with router.push() in CreateSearchSpaceDialog
- Replace window.location.reload() with router.refresh() in login page retry action
- Prevents full page reloads and preserves React state during in-app navigation
- Add optional priority prop to Logo component (defaults to false)
- Set priority=true on login and register pages to preload logo
- Logo on other pages remains lazy-loaded by default
- Improves LCP on critical auth pages by eliminating lazy-load delay
Extract submission logic into submitForm() so the retry toast
action does not capture the original SyntheticEvent, which may
be recycled by React by the time the user clicks retry.
Closes#945
- Removed the "signing_in" text from the login form for a more streamlined user experience.
- Updated the Logo component to include "select-none" class for improved styling and user interaction.
- Replaced the existing announcement card and empty state components with imports from the new announcements directory.
- Introduced state management for the announcements sidebar in the LayoutDataProvider.
- Updated navigation items to handle announcements sidebar toggling.
- Integrated AnnouncementsSidebar into the LayoutShell for both mobile and desktop views.
- Enhanced sidebar handling to improve user experience when navigating announcements.