@epic-web/workshop-app 5.4.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/build/client/assets/_exerciseNumber-DCSM0NCG.js.map +1 -1
  2. package/build/client/assets/_exerciseNumber_.finished-nbpk1ToO.js.map +1 -1
  3. package/build/client/assets/_layout-B8j0pWoF.js +6 -0
  4. package/build/client/assets/_layout-B8j0pWoF.js.map +1 -0
  5. package/build/client/assets/_layout-DTAM9xh5.js.map +1 -1
  6. package/build/client/assets/{account-C4Piztoz.js → account-DPP4rKOb.js} +2 -2
  7. package/build/client/assets/{account-C4Piztoz.js.map → account-DPP4rKOb.js.map} +1 -1
  8. package/build/client/assets/epic-video-Bp4BOD2R.js.map +1 -1
  9. package/build/client/assets/finished-C0cpfAFL.js.map +1 -1
  10. package/build/client/assets/index-Bi1TbRTj.js.map +1 -1
  11. package/build/client/assets/index-Ca4vBON4.js.map +1 -1
  12. package/build/client/assets/{manifest-bc809ee6.js → manifest-a8336fab.js} +1 -1
  13. package/build/client/assets/onboarding-C2YNq60k.js.map +1 -1
  14. package/build/client/assets/presence-8FPJKg_8.js +28 -0
  15. package/build/client/assets/presence-8FPJKg_8.js.map +1 -0
  16. package/build/client/assets/progress-DQt_Bn9o.js.map +1 -1
  17. package/build/client/assets/{root-a3d3Qwip.js → root-D12XnE1S.js} +2 -2
  18. package/build/client/assets/{root-a3d3Qwip.js.map → root-D12XnE1S.js.map} +1 -1
  19. package/build/client/assets/tests-DbuyD2cI.js.map +1 -1
  20. package/build/client/assets/{version-CaywAlNQ.js → version-lxUUxt3s.js} +2 -2
  21. package/build/client/assets/{version-CaywAlNQ.js.map → version-lxUUxt3s.js.map} +1 -1
  22. package/build/server/index.js +161 -575
  23. package/build/server/index.js.map +1 -1
  24. package/package.json +3 -3
  25. package/build/client/assets/_layout-Cbz7Qt-S.js +0 -6
  26. package/build/client/assets/_layout-Cbz7Qt-S.js.map +0 -1
  27. package/build/client/assets/presence-DJGFvdDh.js +0 -28
  28. package/build/client/assets/presence-DJGFvdDh.js.map +0 -1
@@ -5,11 +5,13 @@ import { RemixServer, Link, useRouteError, useParams, isRouteErrorResponse, useN
5
5
  import { isbot } from "isbot";
6
6
  import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
7
7
  import path from "node:path";
8
- import { makeSingletonCache, cachified, fsCache, deleteCache, compiledCodeCache, diffFilesCache, diffCodeCache, shouldForceFresh, getAllFileCacheEntries, ogCache } from "@epic-web/workshop-utils/cache.server";
9
- import { getPreferences, getAuthInfo, readOnboardingData, requireAuthInfo, deleteDb, setPresencePreferences, PlayerPreferencesSchema, setPlayerPreferences, setAuthInfo, markOnboardingVideoWatched } from "@epic-web/workshop-utils/db.server";
10
- import { z } from "zod";
11
- import { getWorkshopInstructions, getWorkshopFinished, getExercises, getApps, getPlaygroundAppName, extractNumbersAndTypeFromAppNameOrPath, getAppFromFile, getAppByName, isProblemApp, isPlaygroundApp, isExerciseStepApp, getExercise, isSolutionApp, isExampleApp, getRelativePath as getRelativePath$1, workshopRoot, modifiedTimes, getForceFreshForDir, setPlayground, requireExerciseApp, requireExercise, getExerciseApp, getAppDisplayName, getNextExerciseApp, getPrevExerciseApp, getAppPageRoute } from "@epic-web/workshop-utils/apps.server";
8
+ import { makeSingletonCache, cachified, deleteCache, compiledCodeCache, diffFilesCache, diffCodeCache, shouldForceFresh, fsCache, getAllFileCacheEntries, ogCache } from "@epic-web/workshop-utils/cache.server";
12
9
  import { getWorkshopConfig } from "@epic-web/workshop-utils/config.server";
10
+ import { getAuthInfo, getPreferences, readOnboardingData, requireAuthInfo, deleteDb, setPresencePreferences, PlayerPreferencesSchema, setPlayerPreferences, setAuthInfo, markOnboardingVideoWatched } from "@epic-web/workshop-utils/db.server";
11
+ import { getUserInfo, userHasAccessToWorkshop, getProgress, updateProgress, getEpicVideoInfos } from "@epic-web/workshop-utils/epic-api.server";
12
+ import { getUserId, getSetClientIdCookieHeader } from "@epic-web/workshop-utils/user.server";
13
+ import { z } from "zod";
14
+ import { getApps, getExercises, getPlaygroundAppName, extractNumbersAndTypeFromAppNameOrPath, getAppFromFile, getAppByName, isProblemApp, isPlaygroundApp, isExerciseStepApp, getExercise, isSolutionApp, isExampleApp, getRelativePath as getRelativePath$1, workshopRoot, modifiedTimes, getForceFreshForDir, setPlayground, requireExerciseApp, requireExercise, getExerciseApp, getAppDisplayName, getNextExerciseApp, getPrevExerciseApp, getAppPageRoute, getWorkshopFinished, getWorkshopInstructions } from "@epic-web/workshop-utils/apps.server";
13
15
  import { getEnv } from "@epic-web/workshop-utils/env.server";
14
16
  import { makeTimings, getServerTimeHeader, combineServerTimings, time } from "@epic-web/workshop-utils/timing.server";
15
17
  import { cssBundleHref } from "@remix-run/css-bundle";
@@ -20,7 +22,7 @@ import { ClientOnly } from "remix-utils/client-only";
20
22
  import slugify from "@sindresorhus/slugify";
21
23
  import clsx$1, { clsx } from "clsx";
22
24
  import * as React from "react";
23
- import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
25
+ import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useCallback, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
24
26
  import { extendTailwindMerge } from "tailwind-merge";
25
27
  import { Toaster, toast } from "sonner";
26
28
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
@@ -33,10 +35,8 @@ import { clientHint as clientHint$1 } from "@epic-web/client-hints/time-zone";
33
35
  import { safeRedirect } from "remix-utils/safe-redirect";
34
36
  import { ServerOnly } from "remix-utils/server-only";
35
37
  import * as cookie from "cookie";
36
- import cookie__default from "cookie";
37
- import md5 from "md5-hex";
38
- import { createId } from "@paralleldrive/cuid2";
39
38
  import { usePartySocket } from "partysocket/react";
39
+ import { createId } from "@paralleldrive/cuid2";
40
40
  import { motion, useAnimationControls } from "framer-motion";
41
41
  import { useHydrated } from "remix-utils/use-hydrated";
42
42
  import * as DialogPrimitive from "@radix-ui/react-dialog";
@@ -74,6 +74,7 @@ import { useEventSource } from "remix-utils/sse/react";
74
74
  import { eventStream } from "remix-utils/sse/server";
75
75
  import { EventEmitter } from "events";
76
76
  import { remember } from "@epic-web/remember";
77
+ import md5 from "md5-hex";
77
78
  import { Issuer } from "openid-client";
78
79
  import inspector from "node:inspector";
79
80
  import { getCommitInfo, getLatestWorkshopAppVersion } from "@epic-web/workshop-utils/git.server";
@@ -148,15 +149,18 @@ const MessageSchema = z.object({
148
149
  );
149
150
  const PresenceSchema = z.object({ users: z.array(UserSchema) });
150
151
  const presenceCache = makeSingletonCache("PresenceCache");
151
- async function getPresentUsers(user, { timings, request } = {}) {
152
- return cachified({
152
+ async function getPresentUsers({
153
+ timings,
154
+ request
155
+ } = {}) {
156
+ const presence = await cachified({
153
157
  key: "presence",
154
158
  cache: presenceCache,
155
159
  timings,
156
160
  request,
157
- ttl: 1e3 * 60 * 5,
161
+ ttl: 1e3 * 2,
158
162
  swr: 1e3 * 60 * 60 * 24,
159
- checkValue: z.array(UserSchema),
163
+ checkValue: PresenceSchema,
160
164
  async getFreshValue(context) {
161
165
  try {
162
166
  const response = await Promise.race([
@@ -175,20 +179,53 @@ async function getPresentUsers(user, { timings, request } = {}) {
175
179
  `Unexpected response from partykit: ${response.status} ${response.statusText}`
176
180
  );
177
181
  }
178
- const presence = PresenceSchema.parse(await response.json());
179
- const preferences = await getPreferences();
180
- const users = presence.users;
181
- if ((preferences == null ? void 0 : preferences.presence.optOut) ?? !user) {
182
- return uniqueUsers(users.filter((u) => u.id !== (user == null ? void 0 : user.id)));
183
- } else {
184
- return uniqueUsers([...users, user]);
185
- }
182
+ const presence2 = PresenceSchema.parse(await response.json());
183
+ return presence2;
186
184
  } catch {
187
185
  context.metadata.ttl = 300;
188
- return [];
186
+ return { users: [] };
189
187
  }
190
188
  }
191
189
  });
190
+ const { users } = presence;
191
+ const authInfo = await getAuthInfo();
192
+ const userId = request ? (await getUserId({ request })).id : (authInfo == null ? void 0 : authInfo.id) ?? null;
193
+ const preferences = await getPreferences();
194
+ if ((preferences == null ? void 0 : preferences.presence.optOut) || !userId) {
195
+ return uniqueUsers(users.filter((u) => u.id !== userId));
196
+ } else {
197
+ const user = { id: userId };
198
+ const config = getWorkshopConfig();
199
+ const url = request ? new URL(request.url) : void 0;
200
+ user.location = {
201
+ workshopTitle: config.title,
202
+ origin: url ? url.origin : void 0
203
+ };
204
+ if (url) {
205
+ if (url.pathname.startsWith("/exercise/")) {
206
+ const [exerciseNumber, stepNumber, type] = url.pathname.split("/").slice(2);
207
+ user.location.exercise = {
208
+ exerciseNumber: isNaN(Number(exerciseNumber)) ? null : Number(exerciseNumber),
209
+ stepNumber: isNaN(Number(stepNumber)) ? null : Number(stepNumber),
210
+ type: type === "problem" ? "problem" : type === "solution" ? "solution" : null
211
+ };
212
+ }
213
+ }
214
+ if (authInfo) {
215
+ const [userInfo, hasAccess] = await Promise.all([
216
+ getUserInfo({ request, timings }),
217
+ userHasAccessToWorkshop({ request, timings })
218
+ ]);
219
+ Object.assign(user, {
220
+ name: userInfo == null ? void 0 : userInfo.name,
221
+ avatarUrl: userInfo == null ? void 0 : userInfo.imageUrlLarge,
222
+ imageUrlSmall: userInfo == null ? void 0 : userInfo.imageUrlSmall,
223
+ imageUrlLarge: userInfo == null ? void 0 : userInfo.imageUrlLarge,
224
+ hasAccess
225
+ });
226
+ }
227
+ return uniqueUsers([...users, user]);
228
+ }
192
229
  }
193
230
  function uniqueUsers(users) {
194
231
  const seen = /* @__PURE__ */ new Set();
@@ -903,495 +940,6 @@ function createConfettiHeaders(value = String(Date.now())) {
903
940
  })
904
941
  });
905
942
  }
906
- const Transcript = z.string().nullable().optional().transform((s) => s ?? "Transcripts not available");
907
- const EpicVideoInfoSchema = z.object({
908
- transcript: Transcript,
909
- muxPlaybackId: z.string()
910
- });
911
- const EpicVideoRegionRestrictedErrorSchema = z.object({
912
- requestCountry: z.string(),
913
- restrictedCountry: z.string(),
914
- isRegionRestricted: z.literal(true)
915
- });
916
- const CachedEpicVideoInfoSchema = z.object({
917
- transcript: Transcript,
918
- muxPlaybackId: z.string(),
919
- status: z.literal("success"),
920
- statusCode: z.number(),
921
- statusText: z.string()
922
- }).or(
923
- z.object({
924
- status: z.literal("error"),
925
- statusCode: z.number(),
926
- statusText: z.string(),
927
- type: z.literal("unknown")
928
- })
929
- ).or(
930
- z.object({
931
- status: z.literal("error"),
932
- statusCode: z.number(),
933
- statusText: z.string(),
934
- type: z.literal("region-restricted"),
935
- requestCountry: z.string(),
936
- restrictedCountry: z.string()
937
- })
938
- ).or(z.null());
939
- async function getEpicVideoInfos(epicWebUrls, { request, timings } = {}) {
940
- if (!epicWebUrls) return {};
941
- const authInfo = await getAuthInfo();
942
- if (ENV.EPICSHOP_DEPLOYED) return {};
943
- const epicVideoInfos = {};
944
- for (const epicVideoEmbed of epicWebUrls) {
945
- const epicVideoInfo = await getEpicVideoInfo({
946
- epicVideoEmbed,
947
- accessToken: authInfo == null ? void 0 : authInfo.tokenSet.access_token,
948
- request,
949
- timings
950
- });
951
- if (epicVideoInfo) {
952
- epicVideoInfos[epicVideoEmbed] = epicVideoInfo;
953
- }
954
- }
955
- return epicVideoInfos;
956
- }
957
- async function getEpicVideoInfo({
958
- epicVideoEmbed,
959
- accessToken,
960
- request,
961
- timings
962
- }) {
963
- const tokenPortion = accessToken ? md5(accessToken) : "unauthenticated";
964
- const key = `epic-video-info:${tokenPortion}:${epicVideoEmbed}`;
965
- return cachified({
966
- key,
967
- request,
968
- cache: fsCache,
969
- timings,
970
- ttl: 1e3 * 60 * 60,
971
- swr: 1e3 * 60 * 60 * 24 * 30,
972
- checkValue: CachedEpicVideoInfoSchema,
973
- async getFreshValue(context) {
974
- const epicUrl = new URL(epicVideoEmbed);
975
- if (epicUrl.host !== "www.epicweb.dev" && epicUrl.host !== "www.epicreact.dev") {
976
- return null;
977
- }
978
- if (epicUrl.pathname.startsWith("/tutorials/")) {
979
- epicUrl.pathname = epicUrl.pathname.replace(
980
- /^\/tutorials\//,
981
- "/workshops/"
982
- );
983
- }
984
- const infoResponse = await fetch(
985
- `https://${epicUrl.host}/api${epicUrl.pathname}`,
986
- accessToken ? { headers: { authorization: `Bearer ${accessToken}` } } : void 0
987
- );
988
- const { status, statusText } = infoResponse;
989
- if (infoResponse.status >= 200 && infoResponse.status < 300) {
990
- const rawInfo = await infoResponse.json();
991
- const infoResult = EpicVideoInfoSchema.safeParse(rawInfo);
992
- if (infoResult.success) {
993
- return {
994
- status: "success",
995
- statusCode: status,
996
- statusText,
997
- ...infoResult.data
998
- };
999
- } else {
1000
- context.metadata.ttl = 1e3 * 2;
1001
- context.metadata.swr = 0;
1002
- const restrictedResult = EpicVideoRegionRestrictedErrorSchema.safeParse(rawInfo);
1003
- if (restrictedResult.success) {
1004
- return {
1005
- status: "error",
1006
- statusCode: status,
1007
- statusText,
1008
- type: "region-restricted",
1009
- ...restrictedResult.data
1010
- };
1011
- } else {
1012
- console.warn(
1013
- `Response from EpicWeb for "${epicUrl.pathname}" does not match expectation`,
1014
- infoResult.error
1015
- );
1016
- return {
1017
- status: "error",
1018
- statusCode: 500,
1019
- statusText: "API Data Type Mismatch",
1020
- type: "unknown"
1021
- };
1022
- }
1023
- }
1024
- } else {
1025
- context.metadata.ttl = 1e3 * 2;
1026
- context.metadata.swr = 0;
1027
- return {
1028
- status: "error",
1029
- statusCode: status,
1030
- statusText,
1031
- type: "unknown"
1032
- };
1033
- }
1034
- }
1035
- }).catch((e) => {
1036
- console.error(`Failed to fetch epic video info for ${epicVideoEmbed}`, e);
1037
- throw e;
1038
- });
1039
- }
1040
- async function getEpicProgress({
1041
- timings,
1042
- request,
1043
- forceFresh
1044
- } = {}) {
1045
- if (ENV.EPICSHOP_DEPLOYED) return [];
1046
- const authInfo = await getAuthInfo();
1047
- const {
1048
- product: { host }
1049
- } = getWorkshopConfig();
1050
- if (!authInfo) return [];
1051
- const tokenPart = md5(authInfo.tokenSet.access_token);
1052
- const EpicProgressSchema = z.array(
1053
- z.object({
1054
- lessonId: z.string(),
1055
- completedAt: z.string().nullable()
1056
- })
1057
- );
1058
- return cachified({
1059
- key: `epic-progress:${host}:${tokenPart}`,
1060
- cache: fsCache,
1061
- request,
1062
- timings,
1063
- forceFresh,
1064
- ttl: 1e3 * 2,
1065
- swr: 1e3 * 60 * 60 * 24 * 30,
1066
- checkValue: EpicProgressSchema,
1067
- async getFreshValue(context) {
1068
- const response = await fetch(`https://${host}/api/progress`, {
1069
- headers: {
1070
- authorization: `Bearer ${authInfo.tokenSet.access_token}`
1071
- }
1072
- }).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
1073
- if (response.status < 200 || response.status >= 300) {
1074
- console.error(
1075
- `Failed to fetch progress from EpicWeb: ${response.status} ${response.statusText}`
1076
- );
1077
- context.metadata.ttl = 1e3 * 2;
1078
- context.metadata.swr = 0;
1079
- return [];
1080
- }
1081
- return EpicProgressSchema.parse(await response.json());
1082
- }
1083
- });
1084
- }
1085
- async function getProgress({
1086
- timings,
1087
- request
1088
- } = {}) {
1089
- if (ENV.EPICSHOP_DEPLOYED) return [];
1090
- const authInfo = await getAuthInfo();
1091
- if (!authInfo) return [];
1092
- const {
1093
- product: { slug, host }
1094
- } = getWorkshopConfig();
1095
- if (!slug) return [];
1096
- const [
1097
- workshopData,
1098
- epicProgress,
1099
- workshopInstructions,
1100
- workshopFinished,
1101
- exercises
1102
- ] = await Promise.all([
1103
- getWorkshopData(slug, { request, timings }),
1104
- getEpicProgress({ request, timings }),
1105
- getWorkshopInstructions({ request }),
1106
- getWorkshopFinished({ request }),
1107
- getExercises({ request, timings })
1108
- ]);
1109
- const progress = [];
1110
- for (const resource of workshopData.resources) {
1111
- const lessons = resource._type === "section" ? resource.lessons : [resource];
1112
- for (const lesson of lessons) {
1113
- const epicLessonSlug = lesson.slug;
1114
- const lessonProgress = epicProgress.find(
1115
- ({ lessonId }) => lessonId === lesson._id
1116
- );
1117
- const epicCompletedAt = lessonProgress ? lessonProgress.completedAt : null;
1118
- const progressForLesson = getProgressForLesson(epicLessonSlug, {
1119
- workshopInstructions,
1120
- workshopFinished,
1121
- exercises
1122
- });
1123
- const epicLessonUrl = `https://${host}/workshops/${slug}/${epicLessonSlug}`;
1124
- if (progressForLesson) {
1125
- progress.push({
1126
- ...progressForLesson,
1127
- epicLessonUrl,
1128
- epicLessonSlug,
1129
- epicCompletedAt
1130
- });
1131
- } else {
1132
- progress.push({
1133
- type: "unknown",
1134
- epicLessonUrl,
1135
- epicLessonSlug,
1136
- epicCompletedAt
1137
- });
1138
- }
1139
- }
1140
- }
1141
- return progress;
1142
- }
1143
- function getProgressForLesson(epicLessonSlug, {
1144
- workshopInstructions,
1145
- workshopFinished,
1146
- exercises
1147
- }) {
1148
- var _a;
1149
- const hasEmbed = (embed) => embed == null ? void 0 : embed.some((e) => e.split("/").at(-1) === epicLessonSlug);
1150
- if (workshopInstructions.compiled.status === "success" && hasEmbed(workshopInstructions.compiled.epicVideoEmbeds)) {
1151
- return { type: "workshop-instructions" };
1152
- }
1153
- if (workshopFinished.compiled.status === "success" && hasEmbed(workshopFinished.compiled.epicVideoEmbeds)) {
1154
- return { type: "workshop-finished" };
1155
- }
1156
- for (const exercise of exercises) {
1157
- if (hasEmbed(exercise.instructionsEpicVideoEmbeds)) {
1158
- return {
1159
- type: "instructions",
1160
- exerciseNumber: exercise.exerciseNumber
1161
- };
1162
- }
1163
- if (hasEmbed(exercise.finishedEpicVideoEmbeds)) {
1164
- return {
1165
- type: "finished",
1166
- exerciseNumber: exercise.exerciseNumber
1167
- };
1168
- }
1169
- for (const step of exercise.steps.filter(Boolean)) {
1170
- if (hasEmbed((_a = step.problem) == null ? void 0 : _a.epicVideoEmbeds)) {
1171
- return {
1172
- type: "step",
1173
- exerciseNumber: exercise.exerciseNumber,
1174
- stepNumber: step.stepNumber
1175
- };
1176
- }
1177
- }
1178
- }
1179
- }
1180
- async function updateProgress({ lessonSlug, complete }, {
1181
- timings,
1182
- request
1183
- } = {}) {
1184
- if (ENV.EPICSHOP_DEPLOYED) {
1185
- return {
1186
- status: "error",
1187
- error: "cannot update progress when deployed"
1188
- };
1189
- }
1190
- const authInfo = await getAuthInfo();
1191
- if (!authInfo) {
1192
- return { status: "error", error: "not authenticated" };
1193
- }
1194
- const {
1195
- product: { host }
1196
- } = getWorkshopConfig();
1197
- const response = await fetch(`https://${host}/api/progress`, {
1198
- method: "POST",
1199
- headers: {
1200
- authorization: `Bearer ${authInfo.tokenSet.access_token}`,
1201
- "content-type": "application/json"
1202
- },
1203
- body: JSON.stringify(
1204
- complete ? { lessonSlug } : { lessonSlug, remove: true }
1205
- )
1206
- }).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
1207
- await getEpicProgress({ forceFresh: true, request, timings });
1208
- if (response.status < 200 || response.status >= 300) {
1209
- return {
1210
- status: "error",
1211
- error: `${response.status} ${response.statusText}`
1212
- };
1213
- }
1214
- return { status: "success" };
1215
- }
1216
- const ModuleSchema = z.object({
1217
- resources: z.array(
1218
- z.union([
1219
- z.object({
1220
- _type: z.literal("lesson"),
1221
- _id: z.string(),
1222
- slug: z.string()
1223
- }),
1224
- z.object({
1225
- _type: z.literal("section"),
1226
- lessons: z.array(z.object({ _id: z.string(), slug: z.string() }))
1227
- })
1228
- ])
1229
- )
1230
- });
1231
- async function getWorkshopData(slug, {
1232
- timings,
1233
- request,
1234
- forceFresh
1235
- } = {}) {
1236
- if (ENV.EPICSHOP_DEPLOYED) return { resources: [] };
1237
- const authInfo = await getAuthInfo();
1238
- if (!authInfo) return { resources: [] };
1239
- const {
1240
- product: { host }
1241
- } = getWorkshopConfig();
1242
- return cachified({
1243
- key: `epic-workshop-data:${host}:${slug}`,
1244
- cache: fsCache,
1245
- request,
1246
- forceFresh,
1247
- timings,
1248
- checkValue: ModuleSchema,
1249
- async getFreshValue() {
1250
- const response = await fetch(
1251
- `https://${host}/api/workshops/${encodeURIComponent(slug)}`
1252
- ).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
1253
- if (response.status < 200 || response.status >= 300) {
1254
- console.error(
1255
- `Failed to fetch workshop data from EpicWeb for ${slug}: ${response.status} ${response.statusText}`
1256
- );
1257
- return { resources: [] };
1258
- }
1259
- return ModuleSchema.parse(await response.json());
1260
- }
1261
- });
1262
- }
1263
- async function userHasAccessToWorkshop({
1264
- timings,
1265
- request,
1266
- forceFresh
1267
- }) {
1268
- var _a;
1269
- const config = getWorkshopConfig();
1270
- const {
1271
- product: { host, slug }
1272
- } = config;
1273
- if (!slug) return true;
1274
- if (ENV.EPICSHOP_DEPLOYED) {
1275
- const cookieHeader = request.headers.get("Cookie");
1276
- if (!cookieHeader) return false;
1277
- const cookies = cookie__default.parse(cookieHeader);
1278
- return ((_a = cookies.skill) == null ? void 0 : _a.split(",").includes(slug)) ?? false;
1279
- }
1280
- const authInfo = await getAuthInfo();
1281
- if (!authInfo) return false;
1282
- return cachified({
1283
- key: `user-has-access-to-workshop:${host}:${slug}`,
1284
- cache: fsCache,
1285
- request,
1286
- forceFresh,
1287
- timings,
1288
- ttl: 1e3 * 5,
1289
- checkValue: z.boolean(),
1290
- async getFreshValue(context) {
1291
- const response = await fetch(
1292
- `https://${host}/api/workshops/${encodeURIComponent(slug)}/access`,
1293
- {
1294
- headers: {
1295
- authorization: `Bearer ${authInfo.tokenSet.access_token}`
1296
- }
1297
- }
1298
- ).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
1299
- const hasAccess = response.ok ? await response.json() === true : false;
1300
- if (hasAccess) {
1301
- context.metadata.ttl = 1e3 * 60 * 60 * 24 * 30;
1302
- context.metadata.swr = 1e3 * 60 * 60 * 24 * 30;
1303
- }
1304
- return hasAccess;
1305
- }
1306
- });
1307
- }
1308
- const UserInfoSchema = z.object({
1309
- id: z.string(),
1310
- name: z.string().nullable(),
1311
- email: z.string().email(),
1312
- image: z.string().nullable(),
1313
- discordProfile: z.object({
1314
- nick: z.string().nullable(),
1315
- user: z.object({
1316
- id: z.string(),
1317
- username: z.string(),
1318
- avatar: z.string().nullable().optional(),
1319
- global_name: z.string().nullable().optional()
1320
- })
1321
- }).nullable().optional()
1322
- }).transform((data) => {
1323
- var _a, _b;
1324
- return {
1325
- ...data,
1326
- imageUrlSmall: resizeImageUrl(data.image, { size: 64 }) ?? resolveDiscordAvatar((_a = data.discordProfile) == null ? void 0 : _a.user, {
1327
- size: 64
1328
- }) ?? resolveGravatarUrl(data.email, { size: 64 }),
1329
- imageUrlLarge: resizeImageUrl(data.image, { size: 512 }) ?? resolveDiscordAvatar((_b = data.discordProfile) == null ? void 0 : _b.user, {
1330
- size: 512
1331
- }) ?? resolveGravatarUrl(data.email, { size: 512 })
1332
- };
1333
- });
1334
- function resizeImageUrl(url, { size }) {
1335
- if (!url) return null;
1336
- const urlObj = new URL(url);
1337
- urlObj.searchParams.set("size", size.toString());
1338
- return urlObj.toString();
1339
- }
1340
- function resolveGravatarUrl(email, { size }) {
1341
- if (!email) return null;
1342
- const hash = md5(email.toLowerCase());
1343
- const gravatarOptions = new URLSearchParams({
1344
- size: size.toString(),
1345
- default: "identicon"
1346
- });
1347
- return `https://www.gravatar.com/avatar/${hash}?${gravatarOptions.toString()}`;
1348
- }
1349
- function resolveDiscordAvatar(user, { size }) {
1350
- if (!user) return null;
1351
- const { avatar, id: userId } = user;
1352
- if (!avatar) return null;
1353
- const isGif = avatar.startsWith("a_");
1354
- const url = new URL(
1355
- `/avatars/${userId}/${avatar}.${isGif ? "gif" : "png"}`,
1356
- "https://cdn.discordapp.com"
1357
- );
1358
- url.searchParams.set("size", size.toString());
1359
- return url.toString();
1360
- }
1361
- async function getUserInfo({
1362
- timings,
1363
- request,
1364
- forceFresh
1365
- } = {}) {
1366
- const authInfo = await getAuthInfo();
1367
- if (!authInfo) return null;
1368
- const { tokenSet } = authInfo;
1369
- const {
1370
- product: { host }
1371
- } = getWorkshopConfig();
1372
- const accessToken = tokenSet.access_token;
1373
- const url = `https://${host}/oauth/userinfo`;
1374
- return cachified({
1375
- key: `${url}:${md5(accessToken)}`,
1376
- cache: fsCache,
1377
- request,
1378
- forceFresh,
1379
- timings,
1380
- ttl: 1e3 * 60 * 1,
1381
- swr: 1e3 * 60 * 60 * 24 * 365,
1382
- checkValue: UserInfoSchema,
1383
- async getFreshValue() {
1384
- const response = await fetch(url, {
1385
- headers: { authorization: `Bearer ${accessToken}` }
1386
- });
1387
- if (!response.ok) {
1388
- throw new Error(`Failed to fetch user info: ${response.statusText}`);
1389
- }
1390
- const data = await response.json();
1391
- return UserInfoSchema.parse(data);
1392
- }
1393
- });
1394
- }
1395
943
  const PresenceContext = createContext(null);
1396
944
  function usePresencePreferences() {
1397
945
  var _a;
@@ -1407,35 +955,51 @@ const ExerciseAppParamsSchema = z.object({
1407
955
  exerciseNumber: z.coerce.number().finite(),
1408
956
  stepNumber: z.coerce.number().finite().optional()
1409
957
  });
958
+ function useFirstCallDelayedCallback(cb, delay) {
959
+ const [timedPromise] = useState(
960
+ () => new Promise((resolve) => setTimeout(resolve, delay))
961
+ );
962
+ const mounted = useRef(true);
963
+ const currentCallRef = useRef(null);
964
+ const lastCbRef = useRef(cb);
965
+ useEffect(() => {
966
+ lastCbRef.current = cb;
967
+ }, [cb]);
968
+ const delayedCb = useCallback(
969
+ (...args) => {
970
+ const thisOne = Symbol();
971
+ currentCallRef.current = thisOne;
972
+ void timedPromise.then(() => {
973
+ if (!mounted.current) return;
974
+ if (currentCallRef.current !== thisOne) {
975
+ return;
976
+ }
977
+ lastCbRef.current(...args);
978
+ });
979
+ },
980
+ [timedPromise]
981
+ );
982
+ return delayedCb;
983
+ }
1410
984
  function usePresenceSocket(user) {
1411
985
  const workshopTitle = useOptionalWorkshopTitle();
1412
- const { userHasAccess = false } = useRouteLoaderData("root") ?? {};
986
+ const { userHasAccess = false, userId } = useRouteLoaderData("root") ?? {};
1413
987
  const requestInfo = useRequestInfo();
1414
988
  const rawParams = useParams();
1415
989
  const prefs = usePresencePreferences();
1416
990
  const data = useRouteLoaderData("root");
1417
991
  const [users, setUsers] = useState((data == null ? void 0 : data.presence.users) ?? []);
1418
- const [clientId] = useState(() => {
1419
- if (typeof document === "undefined") return null;
1420
- if (user) return user.id;
1421
- const clientId2 = sessionStorage.getItem("clientId");
1422
- if (clientId2) return clientId2;
1423
- const newClientId = createId();
1424
- sessionStorage.setItem("clientId", newClientId);
1425
- return newClientId;
1426
- });
992
+ const handleMessage = useFirstCallDelayedCallback((evt) => {
993
+ const messageResult = MessageSchema.safeParse(JSON.parse(String(evt.data)));
994
+ if (!messageResult.success) return;
995
+ if (messageResult.data.type === "presence") {
996
+ setUsers(messageResult.data.payload.users);
997
+ }
998
+ }, 2e3);
1427
999
  const socket = usePartySocket({
1428
1000
  host: new URL(partykitBaseUrl).host,
1429
1001
  room: partykitRoom,
1430
- onMessage(evt) {
1431
- const messageResult = MessageSchema.safeParse(
1432
- JSON.parse(String(evt.data))
1433
- );
1434
- if (!messageResult.success) return;
1435
- if (messageResult.data.type === "presence") {
1436
- setUsers(messageResult.data.payload.users);
1437
- }
1438
- }
1002
+ onMessage: handleMessage
1439
1003
  });
1440
1004
  const paramsResult = ExerciseAppParamsSchema.safeParse(rawParams);
1441
1005
  const params = paramsResult.success ? paramsResult.data : null;
@@ -1451,54 +1015,58 @@ function usePresenceSocket(user) {
1451
1015
  } : null
1452
1016
  };
1453
1017
  let message = null;
1454
- if ((!user || (prefs == null ? void 0 : prefs.optOut)) && clientId) {
1455
- if (user) {
1018
+ if (user) {
1019
+ if (prefs == null ? void 0 : prefs.optOut) {
1456
1020
  message = { type: "remove-user", payload: { id: user.id } };
1021
+ } else {
1022
+ message = {
1023
+ type: "add-user",
1024
+ payload: {
1025
+ id: user.id,
1026
+ name: user.name,
1027
+ hasAccess: userHasAccess,
1028
+ imageUrlSmall: user.imageUrlSmall,
1029
+ imageUrlLarge: user.imageUrlLarge,
1030
+ location
1031
+ }
1032
+ };
1457
1033
  }
1458
- message = { type: "add-user", payload: { id: clientId, location } };
1459
- } else if (user) {
1460
- message = {
1461
- type: "add-user",
1462
- payload: {
1463
- id: user.id,
1464
- name: user.name,
1465
- hasAccess: userHasAccess,
1466
- imageUrlSmall: user.imageUrlSmall,
1467
- imageUrlLarge: user.imageUrlLarge,
1468
- location
1469
- }
1470
- };
1034
+ } else if (userId == null ? void 0 : userId.id) {
1035
+ message = { type: "add-user", payload: { id: userId.id, location } };
1471
1036
  }
1472
1037
  const messageJson = message ? JSON.stringify(message) : null;
1473
1038
  useEffect(() => {
1474
1039
  if (messageJson) socket.send(messageJson);
1475
1040
  }, [messageJson, socket]);
1476
- const scoredUsers = scoreUsers(location, users);
1041
+ const scoredUsers = scoreUsers({ id: userId == null ? void 0 : userId.id, location }, users);
1477
1042
  return { users: scoredUsers };
1478
1043
  }
1479
- function scoreUsers(location, users) {
1480
- const scoredUsers = users.map((user) => {
1044
+ function scoreUsers(user, users) {
1045
+ const { location } = user;
1046
+ const scoredUsers = users.map((user2) => {
1481
1047
  var _a, _b, _c, _d;
1482
1048
  let score = 0;
1483
1049
  const available = 5;
1484
- if (user.hasAccess) {
1050
+ if (user2.hasAccess) {
1485
1051
  score += 1;
1486
1052
  }
1487
- if ((location == null ? void 0 : location.workshopTitle) === ((_a = user.location) == null ? void 0 : _a.workshopTitle)) {
1053
+ if ((location == null ? void 0 : location.workshopTitle) === ((_a = user2.location) == null ? void 0 : _a.workshopTitle)) {
1488
1054
  score += 1;
1489
- if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c = user.location) == null ? void 0 : _c.exercise) == null ? void 0 : _d.exerciseNumber)) {
1055
+ if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c = user2.location) == null ? void 0 : _c.exercise) == null ? void 0 : _d.exerciseNumber)) {
1490
1056
  score += 1;
1491
- if (location.exercise.stepNumber && location.exercise.stepNumber === user.location.exercise.stepNumber) {
1057
+ if (location.exercise.stepNumber && location.exercise.stepNumber === user2.location.exercise.stepNumber) {
1492
1058
  score += 1;
1493
- if (location.exercise.type && location.exercise.type === user.location.exercise.type) {
1059
+ if (location.exercise.type && location.exercise.type === user2.location.exercise.type) {
1494
1060
  score += 1;
1495
1061
  }
1496
1062
  }
1497
1063
  }
1498
1064
  }
1499
- return { user, score: Math.floor(score / available * 10) / 10 };
1065
+ return { user: user2, score: Math.floor(score / available * 10) / 10 };
1500
1066
  });
1501
1067
  return scoredUsers.sort((a, b) => {
1068
+ if (a.user.id === (user == null ? void 0 : user.id)) return -1;
1069
+ if (b.user.id === (user == null ? void 0 : user.id)) return 1;
1502
1070
  if (a.score === b.score) return 0;
1503
1071
  return a.score > b.score ? -1 : 1;
1504
1072
  });
@@ -1622,6 +1190,7 @@ const meta$6 = ({ data: data2 }) => {
1622
1190
  });
1623
1191
  };
1624
1192
  async function loader$x({ request }) {
1193
+ var _a;
1625
1194
  const timings = makeTimings("rootLoader");
1626
1195
  const workshopConfig = getWorkshopConfig();
1627
1196
  const {
@@ -1640,6 +1209,7 @@ async function loader$x({ request }) {
1640
1209
  const { confettiId, headers: confettiHeaders } = getConfetti(request);
1641
1210
  const { toast: toast2, headers: toastHeaders } = await getToast(request);
1642
1211
  const asyncStuff = await promiseHash({
1212
+ userId: getUserId({ request }),
1643
1213
  preferences: getPreferences(),
1644
1214
  progress: getProgress({ timings }).catch((e) => {
1645
1215
  console.error("Failed to get progress", e);
@@ -1650,7 +1220,7 @@ async function loader$x({ request }) {
1650
1220
  userHasAccess: userHasAccessToWorkshop({ request, timings }),
1651
1221
  apps: getApps({ request, timings })
1652
1222
  });
1653
- const presentUsers = await getPresentUsers(asyncStuff.user, {
1223
+ const presentUsers = await getPresentUsers({
1654
1224
  request,
1655
1225
  timings
1656
1226
  });
@@ -1685,19 +1255,15 @@ async function loader$x({ request }) {
1685
1255
  }
1686
1256
  },
1687
1257
  {
1688
- headers: combineHeaders(toastHeaders, confettiHeaders, {
1689
- "Server-Timing": timings.toString()
1690
- })
1258
+ headers: combineHeaders(
1259
+ toastHeaders,
1260
+ confettiHeaders,
1261
+ { "Server-Timing": timings.toString() },
1262
+ ((_a = asyncStuff.userId) == null ? void 0 : _a.type) === "cookie.randomId" ? { "Set-Cookie": getSetClientIdCookieHeader(asyncStuff.userId.id) } : void 0
1263
+ )
1691
1264
  }
1692
1265
  );
1693
1266
  }
1694
- const headers$c = ({ loaderHeaders }) => {
1695
- const headers2 = {
1696
- "Cache-Control": loaderHeaders.get("Cache-Control") ?? "",
1697
- "Server-Timing": loaderHeaders.get("Server-Timing") ?? ""
1698
- };
1699
- return headers2;
1700
- };
1701
1267
  function Document({
1702
1268
  children,
1703
1269
  env = {},
@@ -1765,7 +1331,6 @@ const route0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
1765
1331
  __proto__: null,
1766
1332
  ErrorBoundary: ErrorBoundary$6,
1767
1333
  default: AppWithProviders,
1768
- headers: headers$c,
1769
1334
  links,
1770
1335
  loader: loader$x,
1771
1336
  meta: meta$6
@@ -2359,7 +1924,7 @@ const route38 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
2359
1924
  useRequireEpicProgress
2360
1925
  }, Symbol.toStringTag, { value: "Module" }));
2361
1926
  async function loader$v({ request }) {
2362
- var _a;
1927
+ var _a, _b;
2363
1928
  const timings = makeTimings("appLayoutLoader");
2364
1929
  const { title: workshopTitle } = getWorkshopConfig();
2365
1930
  const [exercises, playgroundAppName] = await Promise.all([
@@ -2394,7 +1959,8 @@ async function loader$v({ request }) {
2394
1959
  name: (problem == null ? void 0 : problem.name) ?? (solution == null ? void 0 : solution.name) ?? "Unknown"
2395
1960
  }))
2396
1961
  })),
2397
- playground
1962
+ playground,
1963
+ isMenuOpened: ((_b = request.headers.get("cookie")) == null ? void 0 : _b.includes("es_menu_open=true")) ?? false
2398
1964
  },
2399
1965
  {
2400
1966
  headers: {
@@ -2540,11 +2106,16 @@ function FacePile({ isMenuOpened }) {
2540
2106
  }
2541
2107
  const useIsWide = makeMediaQueryStore("(min-width: 640px)", true);
2542
2108
  function App() {
2109
+ const data2 = useLoaderData();
2543
2110
  const user = useOptionalUser();
2544
2111
  const isWide = useIsWide();
2545
2112
  const isHydrated = useHydrated();
2546
- const [isMenuOpened, setMenuOpened] = React.useState(false);
2113
+ const [isMenuOpened, setMenuOpenedState] = React.useState(data2.isMenuOpened);
2547
2114
  useRevalidationWS({ watchPaths: ["./exercises/README.mdx"] });
2115
+ function setMenuOpened(value) {
2116
+ setMenuOpenedState(value);
2117
+ document.cookie = `es_menu_open=${value.toString()}; path=/; SameSite=Lax;`;
2118
+ }
2548
2119
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
2549
2120
  user ? null : /* @__PURE__ */ jsx(NoUserBanner, {}),
2550
2121
  isHydrated && isWide ? null : /* @__PURE__ */ jsx(
@@ -2599,6 +2170,7 @@ function NoUserBanner() {
2599
2170
  const {
2600
2171
  product: { host, displayName }
2601
2172
  } = useWorkshopConfig();
2173
+ const userHasAccess = useUserHasAccess();
2602
2174
  const details = /* @__PURE__ */ jsx("div", { children: ENV.EPICSHOP_DEPLOYED ? /* @__PURE__ */ jsxs("div", { children: [
2603
2175
  `This is the deployed version. `,
2604
2176
  /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -2646,7 +2218,7 @@ function NoUserBanner() {
2646
2218
  details
2647
2219
  ] })
2648
2220
  ] }),
2649
- /* @__PURE__ */ jsxs("div", { className: "hidden h-full flex-col items-center sm:flex md:flex-row", children: [
2221
+ userHasAccess ? null : /* @__PURE__ */ jsxs("div", { className: "hidden h-full flex-col items-center sm:flex md:flex-row", children: [
2650
2222
  /* @__PURE__ */ jsxs(
2651
2223
  Link,
2652
2224
  {
@@ -3353,6 +2925,7 @@ function NavToggle({
3353
2925
  setMenuOpened,
3354
2926
  menuControls
3355
2927
  }) {
2928
+ const initialOpenRef = React.useRef(isMenuOpened);
3356
2929
  const menuButtonRef = React.useRef(null);
3357
2930
  const path01Variants = {
3358
2931
  open: { d: "M3.06061 2.99999L21.0606 21" },
@@ -3410,7 +2983,7 @@ function NavToggle({
3410
2983
  /* @__PURE__ */ jsx(
3411
2984
  motion.path,
3412
2985
  {
3413
- ...path01Variants.closed,
2986
+ ...path01Variants[initialOpenRef.current ? "open" : "closed"],
3414
2987
  animate: path01Controls,
3415
2988
  transition: { duration: 0.2 },
3416
2989
  stroke: "currentColor",
@@ -3420,7 +2993,7 @@ function NavToggle({
3420
2993
  /* @__PURE__ */ jsx(
3421
2994
  motion.path,
3422
2995
  {
3423
- ...path02Variants.closed,
2996
+ ...path02Variants[initialOpenRef.current ? "open" : "closed"],
3424
2997
  animate: path02Controls,
3425
2998
  transition: { duration: 0.2 },
3426
2999
  stroke: "currentColor",
@@ -10110,7 +9683,20 @@ async function registerDevice() {
10110
9683
  return;
10111
9684
  }
10112
9685
  const userinfo = await client.userinfo(tokenSet);
10113
- await setAuthInfo({ tokenSet, email: userinfo.email, name: userinfo.name });
9686
+ let id;
9687
+ if (typeof userinfo.id === "string") {
9688
+ id = userinfo.id;
9689
+ } else {
9690
+ console.warn("[UNEXPECTED] User ID is not a string:", userinfo.id);
9691
+ id = userinfo.email ? md5(userinfo.email) : createId();
9692
+ }
9693
+ await setAuthInfo({
9694
+ id,
9695
+ tokenSet,
9696
+ email: userinfo.email,
9697
+ name: userinfo.name
9698
+ });
9699
+ await getUserInfo({ forceFresh: true });
10114
9700
  authEmitter.emit(EVENTS.AUTH_RESOLVED);
10115
9701
  } catch (error) {
10116
9702
  authEmitter.emit(EVENTS.AUTH_REJECTED, {
@@ -10722,14 +10308,14 @@ function Version() {
10722
10308
  /* @__PURE__ */ jsx("h3", { className: "text-md font-bold", children: "Workshop App" }),
10723
10309
  /* @__PURE__ */ jsxs("p", { children: [
10724
10310
  "Current Version: ",
10725
- /* @__PURE__ */ jsx(
10311
+ ENV.EPICSHOP_APP_VERSION ? /* @__PURE__ */ jsx(
10726
10312
  "a",
10727
10313
  {
10728
10314
  href: `https://github.com/epicweb-dev/epicshop/releases/tag/v${ENV.EPICSHOP_APP_VERSION}`,
10729
10315
  className: "underline",
10730
10316
  children: ENV.EPICSHOP_APP_VERSION
10731
10317
  }
10732
- )
10318
+ ) : "Unknown"
10733
10319
  ] }),
10734
10320
  /* @__PURE__ */ jsxs("p", { children: [
10735
10321
  "Latest Version: ",
@@ -11299,7 +10885,7 @@ const route41 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
11299
10885
  __proto__: null,
11300
10886
  loader
11301
10887
  }, Symbol.toStringTag, { value: "Module" }));
11302
- const serverManifest = { "entry": { "module": "/assets/entry.client-DqIWuxf8.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/root-a3d3Qwip.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/index-C9Hx0Dey.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-Bdg3v8tC.js", "/assets/presence-DJGFvdDh.js", "/assets/seo-pBpFCWsy.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_-BrkpfnBb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/_app+/_layout": { "id": "routes/_app+/_layout", "parentId": "root", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Cbz7Qt-S.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/product-DIAmCwmZ.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-BCTr8uu6.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-DJGFvdDh.js", "/assets/progress-DQt_Bn9o.js", "/assets/index-Bdg3v8tC.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/_app+/account": { "id": "routes/_app+/account", "parentId": "routes/_app+/_layout", "path": "account", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/account-C4Piztoz.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-DJGFvdDh.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.epic_ws[.js]": { "id": "routes/_app+/app.$appName+/test.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.epic_ws[.js]": { "id": "routes/_app+/app.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-Bdnx7fu-.js", "imports": ["/assets/discord-BUWZUTEC.js", "/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": [] }, "routes/_app+/exercise+/_layout": { "id": "routes/_app+/exercise+/_layout", "parentId": "routes/_app+/_layout", "path": "exercise", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-88n0To1b.js", "imports": ["/assets/index-BFGhCX_U.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber": { "id": "routes/_app+/exercise+/$exerciseNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-DCSM0NCG.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-BIMJh_sg.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-DTAM9xh5.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/set-playground-CBHBA46B.js", "/assets/seo-pBpFCWsy.js", "/assets/misc-DUy_whwE.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/tooltip-DO9uwurQ.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/index-BCTr8uu6.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/pe-ChIwTk8v.js", "/assets/index-DZDhtMuq.js", "/assets/index-Bdg3v8tC.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "app", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app-DgTXXO8s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/preview-DaZd0wMb.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/request-info-ByUEfOil.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Bi1TbRTj.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/loading-XhMtj4mp.js", "/assets/discord-BUWZUTEC.js", "/assets/components-Be92gVxW.js", "/assets/index-C9Hx0Dey.js", "/assets/set-playground-CBHBA46B.js", "/assets/tests-DbuyD2cI.js", "/assets/preview-DaZd0wMb.js", "/assets/index-BCTr8uu6.js", "/assets/accordion-D9-D-n9p.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-DoKJvNug.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tests-DbuyD2cI.js", "/assets/components-Be92gVxW.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/accordion-D9-D-n9p.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/set-playground-CBHBA46B.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_._stepNumber.index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.finished": { "id": "routes/_app+/exercise+/$exerciseNumber_.finished", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-nbpk1ToO.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/finished": { "id": "routes/_app+/finished", "parentId": "routes/_app+/_layout", "path": "finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/finished-C0cpfAFL.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/index": { "id": "routes/_app+/index", "parentId": "routes/_app+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Ca4vBON4.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/login": { "id": "routes/_app+/login", "parentId": "routes/_app+/_layout", "path": "login", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-C1oOgi98.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/product-DIAmCwmZ.js", "/assets/workshop-config-WVltG_BV.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/_app+/support": { "id": "routes/_app+/support", "parentId": "routes/_app+/_layout", "path": "support", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/support-CIz02V_r.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Dfmv2zcn.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/cache": { "id": "routes/admin+/cache", "parentId": "routes/admin+/_layout", "path": "cache", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/index": { "id": "routes/admin+/index", "parentId": "routes/admin+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-pkiQppkK.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/admin+/version": { "id": "routes/admin+/version", "parentId": "routes/admin+/_layout", "path": "version", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/version-CaywAlNQ.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/workshop-config-WVltG_BV.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-BhRAIPKc.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/components-Be92gVxW.js", "/assets/accordion-D9-D-n9p.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-C2YNq60k.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/processes": { "id": "routes/processes", "parentId": "root", "path": "processes", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/processes-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/progress": { "id": "routes/progress", "parentId": "root", "path": "progress", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/progress-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/robots[.]txt": { "id": "routes/robots[.]txt", "parentId": "root", "path": "robots.txt", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/robots_._txt-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/set-playground": { "id": "routes/set-playground", "parentId": "root", "path": "set-playground", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/set-playground-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/sitemap[.]xml": { "id": "routes/sitemap[.]xml", "parentId": "root", "path": "sitemap.xml", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/sitemap_._xml-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-bc809ee6.js", "version": "bc809ee6" };
10888
+ const serverManifest = { "entry": { "module": "/assets/entry.client-DqIWuxf8.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/root-D12XnE1S.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/index-C9Hx0Dey.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-Bdg3v8tC.js", "/assets/presence-8FPJKg_8.js", "/assets/seo-pBpFCWsy.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_-BrkpfnBb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/_app+/_layout": { "id": "routes/_app+/_layout", "parentId": "root", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-B8j0pWoF.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/product-DIAmCwmZ.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-BCTr8uu6.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-8FPJKg_8.js", "/assets/progress-DQt_Bn9o.js", "/assets/index-Bdg3v8tC.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/_app+/account": { "id": "routes/_app+/account", "parentId": "routes/_app+/_layout", "path": "account", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/account-DPP4rKOb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-8FPJKg_8.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.js"], "css": [] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.epic_ws[.js]": { "id": "routes/_app+/app.$appName+/test.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.epic_ws[.js]": { "id": "routes/_app+/app.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-Bdnx7fu-.js", "imports": ["/assets/discord-BUWZUTEC.js", "/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": [] }, "routes/_app+/exercise+/_layout": { "id": "routes/_app+/exercise+/_layout", "parentId": "routes/_app+/_layout", "path": "exercise", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-88n0To1b.js", "imports": ["/assets/index-BFGhCX_U.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber": { "id": "routes/_app+/exercise+/$exerciseNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-DCSM0NCG.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-BIMJh_sg.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-DTAM9xh5.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/set-playground-CBHBA46B.js", "/assets/seo-pBpFCWsy.js", "/assets/misc-DUy_whwE.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/tooltip-DO9uwurQ.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/index-BCTr8uu6.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/pe-ChIwTk8v.js", "/assets/index-DZDhtMuq.js", "/assets/index-Bdg3v8tC.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "app", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app-DgTXXO8s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/preview-DaZd0wMb.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/request-info-ByUEfOil.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Bi1TbRTj.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/loading-XhMtj4mp.js", "/assets/discord-BUWZUTEC.js", "/assets/components-Be92gVxW.js", "/assets/index-C9Hx0Dey.js", "/assets/set-playground-CBHBA46B.js", "/assets/tests-DbuyD2cI.js", "/assets/preview-DaZd0wMb.js", "/assets/index-BCTr8uu6.js", "/assets/accordion-D9-D-n9p.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-DoKJvNug.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tests-DbuyD2cI.js", "/assets/components-Be92gVxW.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/accordion-D9-D-n9p.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/set-playground-CBHBA46B.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_._stepNumber.index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.finished": { "id": "routes/_app+/exercise+/$exerciseNumber_.finished", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-nbpk1ToO.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/finished": { "id": "routes/_app+/finished", "parentId": "routes/_app+/_layout", "path": "finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/finished-C0cpfAFL.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/index": { "id": "routes/_app+/index", "parentId": "routes/_app+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Ca4vBON4.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/login": { "id": "routes/_app+/login", "parentId": "routes/_app+/_layout", "path": "login", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-C1oOgi98.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/product-DIAmCwmZ.js", "/assets/workshop-config-WVltG_BV.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/_app+/support": { "id": "routes/_app+/support", "parentId": "routes/_app+/_layout", "path": "support", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/support-CIz02V_r.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Dfmv2zcn.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/cache": { "id": "routes/admin+/cache", "parentId": "routes/admin+/_layout", "path": "cache", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/index": { "id": "routes/admin+/index", "parentId": "routes/admin+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-pkiQppkK.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/admin+/version": { "id": "routes/admin+/version", "parentId": "routes/admin+/_layout", "path": "version", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/version-lxUUxt3s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/workshop-config-WVltG_BV.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-BhRAIPKc.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/components-Be92gVxW.js", "/assets/accordion-D9-D-n9p.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-C2YNq60k.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/processes": { "id": "routes/processes", "parentId": "root", "path": "processes", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/processes-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/progress": { "id": "routes/progress", "parentId": "root", "path": "progress", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/progress-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/robots[.]txt": { "id": "routes/robots[.]txt", "parentId": "root", "path": "robots.txt", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/robots_._txt-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/set-playground": { "id": "routes/set-playground", "parentId": "root", "path": "set-playground", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/set-playground-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/sitemap[.]xml": { "id": "routes/sitemap[.]xml", "parentId": "root", "path": "sitemap.xml", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/sitemap_._xml-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-a8336fab.js", "version": "a8336fab" };
11303
10889
  const mode = "production";
11304
10890
  const assetsBuildDirectory = "build/client";
11305
10891
  const basename = "/";