[{"data":1,"prerenderedAt":260},["ShallowReactive",2],{"blog-en-nextjs-13-app-router":3},{"id":4,"title":5,"body":6,"cover":244,"date":245,"description":246,"draft":247,"extension":248,"locale":249,"meta":250,"navigation":251,"path":252,"seo":253,"stem":254,"tags":255,"__hash__":259},"blog\u002Fblog\u002Fen\u002Fnextjs-13-app-router.md","Next.js 13: the App Router changes everything",{"type":7,"value":8,"toc":240},"minimark",[9,18,23,54,60,63,67,74,227,230,233,236],[10,11,12,13,17],"p",{},"Next.js 13 is here, and the new ",[14,15,16],"code",{},"app"," directory is more than another feature on the list. It breaks habits I've held for years. Much of it is still beta, and I'm treating it with care — but the direction is unmistakable.",[19,20,22],"h2",{"id":21},"a-new-mental-model","A new mental model",[10,24,25,26,29,30,33,34,37,38,41,42,45,46,49,50,53],{},"For years, ",[14,27,28],{},"pages\u002F"," was home. One file, one route, with ",[14,31,32],{},"getServerSideProps"," or ",[14,35,36],{},"getStaticProps"," as the data layer. It worked, yet it separated things that belonged together. The App Router thinks differently. Routes become folders, and inside each one live building blocks with clear jobs: ",[14,39,40],{},"page"," for content, ",[14,43,44],{},"layout"," for the frame, ",[14,47,48],{},"loading"," and ",[14,51,52],{},"error"," for the states in between.",[55,56,57],"blockquote",{},[10,58,59],{},"Nested layouts are the quiet revolution: what wraps stays in place while the content inside it moves.",[10,61,62],{},"Those nested layouts are the real win for me. A navigation, a sidebar state, a scroll context — all of it persists as the user moves between sub-pages. No rebuild, no flicker. It finally feels like the app I always wanted to build.",[19,64,66],{"id":65},"server-components-change-whats-static","Server Components change what's static",[10,68,69,70,73],{},"The bigger leap is React Server Components. Components render on the server by default, fetch their data right there, and send only the result to the front end. Only when I need interactivity do I mark a component with ",[14,71,72],{},"\"use client\"",".",[75,76,81],"pre",{"className":77,"code":78,"language":79,"meta":80,"style":80},"language-jsx shiki shiki-themes github-light github-dark","\u002F\u002F app\u002Fprojects\u002Fpage.js — runs on the server\nasync function Projects() {\n  const projects = await getProjects();\n  return (\n    \u003Cul>\n      {projects.map((p) => (\n        \u003Cli key={p.id}>{p.title}\u003C\u002Fli>\n      ))}\n    \u003C\u002Ful>\n  );\n}\n","jsx","",[14,82,83,92,110,132,141,154,177,199,205,215,221],{"__ignoreMap":80},[84,85,88],"span",{"class":86,"line":87},"line",1,[84,89,91],{"class":90},"sJ8bj","\u002F\u002F app\u002Fprojects\u002Fpage.js — runs on the server\n",[84,93,95,99,102,106],{"class":86,"line":94},2,[84,96,98],{"class":97},"szBVR","async",[84,100,101],{"class":97}," function",[84,103,105],{"class":104},"sScJk"," Projects",[84,107,109],{"class":108},"sVt8B","() {\n",[84,111,113,116,120,123,126,129],{"class":86,"line":112},3,[84,114,115],{"class":97},"  const",[84,117,119],{"class":118},"sj4cs"," projects",[84,121,122],{"class":97}," =",[84,124,125],{"class":97}," await",[84,127,128],{"class":104}," getProjects",[84,130,131],{"class":108},"();\n",[84,133,135,138],{"class":86,"line":134},4,[84,136,137],{"class":97},"  return",[84,139,140],{"class":108}," (\n",[84,142,144,147,151],{"class":86,"line":143},5,[84,145,146],{"class":108},"    \u003C",[84,148,150],{"class":149},"s9eBZ","ul",[84,152,153],{"class":108},">\n",[84,155,157,160,163,166,169,172,175],{"class":86,"line":156},6,[84,158,159],{"class":108},"      {projects.",[84,161,162],{"class":104},"map",[84,164,165],{"class":108},"((",[84,167,10],{"class":168},"s4XuR",[84,170,171],{"class":108},") ",[84,173,174],{"class":97},"=>",[84,176,140],{"class":108},[84,178,180,183,186,189,192,195,197],{"class":86,"line":179},7,[84,181,182],{"class":108},"        \u003C",[84,184,185],{"class":149},"li",[84,187,188],{"class":104}," key",[84,190,191],{"class":97},"=",[84,193,194],{"class":108},"{p.id}>{p.title}\u003C\u002F",[84,196,185],{"class":149},[84,198,153],{"class":108},[84,200,202],{"class":86,"line":201},8,[84,203,204],{"class":108},"      ))}\n",[84,206,208,211,213],{"class":86,"line":207},9,[84,209,210],{"class":108},"    \u003C\u002F",[84,212,150],{"class":149},[84,214,153],{"class":108},[84,216,218],{"class":86,"line":217},10,[84,219,220],{"class":108},"  );\n",[84,222,224],{"class":86,"line":223},11,[84,225,226],{"class":108},"}\n",[10,228,229],{},"No separate data-fetching mechanism, no API detour for something that already lives on the server. Fetching moves to where the data is. That less JavaScript reaches the client is a welcome side effect — for the animation-heavy pages I love to build, every kilobyte counts.",[10,231,232],{},"Honestly, I'm still rearranging my head. When server, when client? Where does the boundary run? It takes practice, and some libraries still lag behind. I wouldn't bet a critical client relaunch on it blindly today.",[10,234,235],{},"But as a glimpse of what's coming, it's convincing. Next.js 13 doesn't ask how I organize pages differently — it asks where code should actually run. That question will stay with us for years.",[237,238,239],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":80,"searchDepth":94,"depth":94,"links":241},[242,243],{"id":21,"depth":94,"text":22},{"id":65,"depth":94,"text":66},null,"2022-10-25","Next.js 13 brings the App Router and React Server Components — a new mental model that shifts how I think about routing and rendering.",false,"md","en",{},true,"\u002Fblog\u002Fen\u002Fnextjs-13-app-router",{"title":5,"description":246},"blog\u002Fen\u002Fnextjs-13-app-router",[256,257,258],"Next.js","React","Web","BywMRWcEfIghIjc0SfN0VEfqewbWbiKxOeMMM3n8NpY",1781691288096]