@epic-web/workshop-app 5.4.1 → 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 (26) 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-e5b2a6e1.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/server/index.js +159 -573
  21. package/build/server/index.js.map +1 -1
  22. package/package.json +3 -3
  23. package/build/client/assets/_layout-Cbz7Qt-S.js +0 -6
  24. package/build/client/assets/_layout-Cbz7Qt-S.js.map +0 -1
  25. package/build/client/assets/presence-DJGFvdDh.js +0 -28
  26. 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, {
@@ -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-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-e5b2a6e1.js", "version": "e5b2a6e1" };
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 = "/";