Skip to content

Commit 0bbb633

Browse files
committed
fix(nuqs): revert landing-page param migrations and tighten workspace URL-state
- Revert integrations/models landing pages to static SEO HTML (drop nuqs migration + their search-params files) - MCP settings: refresh tools only for an initial deep-linked server id, not on subsequent user selections - Add a Suspense boundary with real chrome around the nuqs-using integration detail page - Trim inaccurate "server component reads these params" TSDoc from search-params files (createSearchParamsCache is unused) - Export mcpServerIdUrlKeys from the settings search-params file instead of inlining the options in mcp.tsx - Convert two new relative imports (logs use-log-filters, tables loading) to absolute - Wrap setSelectedCategory in useCallback; clear active skillId edit param when opening the create-skill form
1 parent df0df7e commit 0bbb633

17 files changed

Lines changed: 67 additions & 141 deletions

File tree

apps/sim/app/(landing)/integrations/(shell)/page.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Suspense } from 'react'
21
import type { Metadata } from 'next'
32
import { Badge } from '@/components/emcn'
43
import { SITE_URL } from '@/lib/core/utils/urls'
@@ -206,9 +205,7 @@ export default function IntegrationsPage() {
206205
All Integrations
207206
</h2>
208207
</div>
209-
<Suspense fallback={null}>
210-
<IntegrationGrid integrations={allIntegrations} />
211-
</Suspense>
208+
<IntegrationGrid integrations={allIntegrations} />
212209
</section>
213210

214211
<div className='h-px w-full bg-[var(--landing-bg-elevated)]' />

apps/sim/app/(landing)/integrations/components/integration-grid.tsx

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
'use client'
22

3-
import { useEffect, useRef, useState } from 'react'
4-
import { useQueryStates } from 'nuqs'
3+
import { useState } from 'react'
54
import { ChipInput, Search } from '@/components/emcn'
65
import { blockTypeToIconMap, formatIntegrationType, type Integration } from '@/lib/integrations'
76
import { IntegrationRow } from '@/app/(landing)/integrations/components/integration-card'
8-
import {
9-
integrationsDirectoryParsers,
10-
integrationsDirectoryUrlKeys,
11-
} from '@/app/(landing)/integrations/search-params'
12-
import { useDebounce } from '@/hooks/use-debounce'
137

148
const PILL_BASE =
159
'rounded-[5px] border border-[var(--landing-border-strong)] px-[9px] py-0.5 text-[13.5px] text-[var(--landing-text)] transition-colors' as const
@@ -21,29 +15,8 @@ interface IntegrationGridProps {
2115
}
2216

2317
export function IntegrationGrid({ integrations }: IntegrationGridProps) {
24-
const [{ search: urlQuery, category: urlCategory }, setDirectoryFilters] = useQueryStates(
25-
integrationsDirectoryParsers,
26-
integrationsDirectoryUrlKeys
27-
)
28-
29-
const [query, setQuery] = useState(urlQuery)
30-
const debouncedQuery = useDebounce(query, 300)
31-
32-
useEffect(() => {
33-
setDirectoryFilters({ search: debouncedQuery.length > 0 ? debouncedQuery : null })
34-
}, [debouncedQuery, setDirectoryFilters])
35-
36-
const lastSyncedUrlSearchRef = useRef(urlQuery)
37-
useEffect(() => {
38-
if (urlQuery === lastSyncedUrlSearchRef.current) return
39-
lastSyncedUrlSearchRef.current = urlQuery
40-
setQuery((current) => (current === urlQuery ? current : urlQuery))
41-
}, [urlQuery])
42-
43-
const activeCategory = urlCategory.length > 0 ? urlCategory : null
44-
const setActiveCategory = (category: string | null) => {
45-
setDirectoryFilters({ category })
46-
}
18+
const [query, setQuery] = useState('')
19+
const [activeCategory, setActiveCategory] = useState<string | null>(null)
4720

4821
const counts = new Map<string, number>()
4922
for (const i of integrations) {

apps/sim/app/(landing)/integrations/search-params.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

apps/sim/app/(landing)/models/(shell)/page.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Suspense } from 'react'
21
import type { Metadata } from 'next'
32
import { Badge } from '@/components/emcn'
43
import { SITE_URL } from '@/lib/core/utils/urls'
@@ -226,9 +225,7 @@ export default function ModelsPage() {
226225
All models
227226
</h2>
228227
</div>
229-
<Suspense fallback={null}>
230-
<ModelDirectory />
231-
</Suspense>
228+
<ModelDirectory />
232229
</section>
233230

234231
<div className='h-px w-full bg-[var(--landing-bg-elevated)]' />

apps/sim/app/(landing)/models/components/model-directory.tsx

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
'use client'
22

3-
import { useEffect, useMemo, useRef, useState } from 'react'
3+
import { useMemo, useState } from 'react'
44
import Link from 'next/link'
5-
import { useQueryStates } from 'nuqs'
65
import { Input } from '@/components/emcn'
76
import { ChevronArrow, ProviderIcon } from '@/app/(landing)/models/components/model-primitives'
8-
import { modelDirectoryParsers, modelDirectoryUrlKeys } from '@/app/(landing)/models/search-params'
97
import {
108
type CatalogModel,
119
type CatalogProvider,
@@ -14,32 +12,10 @@ import {
1412
MODEL_PROVIDERS_WITH_CATALOGS,
1513
MODEL_PROVIDERS_WITH_DYNAMIC_CATALOGS,
1614
} from '@/app/(landing)/models/utils'
17-
import { useDebounce } from '@/hooks/use-debounce'
1815

1916
export function ModelDirectory() {
20-
const [{ search: urlQuery, provider: urlProvider }, setModelFilters] = useQueryStates(
21-
modelDirectoryParsers,
22-
modelDirectoryUrlKeys
23-
)
24-
25-
const [query, setQuery] = useState(urlQuery)
26-
const debouncedQuery = useDebounce(query, 300)
27-
28-
useEffect(() => {
29-
setModelFilters({ search: debouncedQuery.length > 0 ? debouncedQuery : null })
30-
}, [debouncedQuery, setModelFilters])
31-
32-
const lastSyncedUrlSearchRef = useRef(urlQuery)
33-
useEffect(() => {
34-
if (urlQuery === lastSyncedUrlSearchRef.current) return
35-
lastSyncedUrlSearchRef.current = urlQuery
36-
setQuery((current) => (current === urlQuery ? current : urlQuery))
37-
}, [urlQuery])
38-
39-
const activeProviderId = urlProvider.length > 0 ? urlProvider : null
40-
const setActiveProviderId = (providerId: string | null) => {
41-
setModelFilters({ provider: providerId })
42-
}
17+
const [query, setQuery] = useState('')
18+
const [activeProviderId, setActiveProviderId] = useState<string | null>(null)
4319

4420
const providerOptions = useMemo(
4521
() =>

apps/sim/app/(landing)/models/search-params.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

apps/sim/app/workspace/[workspaceId]/files/search-params.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ const parseAsNewFlag = createParser<boolean>({
1515
})
1616

1717
/**
18-
* Co-located, typed URL query-param definitions for the Files feature. Both the
19-
* client (`Files`) and any server component that reads these params consume this
20-
* single source of truth.
18+
* Co-located, typed URL query-param definitions for the Files feature. The
19+
* client (`Files`) consumes this typed param definition as the single source of
20+
* truth.
2121
*
2222
* - `folderId` is the currently open folder; it is shareable, bookmarkable, and
2323
* navigations between folders belong in the browser history (`history: 'push'`).

apps/sim/app/workspace/[workspaceId]/integrations/[block]/page.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { Suspense } from 'react'
2+
import { ArrowLeft } from 'lucide-react'
13
import type { Metadata } from 'next'
24
import { notFound } from 'next/navigation'
5+
import { ChipLink } from '@/components/emcn'
36
import { INTEGRATIONS } from '@/lib/integrations'
47
import { IntegrationBlockDetail } from '@/app/workspace/[workspaceId]/integrations/[block]/integration-block-detail'
58

@@ -24,5 +27,19 @@ export default async function IntegrationBlockPage({
2427
const integration = INTEGRATIONS.find((i) => i.slug === block)
2528
if (!integration) notFound()
2629

27-
return <IntegrationBlockDetail integration={integration} workspaceId={workspaceId} />
30+
return (
31+
<Suspense
32+
fallback={
33+
<div className='flex h-full flex-col bg-[var(--bg)]'>
34+
<div className='flex flex-shrink-0 items-center bg-[var(--bg)] px-[16px] pt-[8.5px] pb-[8.5px]'>
35+
<ChipLink href={`/workspace/${workspaceId}/integrations`} leftIcon={ArrowLeft}>
36+
Integrations
37+
</ChipLink>
38+
</div>
39+
</div>
40+
}
41+
>
42+
<IntegrationBlockDetail integration={integration} workspaceId={workspaceId} />
43+
</Suspense>
44+
)
2845
}

apps/sim/app/workspace/[workspaceId]/integrations/integrations.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { type ComponentType, useEffect, useMemo, useRef, useState } from 'react'
3+
import { type ComponentType, useCallback, useEffect, useMemo, useRef, useState } from 'react'
44
import Link from 'next/link'
55
import { useParams } from 'next/navigation'
66
import { useQueryStates } from 'nuqs'
@@ -184,9 +184,12 @@ export function Integrations() {
184184
setSearchTerm((current) => (current === urlSearchTerm ? current : urlSearchTerm))
185185
}, [urlSearchTerm])
186186

187-
const setSelectedCategory = (category: string) => {
188-
setIntegrationFilters({ category })
189-
}
187+
const setSelectedCategory = useCallback(
188+
(category: string) => {
189+
setIntegrationFilters({ category })
190+
},
191+
[setIntegrationFilters]
192+
)
190193

191194
const categoryOptions = [
192195
ALL_CATEGORY,

apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/search-params.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { parseAsInteger, parseAsString } from 'nuqs/server'
22

33
/**
44
* Co-located, typed URL query-param definitions for the knowledge document
5-
* (chunk list + inline chunk editor) page. Both the client (`Document`) and any
6-
* server component that reads these params consume this single source of truth.
5+
* (chunk list + inline chunk editor) page. The client (`Document`) consumes this
6+
* typed param definition as the single source of truth.
77
*
88
* - `page` is the chunk pagination page, shareable and bookmarkable. It defaults
99
* to 1 and clears from the URL at the default to keep links clean.

0 commit comments

Comments
 (0)