this repo has no description
1export const chapterGroups = [
2 {
3 label: "Foundations",
4 description: "Start with route loading, then add preloading before the reader clicks.",
5 chapters: [
6 {
7 number: "01",
8 to: "/basic",
9 navLabel: "01 / Basic",
10 title: "Basic",
11 routeTitle: "01_basic",
12 summary: "Baseline fetching. Data loads only after the route renders.",
13 tags: ["suspense", "query"],
14 },
15 {
16 number: "02",
17 to: "/preloading",
18 navLabel: "02 / Preloading",
19 title: "Preloading",
20 routeTitle: "02_preloading",
21 summary: "Route loader prefetch. The next screen can render from warmed query data.",
22 tags: ["loader", "prefetch"],
23 },
24 {
25 number: "03",
26 to: "/intent-preloading",
27 navLabel: "03 / Intent preloading",
28 title: "Intent preloading",
29 routeTitle: "03_intent-preloading",
30 summary: "Hover and focus intent preloads the route before activation.",
31 tags: ["intent", "link"],
32 },
33 ],
34 },
35 {
36 label: "Route State",
37 description: "Make search params part of the lesson with pages, filters, and typing intent.",
38 chapters: [
39 {
40 number: "04",
41 to: "/pagination",
42 navLabel: "04 / Pagination",
43 title: "Pagination",
44 routeTitle: "04_pagination",
45 summary: "Adjacent pages preload so previous and next navigation stays warm.",
46 tags: ["pagination", "viewport"],
47 },
48 {
49 number: "05",
50 to: "/filters",
51 navLabel: "05 / Filters",
52 title: "Filters",
53 routeTitle: "05_filters",
54 summary: "Submitted search params drive filtered data and prefetch behavior.",
55 tags: ["search params", "filter"],
56 },
57 {
58 number: "06",
59 to: "/debounced-preload-filters",
60 navLabel: "06 / Debounced filters",
61 title: "Debounced filters",
62 routeTitle: "06_debounced",
63 summary: "Typing preloads likely filtered results before the form is submitted.",
64 tags: ["debounce", "prefetch"],
65 },
66 ],
67 },
68 {
69 label: "Local-First",
70 description: "Move from fetching routes to subscribing to synced collections.",
71 chapters: [
72 {
73 number: "07",
74 to: "/live-query",
75 navLabel: "07 / Live query",
76 title: "Live query",
77 routeTitle: "07_live-query",
78 summary: "TanStack DB reads from an Electric SQL synced collection.",
79 tags: ["electric", "live query"],
80 },
81 {
82 number: "08",
83 to: "/live-query-filters",
84 navLabel: "08 / Live query filters",
85 title: "Live query filters",
86 routeTitle: "08_live-query-filters",
87 summary: "Reactive filtered live queries update from local synced data.",
88 tags: ["reactive", "sync"],
89 },
90 ],
91 },
92] as const;
93
94export const chapters = [
95 ...chapterGroups[0].chapters,
96 ...chapterGroups[1].chapters,
97 ...chapterGroups[2].chapters,
98] as const;
99
100export type Chapter = (typeof chapters)[number];
101export type ChapterPath = Chapter["to"];
102
103export function getChapterByPath(pathname: string) {
104 return chapters.find((chapter) => chapter.to === pathname);
105}
106
107export function getChapterNeighbors(pathname: string) {
108 const index = chapters.findIndex((chapter) => chapter.to === pathname);
109
110 if (index === -1) {
111 return { current: undefined, previous: undefined, next: undefined };
112 }
113
114 return {
115 current: chapters[index],
116 previous: chapters[index - 1],
117 next: chapters[index + 1],
118 };
119}