Modern full-stack React framework with SSR, streaming, server functions, and API routes powered by TanStack Router and Vite.
—
Isomorphic functions allow you to create functions with different implementations for client and server environments. This enables code that adapts to its execution context, providing optimal behavior on both sides of your application.
Creates a function that can have different implementations on the client and server, with implementations defaulting to no-op functions when not provided.
/**
* Creates an isomorphic function with different client/server implementations
* @returns IsomorphicFnBase for chaining client/server implementations
*/
function createIsomorphicFn(): IsomorphicFnBase;
interface IsomorphicFnBase {
/** Define the server-side implementation */
server<TArgs extends Array<any>, TServer>(
serverImpl: (...args: TArgs) => TServer
): ServerOnlyFn<TArgs, TServer>;
/** Define the client-side implementation */
client<TArgs extends Array<any>, TClient>(
clientImpl: (...args: TArgs) => TClient
): ClientOnlyFn<TArgs, TClient>;
}Usage Examples:
import { createIsomorphicFn } from "@tanstack/react-start";
// Logging function with different implementations
const log = createIsomorphicFn()
.server((message: string) => {
// Server-side: log to console with timestamp
console.log(`[${new Date().toISOString()}] ${message}`);
})
.client((message: string) => {
// Client-side: log to browser console
console.log(`[CLIENT] ${message}`);
});
// Storage function with different backends
const getItem = createIsomorphicFn()
.server((key: string) => {
// Server-side: use environment variables or file system
return process.env[key] || null;
})
.client((key: string) => {
// Client-side: use localStorage
return localStorage.getItem(key);
});Creates a function that only executes on the server, with the option to add a client-side implementation later.
/**
* Creates a server-only function with optional client implementation
* @param serverImpl - The server-side implementation
* @returns ServerOnlyFn that can be extended with client implementation
*/
function createServerOnlyFn<TArgs extends Array<any>, TServer>(
serverImpl: (...args: TArgs) => TServer
): ServerOnlyFn<TArgs, TServer>;
interface ServerOnlyFn<TArgs extends Array<any>, TServer>
extends IsomorphicFn<TArgs, TServer> {
/** Add a client-side implementation */
client<TClient>(
clientImpl: (...args: TArgs) => TClient
): IsomorphicFn<TArgs, TServer, TClient>;
}Usage Examples:
import { createServerOnlyFn } from "@tanstack/react-start";
// Database access function (server-only by default)
const getUser = createServerOnlyFn((id: string) => {
// Server-side: access database
return db.user.findUnique({ where: { id } });
});
// Add client-side fallback
const getUserWithFallback = createServerOnlyFn((id: string) => {
return db.user.findUnique({ where: { id } });
}).client((id: string) => {
// Client-side: fetch from API
return fetch(`/api/users/${id}`).then(r => r.json());
});Creates a function that only executes on the client, with the option to add a server-side implementation later.
/**
* Creates a client-only function with optional server implementation
* @param clientImpl - The client-side implementation
* @returns ClientOnlyFn that can be extended with server implementation
*/
function createClientOnlyFn<TArgs extends Array<any>, TClient>(
clientImpl: (...args: TArgs) => TClient
): ClientOnlyFn<TArgs, TClient>;
interface ClientOnlyFn<TArgs extends Array<any>, TClient>
extends IsomorphicFn<TArgs, undefined, TClient> {
/** Add a server-side implementation */
server<TServer>(
serverImpl: (...args: TArgs) => TServer
): IsomorphicFn<TArgs, TServer, TClient>;
}Usage Examples:
import { createClientOnlyFn } from "@tanstack/react-start";
// Analytics tracking function (client-only by default)
const trackEvent = createClientOnlyFn((event: string, data: any) => {
// Client-side: send to analytics service
analytics.track(event, data);
});
// Add server-side implementation for SSR contexts
const trackEventWithServer = createClientOnlyFn((event: string, data: any) => {
analytics.track(event, data);
}).server((event: string, data: any) => {
// Server-side: log for debugging or send to server analytics
console.log(`[ANALYTICS] ${event}:`, data);
});Isomorphic functions automatically detect their execution environment and call the appropriate implementation:
import { createIsomorphicFn } from "@tanstack/react-start";
const getCurrentUrl = createIsomorphicFn()
.server(() => {
// Server-side: construct URL from request
return `${process.env.BASE_URL}/current-page`;
})
.client(() => {
// Client-side: use window.location
return window.location.href;
});
// This will call the appropriate implementation based on context
const url = getCurrentUrl();import { createIsomorphicFn } from "@tanstack/react-start";
const formatDate = createIsomorphicFn()
.server((date: Date) => {
// Server-side: use server timezone
return date.toLocaleString('en-US', {
timeZone: process.env.SERVER_TIMEZONE || 'UTC'
});
})
.client((date: Date) => {
// Client-side: use user's timezone
return date.toLocaleString();
});// Base isomorphic function type
interface IsomorphicFn<
TArgs extends Array<any> = [],
TServer = undefined,
TClient = undefined
> {
(...args: TArgs): TServer | TClient;
}
// Server-only function with optional client extension
interface ServerOnlyFn<TArgs extends Array<any>, TServer>
extends IsomorphicFn<TArgs, TServer> {
client<TClient>(
clientImpl: (...args: TArgs) => TClient
): IsomorphicFn<TArgs, TServer, TClient>;
}
// Client-only function with optional server extension
interface ClientOnlyFn<TArgs extends Array<any>, TClient>
extends IsomorphicFn<TArgs, undefined, TClient> {
server<TServer>(
serverImpl: (...args: TArgs) => TServer
): IsomorphicFn<TArgs, TServer, TClient>;
}
// Base interface for creating isomorphic functions
interface IsomorphicFnBase extends IsomorphicFn {
server<TArgs extends Array<any>, TServer>(
serverImpl: (...args: TArgs) => TServer
): ServerOnlyFn<TArgs, TServer>;
client<TArgs extends Array<any>, TClient>(
clientImpl: (...args: TArgs) => TClient
): ClientOnlyFn<TArgs, TClient>;
}Install with Tessl CLI
npx tessl i tessl/npm-tanstack--react-start