packages/eslint-plugin-start/no-client-code-in-server-component.md
no-client-code-in-server-componentDisallow client-only code inside createServerComponent().
This rule is meant to catch common "RSC boundary" mistakes in TanStack Start:
window, document)onClick, etc.)This rule treats the callback passed to createServerComponent(...) as server-only, and also treats any components rendered from within that callback as server-only unless they cross a 'use client' boundary.
Supported call patterns:
createServerComponent(() => <div />)createServerComponent(async () => <div />)createServerComponent(MyComponent) (direct reference)The rule flags common React hooks that require a client runtime (eg useState, useEffect).
Allowed hooks:
useId is allowed by default.allowedServerHooks option.Any global that exists in globals.browser but not globals.node is treated as browser-only and disallowed.
Examples:
windowdocumentnavigatorJSX props that look like React event handlers (eg onClick, onChange, etc.) are disallowed in server components.
Passing a function through props is disallowed because server-to-client serialization can’t serialize functions.
Class components are disallowed because they rely on client-side lifecycle.
createServerComponent callback, the error is reported at the violating node.type Options = [
{
allowedServerHooks?: string[]
},
]
allowedServerHooksAdd additional hook names that should be allowed in server components.
Example:
{
rules: {
'@tanstack/start/no-client-code-in-server-component': [
'error',
{
allowedServerHooks: ['useMyServerSafeHook'],
},
],
},
}
import { createServerComponent } from '@tanstack/react-start/rsc'
import { useState } from 'react'
export const Server = createServerComponent(() => {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
})
import { createServerComponent } from '@tanstack/react-start/rsc'
export const Server = createServerComponent(() => {
return <div>{window.location.href}</div>
})
// server.tsx
import { createServerComponent } from '@tanstack/react-start/rsc'
import { Middle } from './middle'
export const Server = createServerComponent(() => <Middle />)
// middle.tsx
import { ClientThing } from './client-thing'
export function Middle() {
return <ClientThing />
}
// client-thing.tsx
export function ClientThing() {
return <button onClick={() => {}}>Click</button>
}
import { createServerComponent } from '@tanstack/react-start/rsc'
export const Server = createServerComponent(({ ActionButton }) => {
return (
<div>
<ActionButton />
</div>
)
})
src/rules/no-client-code-in-server-component/
no-client-code-in-server-component.rule.ts
transitive-analyzer.ts
violation-detector.ts
constants.ts
src/shared/
use-client-resolver.ts