Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/content/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default defineConfig({
{ text: 'Elysia', link: '/docs/integrations/elysia' },
{ text: 'SvelteKit', link: '/docs/integrations/svelte-kit' },
{ text: 'Remix', link: '/docs/integrations/remix' },
{ text: 'SolidStart', link: '/docs/integrations/solid-start' },
{ text: 'Solid Start', link: '/docs/integrations/solid-start' },
{ text: 'Astro', link: '/docs/integrations/astro' },
{ text: 'React Native', link: '/docs/integrations/react-native' },
{ text: 'Electron', link: '/docs/integrations/electron' },
Expand Down
3 changes: 2 additions & 1 deletion apps/content/docs/integrations/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Next.js doesn’t natively support isomorphic functions, so you need a workaroun
::: code-group

```ts [lib/orpc.ts]
import { RPCLink } from '@orpc/client/fetch'
import type { headers } from 'next/headers'

declare global {
Expand Down Expand Up @@ -132,7 +133,7 @@ This only shows how to configure the link. For full client examples, see [Client

## Optimize SSR

To reduce HTTP requests and improve latency during SSR, you can utilize a [Server-Side Client](/docs/client/server-side) during SSR. Below is a quick setup, see [Optimize SSR](/docs/best-practices/optimize-ssr) for a more details.
To reduce HTTP requests and improve latency during SSR, you can utilize a [Server-Side Client](/docs/client/server-side) during SSR. Below is a quick setup, see [Optimize SSR](/docs/best-practices/optimize-ssr) for more details.

::: code-group

Expand Down
88 changes: 85 additions & 3 deletions apps/content/docs/integrations/solid-start.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
title: SolidStart Integration
description: Integrate oRPC with SolidStart
title: Solid Start Integration
description: Setup oRPC within a Solid Start application
---

# SolidStart Integration

[SolidStart](https://start.solidjs.com/) is a full stack JavaScript framework for building web applications with SolidJS. For additional context, refer to the [HTTP Adapter](/docs/adapters/http) guide.

## Basic
## Server

::: code-group

Expand All @@ -26,6 +26,7 @@ async function handle({ request }: APIEvent) {
return response ?? new Response('Not Found', { status: 404 })
}

export const HEAD = handle
export const GET = handle
export const POST = handle
export const PUT = handle
Expand All @@ -42,3 +43,84 @@ export * from './[...rest]'
::: info
The `handler` can be any supported oRPC handler, such as [RPCHandler](/docs/rpc-handler), [OpenAPIHandler](/docs/openapi/openapi-handler), or another custom handler.
:::

## Client

On the client, use `getRequestEvent` to provide a headers function that works seamlessly with SSR. This enables usage in both server and browser environments.

```ts
import { RPCLink } from '@orpc/client/fetch'
import { getRequestEvent } from 'solid-js/web'

const link = new RPCLink({
url: new URL('/api/rpc', typeof window !== 'undefined' ? window.location.href : 'http://localhost:3000'),
headers: () => Object.fromEntries(getRequestEvent()?.request.headers ?? []),
})
```

:::info
This only shows how to configure the link. For full client examples, see [Client-Side Clients](/docs/client/client-side).
:::

## Optimize SSR

To reduce HTTP requests and improve latency during SSR, you can utilize a [Server-Side Client](/docs/client/server-side) during SSR. Below is a quick setup, see [Optimize SSR](/docs/best-practices/optimize-ssr) for more details.

::: code-group

```ts [src/lib/orpc.ts]
if (typeof window === 'undefined') {
await import('./orpc.server')
}

import type { RouterClient } from '@orpc/server'
import { RPCLink } from '@orpc/client/fetch'
import { createORPCClient } from '@orpc/client'

declare global {
var $client: RouterClient<typeof router> | undefined
}

const link = new RPCLink({
url: () => {
if (typeof window === 'undefined') {
throw new Error('RPCLink is not allowed on the server side.')
}

return new URL('/rpc', window.location.href)
},
})

/**
* Fallback to client-side client if server-side client is not available.
*/
export const client: RouterClient<typeof router> = globalThis.$client ?? createORPCClient(link)
```

```ts [src/lib/orpc.server.ts]
import { createRouterClient } from '@orpc/server'
import { getRequestEvent } from 'solid-js/web'

if (typeof window !== 'undefined') {
throw new Error('This file should not be imported in the browser')
}

globalThis.$client = createRouterClient(router, {
/**
* Provide initial context if needed.
*
* Because this client instance is shared across all requests,
* only include context that's safe to reuse globally.
* For per-request context, use middleware context or pass a function as the initial context.
*/
context: async () => {
const headers = getRequestEvent()?.request.headers

return {
headers,
}
},
})
```

:::
3 changes: 2 additions & 1 deletion apps/content/docs/integrations/tanstack-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ The `handler` can be any supported oRPC handler, including [RPCHandler](/docs/rp
On the client, use `createIsomorphicFn` to provide a headers function that works seamlessly with SSR. This enables usage in both server and browser environments.

```ts
import { RPCLink } from '@orpc/client/fetch'
import { getHeaders } from '@tanstack/react-start/server'
import { createIsomorphicFn } from '@tanstack/react-start'

Expand All @@ -73,7 +74,7 @@ This only shows how to configure the link. For full client examples, see [Client

## Optimize SSR

To reduce HTTP requests and improve latency during SSR, you can utilize a [Server-Side Client](/docs/client/server-side) during SSR. Below is a quick setup, see [Optimize SSR](/docs/best-practices/optimize-ssr) for a more details.
To reduce HTTP requests and improve latency during SSR, you can utilize a [Server-Side Client](/docs/client/server-side) during SSR. Below is a quick setup, see [Optimize SSR](/docs/best-practices/optimize-ssr) for more details.

::: code-group

Expand Down
6 changes: 3 additions & 3 deletions apps/content/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
"@pinia/colada": "^0.16.1",
"@shikijs/vitepress-twoslash": "^3.0.0",
"@tanstack/react-query": "^5.75.7",
"@tanstack/solid-query": "^5.72.3",
"@tanstack/svelte-query": "^5.72.3",
"@tanstack/vue-query": "^5.72.3",
"@tanstack/solid-query": "^5.77.2",
"@tanstack/svelte-query": "^5.77.2",
"@tanstack/vue-query": "^5.77.2",
"@types/node": "^22.15.17",
"openai": "^4.93.0",
"pinia": "^3.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"@orpc/tanstack-query": "workspace:*"
},
"devDependencies": {
"@tanstack/react-query": "^5.72.3",
"@tanstack/react-query": "^5.77.2",
"react": "^19.1.0",
"zod": "^3.25.11"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/solid-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"@orpc/tanstack-query": "workspace:*"
},
"devDependencies": {
"@tanstack/solid-query": "^5.72.3",
"@tanstack/solid-query": "^5.77.2",
"zod": "^3.25.11"
}
}
2 changes: 1 addition & 1 deletion packages/svelte-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"@orpc/tanstack-query": "workspace:*"
},
"devDependencies": {
"@tanstack/svelte-query": "^5.72.3",
"@tanstack/svelte-query": "^5.77.2",
"zod": "^3.25.11"
}
}
2 changes: 1 addition & 1 deletion packages/tanstack-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@orpc/shared": "workspace:*"
},
"devDependencies": {
"@tanstack/query-core": "^5.72.3",
"@tanstack/query-core": "^5.77.2",
"zod": "^3.25.11"
}
}
2 changes: 1 addition & 1 deletion packages/vue-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@
"@orpc/tanstack-query": "workspace:*"
},
"devDependencies": {
"@tanstack/vue-query": "^5.72.3"
"@tanstack/vue-query": "^5.77.2"
}
}
2 changes: 1 addition & 1 deletion playgrounds/electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@orpc/react-query": "next",
"@orpc/server": "next",
"@orpc/zod": "next",
"@tanstack/react-query": "^5.72.3",
"@tanstack/react-query": "^5.77.2",
"@types/node": "^22.15.18",
"@types/react": "^19.1.4",
"@types/react-dom": "^19.1.5",
Expand Down
2 changes: 1 addition & 1 deletion playgrounds/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@orpc/server": "next",
"@orpc/vue-query": "next",
"@orpc/zod": "next",
"@tanstack/vue-query": "^5.72.3",
"@tanstack/vue-query": "^5.77.2",
"nuxt": "^3.16.2",
"vue": "latest",
"vue-router": "latest",
Expand Down
9 changes: 8 additions & 1 deletion playgrounds/solid-start/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import { defineConfig } from '@solidjs/start/config'
import topLevelAwait from 'vite-plugin-top-level-await'

export default defineConfig({})
export default defineConfig({
vite: {
plugins: [
topLevelAwait(),
],
},
})
5 changes: 3 additions & 2 deletions playgrounds/solid-start/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
"@orpc/zod": "next",
"@solidjs/router": "^0.15.3",
"@solidjs/start": "^1.1.0",
"@tanstack/solid-query": "^5.72.3",
"@tanstack/solid-query": "^5.77.2",
"solid-js": "^1.9.5",
"vinxi": "^0.5.4",
"vinxi": "^0.5.6",
"vite-plugin-top-level-await": "^1.5.0",
"zod": "^3.25.11"
}
}
14 changes: 11 additions & 3 deletions playgrounds/solid-start/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@ import { FileRoutes } from '@solidjs/start/router'
import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
import { Suspense } from 'solid-js'

const queryClient = new QueryClient()

export default function App() {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
experimental_prefetchInRender: true,
},
},
})
Comment on lines +7 to +13
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Move QueryClient instantiation outside the component to prevent recreation on each render.

The QueryClient is being instantiated inside the App component, which means a new instance will be created on every render. This can lead to performance issues and loss of cached data.

+const queryClient = new QueryClient({
+  defaultOptions: {
+    queries: {
+      experimental_prefetchInRender: true,
+    },
+  },
+})
+
 export default function App() {
-  const queryClient = new QueryClient({
-    defaultOptions: {
-      queries: {
-        experimental_prefetchInRender: true,
-      },
-    },
-  })
-
   return (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const queryClient = new QueryClient({
defaultOptions: {
queries: {
experimental_prefetchInRender: true,
},
},
})
const queryClient = new QueryClient({
defaultOptions: {
queries: {
experimental_prefetchInRender: true,
},
},
})
export default function App() {
return (
/* ... */
🤖 Prompt for AI Agents
In playgrounds/solid-start/src/app.tsx around lines 7 to 13, the QueryClient is
instantiated inside the component, causing it to be recreated on every render.
To fix this, move the QueryClient instantiation outside the component function
so that the same instance is reused across renders, preserving cache and
improving performance.


return (
<QueryClientProvider client={queryClient}>
<Router
root={props => (
<>
<Suspense>{props.children}</Suspense>
<Suspense fallback={<p>Loading...</p>}>
{props.children}
</Suspense>
</>
)}
>
Expand Down
29 changes: 29 additions & 0 deletions playgrounds/solid-start/src/lib/orpc.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createRouterClient } from '@orpc/server'
import { getRequestEvent } from 'solid-js/web'
import { router } from '~/router'

if (typeof window !== 'undefined') {
throw new Error('This file should not be imported in the browser')
}

/**
* This is part of the Optimize SSR setup.
*
* @see {@link https://orpc.unnoq.com/docs/integrations/solid-start#optimize-ssr}
*/
globalThis.$client = createRouterClient(router, {
/**
* Provide initial context if needed.
*
* Because this client instance is shared across all requests,
* only include context that's safe to reuse globally.
* For per-request context, use middleware context or pass a function as the initial context.
*/
context: async () => {
const headers = getRequestEvent()?.request.headers

return {
headers,
}
},
})
17 changes: 12 additions & 5 deletions playgrounds/solid-start/src/lib/orpc.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
if (typeof window === 'undefined') {
await import('./orpc.server')
}

import type { RouterClient } from '@orpc/server'
import type { router } from '~/router'
import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
import { createORPCSolidQueryUtils } from '@orpc/solid-query'
import { getRequestEvent } from 'solid-js/web'

declare global {
var $client: RouterClient<typeof router> | undefined
}

const rpcLink = new RPCLink({
const link = new RPCLink({
url: new URL('/rpc', typeof window !== 'undefined' ? window.location.href : 'http://localhost:3000'),
headers: () => ({
Authorization: 'Bearer default-token',
}),
headers: () => Object.fromEntries(getRequestEvent()?.request.headers ?? []),
})

export const client: RouterClient<typeof router> = createORPCClient(rpcLink)
export const client: RouterClient<typeof router> = globalThis.$client ?? createORPCClient(link)

export const orpc = createORPCSolidQueryUtils(client)
4 changes: 2 additions & 2 deletions playgrounds/solid-start/src/routes/orpc-mutation.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { orpc } from '~/lib/orpc'
import { createMutation, useQueryClient } from '@tanstack/solid-query'
import { useMutation, useQueryClient } from '@tanstack/solid-query'

export function CreatePlanetMutationForm() {
const queryClient = useQueryClient()

const mutation = createMutation(
const mutation = useMutation(
() => orpc.planet.create.mutationOptions({
onSuccess() {
queryClient.invalidateQueries({
Expand Down
Loading