mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 00:36:31 +02:00
cloud: added openrouter integration with global configs
This commit is contained in:
parent
ff4e0f9b62
commit
4a51ccdc2c
26 changed files with 911 additions and 178 deletions
|
|
@ -57,7 +57,7 @@ function buildModelFaq(model: AnonModel) {
|
|||
},
|
||||
{
|
||||
question: `Is ${model.name} really free on SurfSense?`,
|
||||
answer: `Yes! You can use ${model.name} completely free without login or sign-up. SurfSense gives you 1 million free tokens to use across any model, including ${model.name}.`,
|
||||
answer: `Yes! You can use ${model.name} completely free without login or sign-up. SurfSense gives you 500,000 free tokens to use across any model, including ${model.name}.`,
|
||||
},
|
||||
{
|
||||
question: `How do I use ${model.name} with no login?`,
|
||||
|
|
|
|||
|
|
@ -107,12 +107,12 @@ const FAQ_ITEMS = [
|
|||
{
|
||||
question: "Can I use ChatGPT without login?",
|
||||
answer:
|
||||
"Yes. SurfSense lets you use ChatGPT without login or any sign-up. Just pick a model and start chatting. No email, no password, no account needed. You get 1 million free tokens to use across ChatGPT, Claude AI, Gemini, and other models.",
|
||||
"Yes. SurfSense lets you use ChatGPT without login or any sign-up. Just pick a model and start chatting. No email, no password, no account needed. You get 500,000 free tokens to use across ChatGPT, Claude AI, Gemini, and other models.",
|
||||
},
|
||||
{
|
||||
question: "Is ChatGPT really free on SurfSense?",
|
||||
answer:
|
||||
"Yes. SurfSense gives you free access to ChatGPT (GPT-4), Claude AI, Gemini, and other models without login. You get 1 million free tokens across any model with no sign-up required.",
|
||||
"Yes. SurfSense gives you free access to ChatGPT (GPT-4), Claude AI, Gemini, and other models without login. You get 500,000 free tokens across any model with no sign-up required.",
|
||||
},
|
||||
{
|
||||
question: "How do I use ChatGPT no login?",
|
||||
|
|
@ -125,9 +125,9 @@ const FAQ_ITEMS = [
|
|||
"SurfSense offers free access without login to models from OpenAI (GPT-4, GPT-4 Turbo), Anthropic (Claude 3, Claude free), Google (Gemini), DeepSeek, Mistral, Llama, and more. All available as a free ChatGPT alternative online with no login required.",
|
||||
},
|
||||
{
|
||||
question: "What happens after I use 1 million free tokens?",
|
||||
question: "What happens after I use my free tokens?",
|
||||
answer:
|
||||
"After your free tokens, create a free SurfSense account to unlock 5 million more. Premium model tokens can be purchased at $1 per million tokens. Non-premium models remain unlimited for registered users.",
|
||||
"After your free tokens, create a free SurfSense account to unlock 3 million more premium tokens. Additional tokens can be purchased at $1 per million. Non-premium models remain unlimited for registered users.",
|
||||
},
|
||||
{
|
||||
question: "Is Claude AI available without login?",
|
||||
|
|
@ -203,7 +203,7 @@ export default async function FreeHubPage() {
|
|||
No login required
|
||||
</Badge>
|
||||
<Badge variant="secondary" className="px-3 py-1.5 text-sm">
|
||||
1M free tokens
|
||||
500K free tokens
|
||||
</Badge>
|
||||
<Badge variant="secondary" className="px-3 py-1.5 text-sm">
|
||||
{seoModels.length} AI models
|
||||
|
|
@ -329,7 +329,7 @@ export default async function FreeHubPage() {
|
|||
<section className="max-w-3xl mx-auto text-center">
|
||||
<h2 className="text-2xl font-bold mb-3">Want More Features?</h2>
|
||||
<p className="text-muted-foreground mb-6 leading-relaxed">
|
||||
Create a free SurfSense account to unlock 5 million tokens, document uploads with
|
||||
Create a free SurfSense account to unlock 3 million tokens, document uploads with
|
||||
citations, team collaboration, and integrations with Slack, Google Drive, Notion, and
|
||||
30+ more tools.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { BreadcrumbNav } from "@/components/seo/breadcrumb-nav";
|
|||
export const metadata: Metadata = {
|
||||
title: "Pricing | SurfSense - Free AI Search Plans",
|
||||
description:
|
||||
"Explore SurfSense plans and pricing. Use ChatGPT, Claude AI, and any AI model free. Open source NotebookLM alternative for teams.",
|
||||
"Explore SurfSense plans and pricing. Start free with 500 pages & 3M premium tokens. Use ChatGPT, Claude AI, and premium AI models. Pay-as-you-go tokens at $1 per million.",
|
||||
alternates: {
|
||||
canonical: "https://surfsense.com/pricing",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ const changelogSource = loader({
|
|||
source: changelog.toFumadocsSource(),
|
||||
});
|
||||
|
||||
const BASE_URL = "https://surfsense.com";
|
||||
const BASE_URL = "https://www.surfsense.com";
|
||||
const BACKEND_URL = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "http://localhost:8000";
|
||||
|
||||
async function getFreeModelSlugs(): Promise<string[]> {
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
title: "Why Enterprise Search Matters More Than Ever"
|
||||
description: "As organizations generate more data across more tools, finding the right information at the right time has become a critical competitive advantage. Here's why enterprise search is no longer optional."
|
||||
date: "2026-04-10"
|
||||
image: "/og-image.png"
|
||||
author: "SurfSense Team"
|
||||
authorAvatar: "/logo.png"
|
||||
tags: ["Enterprise Search", "Productivity", "Knowledge Management"]
|
||||
---
|
||||
|
||||
## The Information Overload Problem
|
||||
|
||||
The average knowledge worker switches between **11 different applications** per day and spends nearly 20% of their time searching for information. That's an entire day each week lost to context-switching and hunting for answers buried in Slack threads, Google Docs, Notion pages, and email chains.
|
||||
|
||||
Enterprise search solves this by providing a **single, unified interface** to query across all your knowledge sources simultaneously.
|
||||
|
||||
## What Makes Modern Enterprise Search Different
|
||||
|
||||
Traditional enterprise search was little more than a keyword matcher slapped onto a file server. Modern solutions like SurfSense take a fundamentally different approach:
|
||||
|
||||
- **Semantic Understanding**: AI-powered search understands the *meaning* behind your query, not just the keywords
|
||||
- **Federated Architecture**: Connect dozens of data sources without migrating data out of where it lives
|
||||
- **Contextual Ranking**: Results are ranked by relevance to your role, recent activity, and team context
|
||||
- **Real-time Indexing**: New content becomes searchable within minutes, not days
|
||||
|
||||
## The ROI of Getting Search Right
|
||||
|
||||
Organizations that invest in proper enterprise search see measurable improvements:
|
||||
|
||||
- **30% reduction** in time spent searching for information
|
||||
- **25% faster** onboarding for new team members
|
||||
- **40% fewer** duplicate documents and redundant work
|
||||
|
||||
## Getting Started
|
||||
|
||||
The best time to implement enterprise search was when your team hit 20 people. The second best time is now. Start by auditing which tools your team uses daily, then look for a solution that connects to all of them natively.
|
||||
|
||||
SurfSense connects to Slack, Google Drive, Notion, Confluence, GitHub, and dozens more — all with a single search bar.
|
||||
|
|
@ -222,7 +222,10 @@ export const FreeComposer: FC = () => {
|
|||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<label htmlFor="free-web-search-toggle" className="flex items-center gap-1.5 cursor-pointer select-none rounded-md px-2 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors">
|
||||
<label
|
||||
htmlFor="free-web-search-toggle"
|
||||
className="flex items-center gap-1.5 cursor-pointer select-none rounded-md px-2 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors"
|
||||
>
|
||||
<Globe className="size-3.5" />
|
||||
<span className="hidden sm:inline">Web</span>
|
||||
<Switch
|
||||
|
|
|
|||
|
|
@ -40,16 +40,21 @@ export function FreeModelSelector({ className }: { className?: string }) {
|
|||
[models, currentSlug]
|
||||
);
|
||||
|
||||
const sortedModels = useMemo(
|
||||
() => [...models].sort((a, b) => Number(a.is_premium) - Number(b.is_premium)),
|
||||
[models]
|
||||
);
|
||||
|
||||
const filteredModels = useMemo(() => {
|
||||
if (!searchQuery.trim()) return models;
|
||||
if (!searchQuery.trim()) return sortedModels;
|
||||
const q = searchQuery.toLowerCase();
|
||||
return models.filter(
|
||||
return sortedModels.filter(
|
||||
(m) =>
|
||||
m.name.toLowerCase().includes(q) ||
|
||||
m.model_name.toLowerCase().includes(q) ||
|
||||
m.provider.toLowerCase().includes(q)
|
||||
);
|
||||
}, [models, searchQuery]);
|
||||
}, [sortedModels, searchQuery]);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(model: AnonModel) => {
|
||||
|
|
@ -170,13 +175,20 @@ export function FreeModelSelector({ className }: { className?: string }) {
|
|||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="font-medium text-sm truncate">{model.name}</span>
|
||||
{model.is_premium && (
|
||||
{model.is_premium ? (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="text-[9px] px-1 py-0 h-3.5 bg-purple-100 text-purple-700 dark:bg-purple-900/50 dark:text-purple-300 border-0"
|
||||
>
|
||||
Premium
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="text-[9px] px-1 py-0 h-3.5 bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300 border-0"
|
||||
>
|
||||
Free
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-xs text-muted-foreground truncate block">
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export function QuotaWarningBanner({
|
|||
</p>
|
||||
<p className="text-xs text-red-600 dark:text-red-300">
|
||||
You've used all {limit.toLocaleString()} free tokens. Create a free account to
|
||||
get 5 million tokens and access to all models.
|
||||
get 3 million tokens and access to all models.
|
||||
</p>
|
||||
<Link
|
||||
href="/register"
|
||||
|
|
|
|||
|
|
@ -433,13 +433,31 @@ export function ModelSelector({
|
|||
isGlobal && "is_auto_mode" in c && !!(c as Record<string, unknown>).is_auto_mode,
|
||||
}));
|
||||
|
||||
const sortGlobalItems = (items: DisplayItem[]): DisplayItem[] =>
|
||||
[...items].sort((a, b) => {
|
||||
if (a.isAutoMode !== b.isAutoMode) return a.isAutoMode ? -1 : 1;
|
||||
const aPremium = !!(a.config as Record<string, unknown>).is_premium;
|
||||
const bPremium = !!(b.config as Record<string, unknown>).is_premium;
|
||||
if (aPremium !== bPremium) return aPremium ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
switch (activeTab) {
|
||||
case "llm":
|
||||
return [...toItems(filteredLLMGlobal, true), ...toItems(filteredLLMUser, false)];
|
||||
return [
|
||||
...sortGlobalItems(toItems(filteredLLMGlobal, true)),
|
||||
...toItems(filteredLLMUser, false),
|
||||
];
|
||||
case "image":
|
||||
return [...toItems(filteredImageGlobal, true), ...toItems(filteredImageUser, false)];
|
||||
return [
|
||||
...sortGlobalItems(toItems(filteredImageGlobal, true)),
|
||||
...toItems(filteredImageUser, false),
|
||||
];
|
||||
case "vision":
|
||||
return [...toItems(filteredVisionGlobal, true), ...toItems(filteredVisionUser, false)];
|
||||
return [
|
||||
...sortGlobalItems(toItems(filteredVisionGlobal, true)),
|
||||
...toItems(filteredVisionUser, false),
|
||||
];
|
||||
}
|
||||
}, [
|
||||
activeTab,
|
||||
|
|
@ -859,14 +877,23 @@ export function ModelSelector({
|
|||
Recommended
|
||||
</Badge>
|
||||
)}
|
||||
{"is_premium" in config && (config as Record<string, unknown>).is_premium && (
|
||||
{"is_premium" in config && (config as Record<string, unknown>).is_premium ? (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="text-[9px] px-1 py-0 h-3.5 bg-purple-100 text-purple-700 dark:bg-purple-900/50 dark:text-purple-300 border-0"
|
||||
>
|
||||
Premium
|
||||
</Badge>
|
||||
)}
|
||||
) : "is_premium" in config &&
|
||||
!(config as Record<string, unknown>).is_premium &&
|
||||
!isAutoMode ? (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="text-[9px] px-1 py-0 h-3.5 bg-emerald-100 text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300 border-0"
|
||||
>
|
||||
Free
|
||||
</Badge>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 mt-0.5">
|
||||
<span className="text-xs text-muted-foreground truncate">
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ const demoPlans = [
|
|||
price: "0",
|
||||
yearlyPrice: "0",
|
||||
period: "",
|
||||
billingText: "500 pages included",
|
||||
billingText: "500 pages + 3M premium tokens included",
|
||||
features: [
|
||||
"Self Hostable",
|
||||
"500 pages included to start",
|
||||
"3 million premium tokens to start",
|
||||
"Earn up to 3,000+ bonus pages for free",
|
||||
"Includes access to OpenAI text, audio and image models",
|
||||
"Realtime Collaborative Group Chats with teammates",
|
||||
|
|
@ -30,11 +31,13 @@ const demoPlans = [
|
|||
name: "PAY AS YOU GO",
|
||||
price: "1",
|
||||
yearlyPrice: "1",
|
||||
period: "1,000 pages",
|
||||
period: "pack",
|
||||
billingText: "No subscription, buy only when you need more",
|
||||
features: [
|
||||
"Everything in Free",
|
||||
"Buy 1,000-page packs at $1 each",
|
||||
"Buy 1M premium token packs at $1 each",
|
||||
"Use premium AI models like GPT-5.4, Claude Sonnet 4.6, Gemini 2.5 Pro & 100+ more via OpenRouter",
|
||||
"Priority support on Discord",
|
||||
],
|
||||
description: "",
|
||||
|
|
@ -77,7 +80,7 @@ interface FAQSection {
|
|||
|
||||
const faqData: FAQSection[] = [
|
||||
{
|
||||
title: "Pages & Billing",
|
||||
title: "Pages & Document Billing",
|
||||
items: [
|
||||
{
|
||||
question: 'What exactly is a "page" in SurfSense?',
|
||||
|
|
@ -126,13 +129,38 @@ const faqData: FAQSection[] = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Premium Tokens",
|
||||
items: [
|
||||
{
|
||||
question: 'What are "premium tokens"?',
|
||||
answer:
|
||||
"Premium tokens are the billing unit for using premium AI models like GPT-5.4, Claude Sonnet 4.6, and Gemini 2.5 Pro in SurfSense. Each AI request consumes tokens based on the length of your conversation. Non-premium models (such as free-tier models available without login) do not consume premium tokens.",
|
||||
},
|
||||
{
|
||||
question: "How many premium tokens do I get for free?",
|
||||
answer:
|
||||
"Every registered SurfSense account starts with 3 million premium tokens at no cost. Anonymous users (no login) get 500,000 free tokens across all models. Once your free tokens are used up, you can purchase more at any time.",
|
||||
},
|
||||
{
|
||||
question: "How does purchasing premium tokens work?",
|
||||
answer:
|
||||
"Just like pages, there's no subscription. You buy 1-million-token packs at $1 each whenever you need more. Purchased tokens are added to your account immediately. You can buy up to 100 packs at a time.",
|
||||
},
|
||||
{
|
||||
question: "What happens if I run out of premium tokens?",
|
||||
answer:
|
||||
"When your premium token balance runs low (below 20%), you'll see a warning. Once you run out, premium model requests are paused until you purchase more tokens. You can always switch to non-premium models which don't consume premium tokens.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Self-Hosting",
|
||||
items: [
|
||||
{
|
||||
question: "Can I self-host SurfSense with unlimited pages?",
|
||||
question: "Can I self-host SurfSense with unlimited pages and tokens?",
|
||||
answer:
|
||||
"Yes! When self-hosting, you have full control over your page limits. The default self-hosted setup gives you effectively unlimited pages, so you can index as much data as your infrastructure supports.",
|
||||
"Yes! When self-hosting, you have full control over your page and token limits. The default self-hosted setup gives you effectively unlimited pages and tokens, so you can index as much data and use as many AI queries as your infrastructure supports.",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -223,8 +251,8 @@ function PricingFAQ() {
|
|||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="mx-auto mt-4 max-w-2xl text-lg text-muted-foreground">
|
||||
Everything you need to know about SurfSense pages and billing. Can't find what you
|
||||
need? Reach out at{" "}
|
||||
Everything you need to know about SurfSense pages, premium tokens, and billing. Can't
|
||||
find what you need? Reach out at{" "}
|
||||
<a href="mailto:rohan@surfsense.com" className="text-blue-500 underline">
|
||||
rohan@surfsense.com
|
||||
</a>
|
||||
|
|
@ -308,7 +336,7 @@ function PricingBasic() {
|
|||
<Pricing
|
||||
plans={demoPlans}
|
||||
title="SurfSense Pricing"
|
||||
description="Start free with 500 pages and pay as you go."
|
||||
description="Start free with 500 pages & 3M premium tokens. Pay as you go."
|
||||
/>
|
||||
<PricingFAQ />
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export function LoginGateProvider({ children }: { children: ReactNode }) {
|
|||
<DialogHeader>
|
||||
<DialogTitle>Create a free account to {feature}</DialogTitle>
|
||||
<DialogDescription>
|
||||
Get 5 million tokens, save chat history, upload documents, use all AI tools, and
|
||||
Get 3 million tokens, save chat history, upload documents, use all AI tools, and
|
||||
connect 30+ integrations.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue