Skills Plugins MCP Prompt Model 博客 我的中心

nextjs-app-router

Full end-to-end tRPC setup for Next.js App Router. Covers route handler with fetchRequestHandler (GET + POST exports), TRPCProvider with QueryClientProvider, createTRPCOptionsProxy for RSC prefetching, HydrateClient/HydrationBoundary for hydration, useSuspenseQuery for Suspense, and server-side callers.

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=trpc-trpc-packages-next-skills-nextjs-app-router-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name nextjs-app-router description Full end-to-end tRPC setup for Next.js App Router. Covers route handler with fetchRequestHandler (GET + POST exports), TRPCProvider with QueryClientProvider, createTRPCOptionsProxy for RSC prefetching, HydrateClient/HydrationBoundary for hydration, useSuspenseQuery for Suspense, and server-side callers. type framework library trpc framework react library_version 11.16.0 requires ["server-setup","client-setup","react-query-setup","adapter-fetch"] sources ["www/docs/client/nextjs/overview.mdx","www/docs/client/tanstack-react-query/server-components.mdx","www/docs/server/adapters/nextjs.md","examples/next-prisma-starter/","examples/next-sse-chat/"] This skill builds on [server-setup], [client-setup], [react-query-setup], and [adapter-fetch]. Read them first for foundational concepts. tRPC -- Next.js App Router File Structure . ├── app │ ├── api/trpc/[trpc] │ │ └── route.ts # tRPC HTTP handler │ ├── layout.tsx # mount TRPCReactProvider │ ├── page.tsx # server component (prefetch) │ └── client-greeting.tsx # client component (consume) ├── trpc │ ├── init.ts # initTRPC, createTRPCContext │ ├── routers │ │ └── _app.ts # main app router, AppRouter type │ ├── query-client.ts # shared QueryClient factory │ ├── client.tsx # client hooks & TRPCReactProvider │ └── server.tsx # server-side proxy & helpers └── ... Setup 1. Install npm install @trpc/server @trpc/client @trpc/tanstack-react-query @tanstack/react-query zod server-only client-only 2. Server init and context import { initTRPC } from '@trpc/server' ; export const createTRPCContext = async ( opts : { headers: Headers } ) => { return { userId : 'user_123' }; }; const t = initTRPC . context < Awaited < ReturnType < typeof createTRPCContext>>>() . create (); export const createTRPCRouter = t. router ; export const createCallerFactory = t. createCallerFactory ; export const baseProcedure = t. procedure ; 3. Define the router import { z } from 'zod' ; import { baseProcedure, createTRPCRouter } from '../init' ; export const appRouter = createTRPCRouter ({ hello : baseProcedure . input (z. object ({ text : z. string () })) . query ( ( { input } ) => ({ greeting : `hello ${input.text} ` , })), }); export type AppRouter = typeof appRouter; 4. Route handler (API endpoint) import { fetchRequestHandler } from '@trpc/server/adapters/fetch' ; import { createTRPCContext } from '../../../../trpc/init' ; import { appRouter } from '../../../../trpc/routers/_app' ; const handler = ( req : Request ) => fetchRequestHandler ({ endpoint : '/api/trpc' , req, router : appRouter, createContext : () => createTRPCContext ({ headers : req. headers }), }); export { handler as GET , handler as POST }; 5. QueryClient factory import { defaultShouldDehydrateQuery, QueryClient , } from '@tanstack/react-query' ; export function makeQueryClient ( ) { return new QueryClient ({ defaultOptions : { queries : { staleTime : 30 * 1000 , }, dehydrate : { shouldDehydrateQuery : ( query ) => defaultShouldDehydrateQuery (query) || query. state . status === 'pending' , }, }, }); } If using a data transformer (e.g., superjson), add dehydrate.serializeData and hydrate.deserializeData here. 6. Client provider (client component) 'use client' ; import type { QueryClient } from '@tanstack/react-query' ; import { QueryClientProvider } from '@tanstack/react-query' ; import { createTRPCClient, httpBatchLink } from '@trpc/client' ; import { createTRPCContext } from '@trpc/tanstack-react-query' ; import { useState } from 'react' ; import { makeQueryClient } from './query-client' ; import type { AppRouter } from './routers/_app' ; export const { TRPCProvider , useTRPC, useTRPCClient } = createTRPCContext< AppRouter >(); let browserQueryClient : QueryClient ; function getQueryClient ( ) { if ( typeof window === 'undefined' ) { return makeQueryClient (); } if (!browserQueryClient) browserQueryClient = makeQueryClient (); return browserQueryClient; } function getUrl ( ) { const base = ( () => { if ( typeof window !== 'undefined' ) return '' ; if (process. env . VERCEL_URL ) return `https:// ${process.env.VERCEL_URL} ` ; return 'http://localhost:3000' ; })(); return ` ${base} /api/trpc` ; } export function TRPCReactProvider ( props : { children: React.ReactNode } ) { const queryClient = getQueryClient (); const [trpcClient] = useState ( () => createTRPCClient< AppRouter >({ links : [ httpBatchLink ({ url : getUrl (), }), ], }), ); return ( < QueryClientProvider client = {queryClient} > < TRPCProvider trpcClient = {trpcClient} queryClient = {queryClient} > {props.children} </ TRPCProvider > </ QueryClientProvider > ); } 7. Server-side proxy (server component) import 'server-only' ; import { dehydrate, HydrationBoundary } from '@tanstack/react-query' ; import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query' ; import type { TRPCQueryOptions } from '@trpc/tanstack-react-query' ; import { headers } from 'next/headers' ; import { cache } from 'react' ; import { createTRPCContext } from './init' ; import { makeQueryClient } from './query-client' ; import { appRouter } from './routers/_app' ; export const getQueryClient = cache (makeQueryClient); export const trpc = createTRPCOptionsProxy ({ ctx : async () => createTRPCContext ({ headers : await headers (), }), router : appRouter, queryClient : getQueryClient, }); export function HydrateClient ( props : { children: React.ReactNode } ) { const queryClient = getQueryClient (); return ( < HydrationBoundary state = {dehydrate(queryClient)} > {props.children} </ HydrationBoundary > ); } export function prefetch<T extends ReturnType < TRPCQueryOptions < any >>>( queryOptions : T, ) { const queryClient = getQueryClient (); if (queryOptions. queryKey [ 1 ]?. type === 'infinite' ) { void queryClient. prefetchInfiniteQuery (queryOptions as any ); } else { void queryClient. prefetchQuery (queryOptions); } } 8. Mount provider in layout import { TRPCReactProvider } from '../trpc/client' ; export default function RootLayout ( { children, }: { children: React.ReactNode; } ) { return ( < html lang = "en" > < body > < TRPCReactProvider > {children} </ TRPCReactProvider > </ body > </ html > ); } Core Patterns Prefetch in server component, consume in client component import { HydrateClient , prefetch, trpc } from '../trpc/server' ; import { ClientGreeting } from './client-greeting' ; export default async function Home ( ) { prefetch (trpc. hello . queryOptions ({ text : 'world' })); return ( < HydrateClient > < ClientGreeting /> </ HydrateClient > ); } 'use client' ; import { useQuery } from '@tanstack/react-query' ; import { useTRPC } from '../trpc/client' ; export function ClientGreeting ( ) { const trpc = useTRPC (); const greeting = useQuery (trpc. hello . queryOptions ({ text : 'world' })); if (!greeting. data ) return < div > Loading... </ div > ; return < div > {greeting.data.greeting} </ div > ; } Suspense with prefetch import { Suspense } from 'react' ; import { ErrorBoundary } from 'react-error-boundary' ; import { HydrateClient , prefetch, trpc } from '../trpc/server' ; import { ClientGreeting } from './client-greeting' ; export default async function Home ( ) { prefetch (trpc. hello . queryOptions ({ text : 'world' })); return ( < HydrateClient > < ErrorBoundary fallback = { < div > Something went wrong </ div > }> < Suspense fallback = { < div > Loading... </ div > }> < ClientGreeting /> </ Suspense > </ ErrorBoundary > </ HydrateClient > ); } 'use client' ; import { useSuspenseQuery } from '@tanstack/react-query' ; import { useTRPC } from '../trpc/client' ; export function ClientGreeting ( ) { const trpc = useTRPC (); const { data } = useSuspenseQuery (trpc. hello . queryOptions ({ text : 'world' })); return < div > {data.greeting} </ div > ; } Direct server caller (data needed on server only) // Add to existing server.tsx export const caller = appRouter. createCaller ( async () => createTRPCContext ({ headers : await headers () }), ); import { caller } from '../trpc/server' ; export default async function Home ( ) { const greeting = await caller. hello ({ text : 'world' }); return < div > {greeting.greeting} </ div > ; } Note: caller results are not stored in the query cache. They cannot hydrate to client components. Use prefetchQuery if client components also need the data. fetchQuery for data on server AND client import { getQueryClient, HydrateClient , trpc } from '../trpc/server' ; import { ClientGreeting } from './client-greeting' ; export default async function Home ( ) { const queryClient = getQueryClient (); const greeting = await queryClient. fetchQuery ( trpc. hello . queryOptions ({ text : 'world' }), ); // Use greeting on the server console . log (greeting. greeting ); return ( < HydrateClient > < ClientGreeting /> </ HydrateClient > ); } Common Mistakes Not exporting both GET and POST from route handler Next.js App Router route handlers must export named GET and POST functions. Missing either causes queries or mutations to return 405 Method Not Allowed. // WRONG export default function handler ( req : Request ) { ... } // CORRECT const handler = ( req : Request ) => fetchRequestHandler ({ req, router : appRouter, endpoint : '/api/trpc' , createContext }); export { handler as GET , handler as POST }; Creating a singleton QueryClient for SSR In server components, each request needs its own QueryClient instance. A singleton leaks data between requests. // WRONG const queryClient = new QueryClient (); // shared across requests! // CORRECT export const getQueryClient = cache (makeQueryClient); The cache() wrapper from React ensures the same QueryClient is reused within a single request but a new one is created for each new request. Missing dehydrate/shouldDehydrateQuery config RSC hydration requires shouldDehydrateQuery to include pending queries so that prefetched-but-not-yet-resolved promises can stream to the client. Without this, prefetched queries may not appear in the hydrated state. // WRONG new QueryClient (); // default shouldDehydrateQuery skips pending // CORRECT new QueryClient ({ defaultOptions : { dehydrate : { shouldDehydrateQuery : ( query ) => defaultShouldDehydrateQuery (query) || query. state . status === 'pending' , }, }, }); Suspense query failure crashes entire page during SSR If a query fails during SSR with useSuspenseQuery , the entire page crashes. Error Boundaries only catch errors on the client side. For critical pages, either handle errors server-side before rendering, or use useQuery (non-suspense) which allows graceful degradation. See Also [react-query-setup] -- TanStack React Query setup, queryOptions/mutationOptions factories [adapter-fetch] -- fetchRequestHandler for edge/serverless runtimes [server-setup] -- initTRPC, routers, procedures, context [nextjs-pages-router] -- if maintaining a Pages Router project alongside App Router
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。