TanStack Agent Skills

repository·main·Indexed 41 days ago

https://github.com/deckardger/tanstack-agent-skills

Structured, high-fidelity guidelines and best practices for AI coding agents working with the TanStack ecosystem, including TanStack Query, Router, Start, and their integrations. Provides specialized rules for data fetching, type-safe routing, full-stack React applications, and SSR integration using the Agent Skills standard.

Tokens
129.5K
Snippets
288
Records
343
Agent score
51%

What's inside TanStack Agent Skills

  1. Overview of TanStack Integration Best Practices

    main

    This project provides a set of best practices and rules for integrating the TanStack ecosystem—specifically TanStack Query, TanStack Router, and TanStack Start—to ensure optimal data flow, caching coordination, and type safety.

    These guidelines are designed for:

    • Setting up new TanStack Start projects.
    • Integrating TanStack Query with TanStack Router.
    • Configuring SSR (Server-Side Rendering) with query hydration.
    • Coordinating caching between the router and query layers.
    • Implementing type-safe data fetching patterns.
  2. Available TanStack Skills Overview

    main

    The repository provides specialized skills for different parts of the TanStack ecosystem:

    • tanstack-query: Best practices for data fetching, caching, mutations, and server state management.
    • tanstack-router: Best practices for type-safe routing, data loading, search params, and navigation.
    • tanstack-start: Best practices for full-stack React applications, including server functions, middleware, and SSR.
    • tanstack-integration: Best practices for combining Query, Router, and Start (e.g., wiring loaders to the query cache).
  3. TanStack Router Best Practices Overview

    main

    This skill provides comprehensive guidelines for implementing TanStack Router patterns in React applications. It focuses on optimizing type safety, data loading, search parameters, navigation, and code organization.

    When to Apply

    Use these guidelines when:

    • Setting up application routing or creating new routes/layouts.
    • Implementing search parameter handling or configuring data loaders.
    • Setting up code splitting or integrating with TanStack Query.
    • Refactoring existing navigation patterns.

    Rule Categories and Priority

    Rules are categorized by their impact on the application:

    • CRITICAL: Type Safety (ts-) and Route Organization (org-).
    • HIGH: Router Config (router-), Data Loading (load-), Search Params (search-), and Error Handling (err-).
    • MEDIUM: Navigation (nav-), Code Splitting (split-), and Preloading (preload-).
    • LOW: Route Context (ctx-).
  4. TanStack Start Best Practices Overview

    main

    The tanstack-start-best-practices skill provides comprehensive guidelines for implementing patterns in full-stack React applications using TanStack Start. It covers critical areas such as server functions, security, middleware, SSR, authentication, and deployment.

    When to Apply

    Use these guidelines when:

    • Creating server functions for data mutations.
    • Setting up middleware for authentication or logging.
    • Configuring SSR (Server-Side Rendering) and hydration.
    • Implementing authentication flows.
    • Handling errors across the client/server boundary.
    • Organizing full-stack codebases.
    • Deploying to various platforms.
  5. Best practices for TanStack Query (React Query)

    main

    TanStack Query (React Query) best practices provide guidelines for optimizing data fetching, caching, mutations, and server state synchronization in React applications. These rules are categorized by priority and impact, ranging from CRITICAL (Query Keys, Caching) to LOW (Performance, Offline Support).

    When to Apply

    • Creating new data fetching logic
    • Setting up query configurations
    • Implementing mutations and optimistic updates
    • Configuring caching strategies
    • Integrating with SSR/SSG
    • Refactoring existing data fetching code
  6. Extend route context using beforeLoad

    main

    You can extend the existing context for a specific route and its children by returning an object from the beforeLoad function. The properties returned from beforeLoad are merged into the context object available to the current route's loader and all subsequent child routes.

    This is useful for fetching route-specific data (like a resource) that subsequent loaders in the hierarchy need to access without re-fetching.

    // routes/posts/$postId.tsx
    export const Route = createFileRoute('/posts/$postId')({
      beforeLoad: async ({ context, params }) => {
        // Fetch data and return it to extend context
        const post = await fetchPost(params.postId)
    
        return {
          post,  // This 'post' is now available in context for this route and its children
        }
      },
      loader: async ({ context }) => {
        // context now includes 'post' from beforeLoad
        const comments = await fetchComments(context.post.id)
        return { comments }
      },
    })
  7. Leverage Parent Search Param Inheritance in TanStack Router

    main

    In TanStack Router, search parameters defined on a parent route are automatically inherited by all child routes. Instead of re-declaring shared search parameters (like pagination or filters) in every child route, define them once in the parent route. This ensures type safety and prevents synchronization issues.

    Key Rules:

    • Define once: Declare shared params in the parent route using validateSearch.
    • Inherit automatically: Child routes only need to define their own unique search parameters.
    • Accessing parent params: Use useSearch({ from: '/parent-path' }) to access specific parent search parameters with full type safety within a child component.
    // routes/posts.tsx — defines shared search params once
    export const Route = createFileRoute('/posts')({
      validateSearch: z.object({
        view: z.enum(['grid', 'list']).catch('grid'),
      }),
    })
    
    // routes/posts.$postId.tsx — only defines its own search params
    export const Route = createFileRoute('/posts/$postId')({
      validateSearch: z.object({
        tab: z.enum(['content', 'comments']).catch('content'),
      }),
      component: PostPage,
    })
    
    function PostPage() {
      // tab from this route
      const { tab } = Route.useSearch()     
      // view from parent
      const { view } = useSearch({ from: '/posts' }) 
    
      return <div>View: {view}, Tab: {tab}</div>
    }
  8. Manage environment variable boundaries

    main

    TanStack Start enforces strict boundaries for environment variables:

    • Client-side: Only variables prefixed with VITE_ are accessible via import.meta.env.
    • Server-side: All process.env variables are available inside createServerFn() handlers or createServerOnlyFn() functions.

    Best Practice: Never return raw secrets from a server function. Instead, return only the specific data the client needs.

    // Client-safe: only VITE_ prefixed vars are available
    function AppHeader() {
      return <h1>{import.meta.env.VITE_APP_NAME}</h1>
    }
    
    // Server-only: access any env var inside server functions
    const getConfig = createServerFn().handler(async () => {
      return {
        // Only return what the client needs — never return secrets
        appName: process.env.VITE_APP_NAME,
        featureFlags: JSON.parse(process.env.FEATURE_FLAGS ?? '{}'),
      }
    })
  9. When to use Server Routes vs Server Functions in TanStack Start

    main

    In TanStack Start, you should choose between Server Functions and Server Routes based on your consumer:

    • Server Functions: Best for Internal RPC. They provide full end-to-end type safety and automatic JSON responses, but have limited access to raw requests and are not designed for external integrations.
    • Server Routes: Best for External Consumers. Use these for webhooks, public APIs, third-party integrations, or when you need standard HTTP semantics (like custom status codes or non-JSON response formats). They provide full access to the raw request and allow explicit URL path definitions.
    FeatureServer FunctionsServer Routes
    Primary useInternal RPCExternal consumers
    Type safetyFull end-to-endManual
    Response formatJSON (automatic)Any (manual)
    Raw request accessLimitedFull
    URL structureAuto-generatedExplicit paths
    WebhooksNot idealDesigned for
  10. Compare Context vs. Loader Data

    main

    Understanding when to use Context versus Loader Data is critical for TanStack Router architecture:

    FeatureContextLoader Data
    AvailabilityAvailable in beforeLoad, loader, and componentsOnly available in components
    SourceSet at router creation or via beforeLoadReturned from loader
    Best Use CaseServices, clients, auth stateRoute-specific data
    ScopeFlows down to all childrenSpecific to the route
  11. Considerations when using Custom Serializers

    main

    When implementing custom search serializers in TanStack Router, keep the following constraints and trade-offs in mind:

    • URL Length Limits: Be mindful of browser limits (typically around 2000 characters). Extremely large search objects may cause issues.
    • SEO: Search engines may struggle to index or understand custom/opaque formats (like Base64 or JSURL).
    • Bookmarkability/UX: Opaque URLs (Base64) prevent users from manually editing parameters in the address bar.
    • Debugging: The default JSON serialization is the easiest to inspect and debug using browser developer tools.
  12. Determine which properties belong in main vs lazy route files

    main

    When splitting routes, follow this distribution of properties to ensure correct execution order:

    Main route file (routes/example.tsx):

    • path configuration (implicit from file location)
    • validateSearch
    • beforeLoad (e.g., auth checks, redirects)
    • loader (data fetching)
    • loaderDeps
    • context manipulation
    • Static route data

    Lazy file (routes/example.lazy.tsx):

    • component
    • pendingComponent
    • errorComponent
    • notFoundComponent