diff --git a/apps/web/components/document-modal/title.tsx b/apps/web/components/document-modal/title.tsx
index 94ce07722..9f2b0255e 100644
--- a/apps/web/components/document-modal/title.tsx
+++ b/apps/web/components/document-modal/title.tsx
@@ -30,7 +30,7 @@ export function Title({
)}
>
-
+
{extension && (
page.documents ?? []))
}
- setTimeout(() => inputRef.current?.focus(), 0)
+ const focusTimer = setTimeout(() => inputRef.current?.focus(), 0)
setSearch(initialSearch)
setSelectedIndex(0)
setSearchResults([])
+ return () => clearTimeout(focusTimer)
}
}, [open, queryClient, projectId, initialSearch])
diff --git a/apps/web/components/feedback-modal.tsx b/apps/web/components/feedback-modal.tsx
index 82f4623c4..7386691e2 100644
--- a/apps/web/components/feedback-modal.tsx
+++ b/apps/web/components/feedback-modal.tsx
@@ -117,7 +117,7 @@ export function FeedbackModal({ isOpen, onClose }: FeedbackModalProps) {
setFeedback(e.target.value)}
onKeyDown={handleKeyDown}
- placeholder="Share your thoughts..."
+ placeholder="Share your thoughts…"
className={cn(
"min-h-[120px] bg-[#0D121A] border border-[rgba(115,115,115,0.2)] text-[#fafafa] placeholder:text-[#737373] focus-visible:border-[#2261CA] focus-visible:ring-[#2261CA33] resize-none",
dmSansClassName(),
@@ -164,7 +164,7 @@ export function FeedbackModal({ isOpen, onClose }: FeedbackModalProps) {
{isSubmitting ? (
<>
- Submitting...
+ Submitting…
>
) : (
"Submit"
diff --git a/apps/web/components/fullscreen-note-modal.tsx b/apps/web/components/fullscreen-note-modal.tsx
index 53394a47b..7762204ed 100644
--- a/apps/web/components/fullscreen-note-modal.tsx
+++ b/apps/web/components/fullscreen-note-modal.tsx
@@ -198,7 +198,7 @@ export function FullscreenNoteModal({
>
Command Key
-
+
Home
@@ -114,7 +114,7 @@ export function Header({ onAddMemory, onOpenSearch }: HeaderProps) {
target="_blank"
rel="noreferrer"
>
-
+
Developer console
@@ -123,7 +123,7 @@ export function Header({ onAddMemory, onOpenSearch }: HeaderProps) {
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
supermemory.ai
@@ -148,7 +148,7 @@ export function Header({ onAddMemory, onOpenSearch }: HeaderProps) {
aria-current={viewMode === "dashboard" ? "page" : undefined}
onClick={() => void setViewMode("dashboard")}
className={cn(
- "flex h-10 w-10 shrink-0 cursor-pointer items-center justify-center rounded-full border transition-colors",
+ "flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-full border transition-colors",
viewMode === "dashboard"
? "border-[#2261CA33] bg-[#00173C] text-white"
: "border-[#161F2C] bg-muted text-muted-foreground hover:bg-white/5",
@@ -236,7 +236,7 @@ export function Header({ onAddMemory, onOpenSearch }: HeaderProps) {
aria-current={viewMode === "chat" ? "page" : undefined}
onClick={() => void setViewMode("chat")}
className={cn(
- "flex h-10 w-10 shrink-0 cursor-pointer items-center justify-center rounded-full border transition-colors",
+ "flex size-10 shrink-0 cursor-pointer items-center justify-center rounded-full border transition-colors",
viewMode === "chat"
? "border-[#2261CA33] bg-[#00173C] text-white"
: "border-[#161F2C] bg-muted text-muted-foreground hover:bg-white/5",
@@ -286,49 +286,49 @@ export function Header({ onAddMemory, onOpenSearch }: HeaderProps) {
onClick={onAddMemory}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Add memory
void setViewMode("dashboard")}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Home
setViewMode("integrations")}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Integrations
void setViewMode("graph")}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Graph
onOpenSearch?.()}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Search
void setViewMode("list")}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Memories
void setViewMode("chat")}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Chat with Nova
@@ -336,14 +336,14 @@ export function Header({ onAddMemory, onOpenSearch }: HeaderProps) {
onClick={handleFeedback}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Feedback
router.push("/settings")}
className="px-3 py-2.5 rounded-md hover:bg-[#293952]/40 cursor-pointer text-white text-sm font-medium gap-2"
>
-
+
Settings
diff --git a/apps/web/components/integration-icons.tsx b/apps/web/components/integration-icons.tsx
index 7629f38e2..07d399ad1 100644
--- a/apps/web/components/integration-icons.tsx
+++ b/apps/web/components/integration-icons.tsx
@@ -13,28 +13,28 @@ export function IntegrationsIcon({ className }: { className?: string }) {
>
Integrations
Google Chrome Icon
)
@@ -105,7 +105,7 @@ export function RaycastIcon({ className }: { className?: string }) {
diff --git a/apps/web/components/integrations/chrome-detail.tsx b/apps/web/components/integrations/chrome-detail.tsx
index c419e4ff6..6a63dbf14 100644
--- a/apps/web/components/integrations/chrome-detail.tsx
+++ b/apps/web/components/integrations/chrome-detail.tsx
@@ -47,7 +47,7 @@ export function ChromeDetail() {
>
-
+
{info && (
-
+
- {plugin.keyStart}...
+ {plugin.keyStart}…
)}
@@ -237,7 +237,7 @@ function PluginCard({
@@ -335,7 +335,7 @@ function PluginCard({
>
{isCurrentlyConnecting ? (
<>
-
Connecting...
+
Connecting…
>
) : (
"Connect Plugin"
@@ -495,13 +495,18 @@ export function PluginsDetail() {
const handleUpgrade = async () => {
try {
- await autumn.attach({
+ const result = await autumn.attach({
planId: "api_pro",
- successUrl: "https://app.supermemory.ai/?view=integrations",
+ successUrl: `${window.location.origin}/?view=integrations`,
})
- window.location.reload()
+ if (result?.paymentUrl) {
+ window.open(result.paymentUrl, "_self")
+ return
+ }
+ autumn.refetch?.()
} catch (error) {
console.error(error)
+ toast.error("Failed to start checkout. Please try again.")
}
}
@@ -614,7 +619,7 @@ export function PluginsDetail() {
- Save your API key now — you won't be able to see it again.
+ Save your API key now: you won't be able to see it again.
{keyCopied ? (
-
+
) : (
-
+
)}
diff --git a/apps/web/components/integrations/raycast-detail.tsx b/apps/web/components/integrations/raycast-detail.tsx
index 68dec85e3..94769cb54 100644
--- a/apps/web/components/integrations/raycast-detail.tsx
+++ b/apps/web/components/integrations/raycast-detail.tsx
@@ -99,7 +99,7 @@ export function RaycastDetail() {
>
-
+
{copied ? (
-
+
) : (
-
+
)}
@@ -219,7 +219,7 @@ export function RaycastDetail() {
'Use "Add Memory" or "Search Memories" commands!',
].map((text, i) => (
-
+
{i + 1}
{copied ? (
-
+
) : (
-
+
)}
@@ -252,7 +252,7 @@ export function ShortcutsDetail() {
"Start using your shortcut!",
].map((text, i) => (
-
+
{i + 1}
handleSetViewMode("grid")}
>
-
+
Grid
handleSetViewMode("timeline")}
>
-
+
Timeline
@@ -618,10 +618,10 @@ export function MemoriesGrid({
type="button"
aria-label="Select documents"
title="Select documents"
- className="w-8 h-8 flex items-center justify-center rounded-full border border-[#161F2C] bg-[#0D121A] hover:bg-[#00173C] hover:border-[#2261CA33] transition-colors cursor-pointer"
+ className="size-8 flex items-center justify-center rounded-full border border-[#161F2C] bg-[#0D121A] hover:bg-[#00173C] hover:border-[#2261CA33] transition-colors cursor-pointer"
onClick={onEnterSelectionMode}
>
-
+
)}
@@ -675,7 +675,7 @@ export function MemoriesGrid({
onClick={handleBulkDeleteClick}
disabled={selectedDocumentIds.size === 0 || isBulkDeleting}
>
-
+
Delete
{selectedDocumentIds.size > 0 && (
@@ -690,7 +690,7 @@ export function MemoriesGrid({
className="flex items-center gap-1 text-xs px-3 h-7 rounded-full text-[#737373] hover:text-white hover:bg-white/5 transition-colors cursor-pointer"
onClick={onClearSelection}
>
-
+
Done
@@ -866,9 +866,9 @@ function ProcessingBadge() {
return (
-
-
-
+
+
+
{isSelected ? (
-
-
+
+
) : (
-
+
)}
)}
@@ -1062,7 +1062,7 @@ const DocumentCard = memo(
) && (
{document.url &&
- !document.url.includes("files.supermemory.ai") &&
+ !isSupermemoryFileUrl(document.url) &&
(document.title ||
(!document.url.includes("x.com") &&
!document.url.includes("twitter.com"))) && (
@@ -1080,7 +1080,7 @@ const DocumentCard = memo(
{
e.currentTarget.style.display = "none"
}}
diff --git a/apps/web/components/memory-graph/graph-card.tsx b/apps/web/components/memory-graph/graph-card.tsx
index 807f594b1..0269aab8d 100644
--- a/apps/web/components/memory-graph/graph-card.tsx
+++ b/apps/web/components/memory-graph/graph-card.tsx
@@ -157,7 +157,7 @@ export const GraphCard = memo
(
{isLoading ? (
) : documentCount > 0 || memoryCount > 0 ? (
(
)}
-
+
diff --git a/apps/web/components/memory-graph/memory-graph-wrapper.tsx b/apps/web/components/memory-graph/memory-graph-wrapper.tsx
index 6b28f6a18..2491a82cf 100644
--- a/apps/web/components/memory-graph/memory-graph-wrapper.tsx
+++ b/apps/web/components/memory-graph/memory-graph-wrapper.tsx
@@ -59,7 +59,7 @@ export function MemoryGraph({
})
return (
-
+
- Share what you want next—we’d love a quick call.
+ Share what you want next. We’d love a quick call.
{isSelected && (
-
+
)}
) : (
- {icon === "check" ? (
-
+
+
- ) : (
-
- )}
-
+ {name}
+
+ {highlight && (
+
+ RECOMMENDED
+
+ )}
+
+
+
+
+ {price}
+
+ {period && (
+
+ {period}
+
+ )}
+
+
+
+ {description}
+
+
+
- {text}
-
+
+
+ {credits}
+
+
+ of usage included
+
+
+
+
+
+ {features.map((text) => (
+
+
+ {text}
+
+ ))}
+
)
}
@@ -152,8 +238,8 @@ export default function Account() {
}
const {
- tokensUsed,
- searchesUsed,
+ usdIncluded,
+ usdSpent,
planUsagePct,
currentPlan,
hasPaidPlan,
@@ -161,6 +247,12 @@ export default function Account() {
daysRemaining,
} = useTokenUsage(autumn)
+ const formatUsd = (n: number) =>
+ n.toLocaleString(undefined, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })
+
const planDisplayNames: Record
= {
free: "Free",
pro: "Pro",
@@ -172,13 +264,19 @@ export default function Account() {
const handleUpgrade = async () => {
setIsUpgrading(true)
try {
- await autumn.attach({
+ const result = await autumn.attach({
planId: "api_pro",
- successUrl: "https://app.supermemory.ai/settings#account",
+ successUrl: `${window.location.origin}/settings#account`,
})
- window.location.reload()
+ if (result?.paymentUrl) {
+ window.open(result.paymentUrl, "_self")
+ return
+ }
+ autumn.refetch?.()
} catch (error) {
console.error(error)
+ toast.error("Failed to start checkout. Please try again.")
+ } finally {
setIsUpgrading(false)
}
}
@@ -418,7 +516,7 @@ export default function Account() {
? "#ef4444"
: "linear-gradient(to right, #4BA0FA 80%, #002757 100%)",
}}
- title={`${formatUsageNumber(tokensUsed)} tokens · ${formatUsageNumber(searchesUsed)} queries`}
+ title={`$${formatUsd(usdSpent)} of $${formatUsd(usdIncluded)} used`}
/>
- {formatUsageNumber(tokensUsed)} tokens ·{" "}
- {formatUsageNumber(searchesUsed)} queries
- {daysRemaining !== null && (
- <>
- {" · resets in "}
- {daysRemaining} day{daysRemaining !== 1 ? "s" : ""}
- >
- )}
+ {daysRemaining !== null
+ ? `Resets in ${daysRemaining} day${daysRemaining !== 1 ? "s" : ""}`
+ : ""}
@@ -457,73 +550,6 @@ export default function Account() {
Manage billing
-
-
- {/* Free plan card */}
-
-
- {/* Current plan card - highlighted */}
-
-
-
- {planDisplayNames[currentPlan]} plan
-
-
- ACTIVE
-
-
-
-
-
-
>
) : (
<>
@@ -576,7 +602,7 @@ export default function Account() {
width: `${planUsagePct}%`,
background: planUsagePct > 80 ? "#ef4444" : "#0054AD",
}}
- title={`${formatUsageNumber(tokensUsed)} tokens · ${formatUsageNumber(searchesUsed)} queries`}
+ title={`$${formatUsd(usdSpent)} of $${formatUsd(usdIncluded)} used`}
/>
- {formatUsageNumber(tokensUsed)} tokens ·{" "}
- {formatUsageNumber(searchesUsed)} queries
- {daysRemaining !== null && (
- <>
- {" · resets in "}
- {daysRemaining} day{daysRemaining !== 1 ? "s" : ""}
- >
- )}
+ {daysRemaining !== null
+ ? `Resets in ${daysRemaining} day${daysRemaining !== 1 ? "s" : ""}`
+ : ""}
@@ -618,7 +639,7 @@ export default function Account() {
{isUpgrading || isCheckingStatus || autumn.isLoading ? (
<>
- Upgrading...
+ Upgrading…
>
) : (
"Upgrade to Pro - $19/month"
@@ -628,72 +649,32 @@ export default function Account() {
- {/* Free plan card */}
-
-
- {/* Pro plan card */}
-
- {/* Header with badge */}
-
-
- Pro plan
-
-
- RECOMMENDED
-
-
-
- {/* Inset highlight */}
-
-
+
+
>
)}
diff --git a/apps/web/components/settings/connections-mcp.tsx b/apps/web/components/settings/connections-mcp.tsx
index 270402985..8c881498d 100644
--- a/apps/web/components/settings/connections-mcp.tsx
+++ b/apps/web/components/settings/connections-mcp.tsx
@@ -423,13 +423,18 @@ export default function ConnectionsMCP() {
// Upgrade handler
const handleUpgrade = async () => {
try {
- await autumn.attach({
+ const result = await autumn.attach({
planId: "api_pro",
- successUrl: "https://app.supermemory.ai/settings#connections",
+ successUrl: `${window.location.origin}/settings#connections`,
})
- window.location.reload()
+ if (result?.paymentUrl) {
+ window.open(result.paymentUrl, "_self")
+ return
+ }
+ autumn.refetch?.()
} catch (error) {
console.error(error)
+ toast.error("Failed to start checkout. Please try again.")
}
}
diff --git a/apps/web/components/settings/integrations.tsx b/apps/web/components/settings/integrations.tsx
index 72893eefc..dc3e58184 100644
--- a/apps/web/components/settings/integrations.tsx
+++ b/apps/web/components/settings/integrations.tsx
@@ -273,7 +273,7 @@ export default function Integrations() {