@cdmbase/wiki-browser 12.0.18-alpha.10

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 (367) hide show
  1. package/LICENSE +21 -0
  2. package/lib/components/Logo.d.ts +4 -0
  3. package/lib/components/Logo.d.ts.map +1 -0
  4. package/lib/components/Logo.js +16 -0
  5. package/lib/components/Logo.js.map +1 -0
  6. package/lib/components/help/SidebarSearch.d.ts +8 -0
  7. package/lib/components/help/SidebarSearch.d.ts.map +1 -0
  8. package/lib/components/help/SidebarSearch.js +111 -0
  9. package/lib/components/help/SidebarSearch.js.map +1 -0
  10. package/lib/components/help/index.d.ts +2 -0
  11. package/lib/components/help/index.d.ts.map +1 -0
  12. package/lib/components/landing/FeatureCard.d.ts +13 -0
  13. package/lib/components/landing/FeatureCard.d.ts.map +1 -0
  14. package/lib/components/landing/FeatureCard.js +85 -0
  15. package/lib/components/landing/FeatureCard.js.map +1 -0
  16. package/lib/components/landing/QuickLinkCard.d.ts +8 -0
  17. package/lib/components/landing/QuickLinkCard.d.ts.map +1 -0
  18. package/lib/components/landing/QuickLinkCard.js +26 -0
  19. package/lib/components/landing/QuickLinkCard.js.map +1 -0
  20. package/lib/components/landing/SearchInput.d.ts +10 -0
  21. package/lib/components/landing/SearchInput.d.ts.map +1 -0
  22. package/lib/components/landing/SearchInput.js +223 -0
  23. package/lib/components/landing/SearchInput.js.map +1 -0
  24. package/lib/components/landing/index.d.ts +4 -0
  25. package/lib/components/landing/index.d.ts.map +1 -0
  26. package/lib/components/welcome.d.ts +3 -0
  27. package/lib/components/welcome.d.ts.map +1 -0
  28. package/lib/compute.d.ts +4 -0
  29. package/lib/compute.d.ts.map +1 -0
  30. package/lib/compute.js +96 -0
  31. package/lib/compute.js.map +1 -0
  32. package/lib/config/env-config.d.ts +4 -0
  33. package/lib/config/env-config.d.ts.map +1 -0
  34. package/lib/config/env-config.js +7 -0
  35. package/lib/config/env-config.js.map +1 -0
  36. package/lib/docs.config.d.ts +48 -0
  37. package/lib/docs.config.d.ts.map +1 -0
  38. package/lib/index.d.ts +4 -0
  39. package/lib/index.d.ts.map +1 -0
  40. package/lib/index.js +2 -0
  41. package/lib/index.js.map +1 -0
  42. package/lib/loaders/search.d.ts +1 -0
  43. package/lib/loaders/search.d.ts.map +1 -0
  44. package/lib/module.d.ts +4 -0
  45. package/lib/module.d.ts.map +1 -0
  46. package/lib/module.js +11 -0
  47. package/lib/module.js.map +1 -0
  48. package/lib/pages/ArticlePage/ArticlePage.d.ts +4 -0
  49. package/lib/pages/ArticlePage/ArticlePage.d.ts.map +1 -0
  50. package/lib/pages/ArticlePage/ArticlePage.js +222 -0
  51. package/lib/pages/ArticlePage/ArticlePage.js.map +1 -0
  52. package/lib/pages/ArticlePage/index.d.ts +3 -0
  53. package/lib/pages/ArticlePage/index.d.ts.map +1 -0
  54. package/lib/pages/ArticlePage/index.js +3 -0
  55. package/lib/pages/ArticlePage/index.js.map +1 -0
  56. package/lib/pages/CategoryCollection/CategoryCollection.d.ts +4 -0
  57. package/lib/pages/CategoryCollection/CategoryCollection.d.ts.map +1 -0
  58. package/lib/pages/CategoryCollection/CategoryCollection.js +103 -0
  59. package/lib/pages/CategoryCollection/CategoryCollection.js.map +1 -0
  60. package/lib/pages/CategoryCollection/index.d.ts +3 -0
  61. package/lib/pages/CategoryCollection/index.d.ts.map +1 -0
  62. package/lib/pages/CategoryCollection/index.js +3 -0
  63. package/lib/pages/CategoryCollection/index.js.map +1 -0
  64. package/lib/pages/Help/HelpIndex.d.ts +4 -0
  65. package/lib/pages/Help/HelpIndex.d.ts.map +1 -0
  66. package/lib/pages/Help/HelpIndex.js +44 -0
  67. package/lib/pages/Help/HelpIndex.js.map +1 -0
  68. package/lib/pages/Help/index.d.ts +4 -0
  69. package/lib/pages/Help/index.d.ts.map +1 -0
  70. package/lib/pages/Help/index.js +226 -0
  71. package/lib/pages/Help/index.js.map +1 -0
  72. package/lib/pages/Landing/index.d.ts +3 -0
  73. package/lib/pages/Landing/index.d.ts.map +1 -0
  74. package/lib/pages/Landing/index.js +281 -0
  75. package/lib/pages/Landing/index.js.map +1 -0
  76. package/lib/routes.json +2533 -0
  77. package/lib/seo.d.ts +22 -0
  78. package/lib/seo.d.ts.map +1 -0
  79. package/lib/slot-fill/FooterFill.d.ts +3 -0
  80. package/lib/slot-fill/FooterFill.d.ts.map +1 -0
  81. package/lib/slot-fill/FooterFill.js +18 -0
  82. package/lib/slot-fill/FooterFill.js.map +1 -0
  83. package/lib/slot-fill/LogoFill.d.ts +5 -0
  84. package/lib/slot-fill/LogoFill.d.ts.map +1 -0
  85. package/lib/slot-fill/LogoFill.js +74 -0
  86. package/lib/slot-fill/LogoFill.js.map +1 -0
  87. package/lib/slot-fill/consts.d.ts +5 -0
  88. package/lib/slot-fill/consts.d.ts.map +1 -0
  89. package/lib/slot-fill/consts.js +1 -0
  90. package/lib/slot-fill/consts.js.map +1 -0
  91. package/lib/slot-fill/index.d.ts +4 -0
  92. package/lib/slot-fill/index.d.ts.map +1 -0
  93. package/lib/templates/assets/images/add-link-frontend.png +0 -0
  94. package/lib/templates/assets/images/add-package-backend.png +0 -0
  95. package/lib/templates/assets/images/add-to-backend-module.png +0 -0
  96. package/lib/templates/assets/images/add-upload-client-frontend.png +0 -0
  97. package/lib/templates/assets/images/additional-parameters.png +0 -0
  98. package/lib/templates/assets/images/aeh-implementation.png +0 -0
  99. package/lib/templates/assets/images/aeh-usage.png +0 -0
  100. package/lib/templates/assets/images/apollo-client/recommendation_cache_mgmt.png +0 -0
  101. package/lib/templates/assets/images/app-deploy-new-version/jenkins1.PNG +0 -0
  102. package/lib/templates/assets/images/app-deploy-new-version/jenkins2.PNG +0 -0
  103. package/lib/templates/assets/images/auth-wrapper-code.png +0 -0
  104. package/lib/templates/assets/images/cdebase.png +0 -0
  105. package/lib/templates/assets/images/cdm-locales-directory.png +0 -0
  106. package/lib/templates/assets/images/client-settings.png +0 -0
  107. package/lib/templates/assets/images/codegen_file_update.png +0 -0
  108. package/lib/templates/assets/images/configuration.png +0 -0
  109. package/lib/templates/assets/images/copy-plugin.png +0 -0
  110. package/lib/templates/assets/images/docusaurus.png +0 -0
  111. package/lib/templates/assets/images/error-link.png +0 -0
  112. package/lib/templates/assets/images/error-sample.png +0 -0
  113. package/lib/templates/assets/images/extension copy.png +0 -0
  114. package/lib/templates/assets/images/extension.png +0 -0
  115. package/lib/templates/assets/images/graphql/graphql-folder-backend.png +0 -0
  116. package/lib/templates/assets/images/graphql/graphql-folder-with-gql.png +0 -0
  117. package/lib/templates/assets/images/i18n-config.png +0 -0
  118. package/lib/templates/assets/images/image.png +0 -0
  119. package/lib/templates/assets/images/logo.svg +10 -0
  120. package/lib/templates/assets/images/logo1.svg +1 -0
  121. package/lib/templates/assets/images/modify-upload-false-server.png +0 -0
  122. package/lib/templates/assets/images/navigation-auth-enabled.png +0 -0
  123. package/lib/templates/assets/images/org-dashboard-navigation.png +0 -0
  124. package/lib/templates/assets/images/org-navigation.png +0 -0
  125. package/lib/templates/assets/images/preferences_graphql_type.png +0 -0
  126. package/lib/templates/assets/images/provider.png +0 -0
  127. package/lib/templates/assets/images/route-config.png +0 -0
  128. package/lib/templates/assets/images/service-accounts.png +0 -0
  129. package/lib/templates/assets/images/source-code/source-code-environments.png +0 -0
  130. package/lib/templates/assets/images/source-code/source-code-organization.png +0 -0
  131. package/lib/templates/assets/images/spin-clone-develop-deployment/jenkins-changes.png +0 -0
  132. package/lib/templates/assets/images/spin-clone-develop-deployment/lerna-changes.png +0 -0
  133. package/lib/templates/assets/images/spin-clone-develop-deployment/root-package-json-changes.png +0 -0
  134. package/lib/templates/assets/images/spin-clone-develop-deployment/values-dev-changes.png +0 -0
  135. package/lib/templates/assets/images/sso-mappers.png +0 -0
  136. package/lib/templates/assets/images/sso-picture-mapper.png +0 -0
  137. package/lib/templates/assets/images/sso-settings.png +0 -0
  138. package/lib/templates/assets/images/timesheet_apollo_cache.png +0 -0
  139. package/lib/templates/assets/images/timesheet_query.png +0 -0
  140. package/lib/templates/assets/images/tutorial/docsVersionDropdown.png +0 -0
  141. package/lib/templates/assets/images/tutorial/localeDropdown.png +0 -0
  142. package/lib/templates/assets/images/unauthenticated.png +0 -0
  143. package/lib/templates/assets/images/undraw_docusaurus_mountain.svg +170 -0
  144. package/lib/templates/assets/images/undraw_docusaurus_react.svg +169 -0
  145. package/lib/templates/assets/images/undraw_docusaurus_tree.svg +1 -0
  146. package/lib/templates/assets/images/vite-plugin-config.png +0 -0
  147. package/lib/templates/content/docs/Generators/Project/generate-fullproject.md +12 -0
  148. package/lib/templates/content/docs/LLM/Logger.llm.md +194 -0
  149. package/lib/templates/content/docs/LLM/backend-proxies-services-llm.md +2687 -0
  150. package/lib/templates/content/docs/LLM/backend-service-llm.md +3384 -0
  151. package/lib/templates/content/docs/LLM/db_migration_llm.md +954 -0
  152. package/lib/templates/content/docs/LLM/frontend/REMIX-15.3-upgrade-llm.md +1245 -0
  153. package/lib/templates/content/docs/LLM/inngest/INNGEST_FUNCTION_DEVELOPMENT_GUIDE_LLM.md +1241 -0
  154. package/lib/templates/content/docs/LLM/inngest/INNGEST_NAMESPACE_LLM.md +384 -0
  155. package/lib/templates/content/docs/LLM/llm_workflow_namespace.md +384 -0
  156. package/lib/templates/content/docs/LLM/organization-components-form-llm.md +1395 -0
  157. package/lib/templates/content/docs/LLM/page-component-llm.md +173 -0
  158. package/lib/templates/content/docs/LLM/preferences-settings-llm.md +2781 -0
  159. package/lib/templates/content/docs/LLM/tailwind-css-llm.md +502 -0
  160. package/lib/templates/content/docs/UI/SchemaBasedUI.md +334 -0
  161. package/lib/templates/content/docs/UI/SlotFillComponent.md +334 -0
  162. package/lib/templates/content/docs/adminide-modules/account/auth0-login.md +31 -0
  163. package/lib/templates/content/docs/adminide-modules/account/index.md +14 -0
  164. package/lib/templates/content/docs/adminide-modules/account/keycloak-remix-setup.md +86 -0
  165. package/lib/templates/content/docs/adminide-modules/account/remix-auth-setup.md +79 -0
  166. package/lib/templates/content/docs/adminide-modules/account/various-auth-qatest.md +157 -0
  167. package/lib/templates/content/docs/adminide-modules/api-builders/graphql.md +906 -0
  168. package/lib/templates/content/docs/adminide-modules/billing/payments/index.md +14 -0
  169. package/lib/templates/content/docs/adminide-modules/billing/payments/stripe/index.md +14 -0
  170. package/lib/templates/content/docs/adminide-modules/billing/payments/stripe/settingup-stripe-locally.md +25 -0
  171. package/lib/templates/content/docs/adminide-modules/billing/tier-config.md +293 -0
  172. package/lib/templates/content/docs/adminide-modules/connectors/Connector.md +207 -0
  173. package/lib/templates/content/docs/adminide-modules/file-upload/index.md +16 -0
  174. package/lib/templates/content/docs/adminide-modules/file-upload/setup.md +435 -0
  175. package/lib/templates/content/docs/adminide-modules/file-upload/upload-file-using-signed-url.md +161 -0
  176. package/lib/templates/content/docs/adminide-modules/preferences/AddAdditionalPermissions.md +151 -0
  177. package/lib/templates/content/docs/adminide-modules/preferences/Configuration.md +241 -0
  178. package/lib/templates/content/docs/adminide-modules/preferences/Policy-Configuration.md +61 -0
  179. package/lib/templates/content/docs/adminide-modules/preferences/UI-components/ResourceSettingsLoader.md +319 -0
  180. package/lib/templates/content/docs/adminide-modules/preferences/contribute_scope_target.md +280 -0
  181. package/lib/templates/content/docs/adminide-modules/preferences/generate-urii.md +94 -0
  182. package/lib/templates/content/docs/adminide-modules/preferences/index.md +28 -0
  183. package/lib/templates/content/docs/adminide-modules/preferences/machine-configuration.md +157 -0
  184. package/lib/templates/content/docs/adminide-modules/preferences/pageSettings/generateCdecodeUri.md +1289 -0
  185. package/lib/templates/content/docs/adminide-modules/preferences/pageSettings/migratingFromUseSettings.md +215 -0
  186. package/lib/templates/content/docs/adminide-modules/preferences/permissions/Roles-Permissions.md +72 -0
  187. package/lib/templates/content/docs/adminide-modules/preferences/permissions/settingUserPermissions.md +139 -0
  188. package/lib/templates/content/docs/adminide-modules/preferences/preference-dependency.md +138 -0
  189. package/lib/templates/content/docs/adminide-modules/preferences/route-based-configuration.md +41 -0
  190. package/lib/templates/content/docs/adminide-modules/preferences/schema-configuration.md +71 -0
  191. package/lib/templates/content/docs/adminide-modules/preferences/supported.md +24 -0
  192. package/lib/templates/content/docs/adminide-modules/preferences/useSettingsLoader.md +248 -0
  193. package/lib/templates/content/docs/adminide-modules/project-tools/auth-providers.md +1317 -0
  194. package/lib/templates/content/docs/adminide-modules/project-tools/keycloak-guide.md +543 -0
  195. package/lib/templates/content/docs/adminide-modules/project-tools/tenant-management/tenant-based-authentication.md +846 -0
  196. package/lib/templates/content/docs/adminide-modules/project-tools/tenant-management/tenant-management.md +708 -0
  197. package/lib/templates/content/docs/adminide-modules/project-tools/tenant-management/tenants.md +1117 -0
  198. package/lib/templates/content/docs/chrome-extension/index.md +14 -0
  199. package/lib/templates/content/docs/chrome-extension/setup.md +30 -0
  200. package/lib/templates/content/docs/contributing/adding-package.md +23 -0
  201. package/lib/templates/content/docs/contributing/adding_new_modules.md +99 -0
  202. package/lib/templates/content/docs/contributing/architecture-updates.md +19 -0
  203. package/lib/templates/content/docs/contributing/avoid-using-promises-ui.md +116 -0
  204. package/lib/templates/content/docs/contributing/coding-guidelines.md +111 -0
  205. package/lib/templates/content/docs/contributing/do-and-dont.md +42 -0
  206. package/lib/templates/content/docs/contributing/faq.md +22 -0
  207. package/lib/templates/content/docs/contributing/folder-setup/browser.md +12 -0
  208. package/lib/templates/content/docs/contributing/folder-setup/config.md +12 -0
  209. package/lib/templates/content/docs/contributing/folder-setup/containers-server.md +12 -0
  210. package/lib/templates/content/docs/contributing/folder-setup/core.md +12 -0
  211. package/lib/templates/content/docs/contributing/folder-setup/graphql.md +12 -0
  212. package/lib/templates/content/docs/contributing/folder-setup/index.md +30 -0
  213. package/lib/templates/content/docs/contributing/folder-setup/module.md +12 -0
  214. package/lib/templates/content/docs/contributing/folder-setup/server.md +12 -0
  215. package/lib/templates/content/docs/contributing/folder-setup/services.md +12 -0
  216. package/lib/templates/content/docs/contributing/folder-setup/store.md +12 -0
  217. package/lib/templates/content/docs/contributing/frontend-coding.md +30 -0
  218. package/lib/templates/content/docs/contributing/git-subtree-sharing.md +73 -0
  219. package/lib/templates/content/docs/contributing/graphql-subscriptions.md +69 -0
  220. package/lib/templates/content/docs/contributing/how-to-contribute.md +30 -0
  221. package/lib/templates/content/docs/contributing/how_to_check_pure_esm.md +29 -0
  222. package/lib/templates/content/docs/contributing/index.md +60 -0
  223. package/lib/templates/content/docs/contributing/installation-issues.md +23 -0
  224. package/lib/templates/content/docs/contributing/keyboard-shortcut.md +131 -0
  225. package/lib/templates/content/docs/contributing/language/locale-support.md +12 -0
  226. package/lib/templates/content/docs/contributing/lerna-build-tools.md +516 -0
  227. package/lib/templates/content/docs/contributing/lerna-yarn-workspaces.md +95 -0
  228. package/lib/templates/content/docs/contributing/lint-and-formatter.md +20 -0
  229. package/lib/templates/content/docs/contributing/mobile-setup.md +16 -0
  230. package/lib/templates/content/docs/contributing/project-setup.md +233 -0
  231. package/lib/templates/content/docs/contributing/react/index.md +14 -0
  232. package/lib/templates/content/docs/contributing/react/lazy-component.md +70 -0
  233. package/lib/templates/content/docs/contributing/run-various-options.md +124 -0
  234. package/lib/templates/content/docs/contributing/schema-first-graphql-types.md +37 -0
  235. package/lib/templates/content/docs/contributing/source-code-organization.md +57 -0
  236. package/lib/templates/content/docs/contributing/staging-docker.md +88 -0
  237. package/lib/templates/content/docs/contributing/third-party/apollo-client-v3-tutorials.md +28 -0
  238. package/lib/templates/content/docs/contributing/third-party/index.md +18 -0
  239. package/lib/templates/content/docs/contributing/typescript-contribution.md +16 -0
  240. package/lib/templates/content/docs/devops/app-deploy-new-version.md +30 -0
  241. package/lib/templates/content/docs/devops/index.md +14 -0
  242. package/lib/templates/content/docs/devops/mobile-jenkins-build.md +40 -0
  243. package/lib/templates/content/docs/devops/versioning-the-project.md +128 -0
  244. package/lib/templates/content/docs/error-handler/application-error-handler.md +40 -0
  245. package/lib/templates/content/docs/error-handler/error-handling.md +26 -0
  246. package/lib/templates/content/docs/error-handler/index.md +16 -0
  247. package/lib/templates/content/docs/error-handler/logging-errors.md +14 -0
  248. package/lib/templates/content/docs/feature-api/copy-operation.md +427 -0
  249. package/lib/templates/content/docs/feature-api/feature-browser/assets.md +46 -0
  250. package/lib/templates/content/docs/feature-api/feature-browser/auth-permissions.md +12 -0
  251. package/lib/templates/content/docs/feature-api/feature-browser/feature.md +131 -0
  252. package/lib/templates/content/docs/feature-api/feature-browser/index.md +22 -0
  253. package/lib/templates/content/docs/feature-api/feature-browser/routes-menu.md +110 -0
  254. package/lib/templates/content/docs/feature-api/feature-browser/routing-convention.md +124 -0
  255. package/lib/templates/content/docs/feature-api/feature-browser/routing.md +338 -0
  256. package/lib/templates/content/docs/feature-api/feature-mobile/auth-permissions.md +20 -0
  257. package/lib/templates/content/docs/feature-api/feature-mobile/feature.md +130 -0
  258. package/lib/templates/content/docs/feature-api/feature-mobile/index.md +18 -0
  259. package/lib/templates/content/docs/feature-api/feature-mobile/navigation.md +187 -0
  260. package/lib/templates/content/docs/feature-api/feature-server/Scheduling.md +44 -0
  261. package/lib/templates/content/docs/feature-api/feature-server/dataloader.md +320 -0
  262. package/lib/templates/content/docs/feature-api/feature-server/dependency-injection.md +81 -0
  263. package/lib/templates/content/docs/feature-api/feature-server/feature.md +65 -0
  264. package/lib/templates/content/docs/feature-api/feature-server/generic-dataloader.md +135 -0
  265. package/lib/templates/content/docs/feature-api/feature-server/index.md +40 -0
  266. package/lib/templates/content/docs/feature-api/feature-server/migration.md +127 -0
  267. package/lib/templates/content/docs/feature-api/feature-server/mongo-model.md +72 -0
  268. package/lib/templates/content/docs/feature-api/feature-server/permissions.md +12 -0
  269. package/lib/templates/content/docs/feature-api/feature-server/policies.md +57 -0
  270. package/lib/templates/content/docs/feature-api/feature-server/preferences.md +57 -0
  271. package/lib/templates/content/docs/feature-api/feature-server/repositories.md +114 -0
  272. package/lib/templates/content/docs/feature-api/feature-server/resolvers.md +126 -0
  273. package/lib/templates/content/docs/feature-api/feature-server/rules.md +132 -0
  274. package/lib/templates/content/docs/feature-api/feature-server/schema.md +12 -0
  275. package/lib/templates/content/docs/feature-api/feature-server/services.md +102 -0
  276. package/lib/templates/content/docs/feature-api/feature-server/setup-resource-crud.md +359 -0
  277. package/lib/templates/content/docs/feature-api/index.md +18 -0
  278. package/lib/templates/content/docs/graphql/apolloClient-mutation.md +94 -0
  279. package/lib/templates/content/docs/graphql/index.md +14 -0
  280. package/lib/templates/content/docs/graphql/scalars.md +15 -0
  281. package/lib/templates/content/docs/help/index.md +14 -0
  282. package/lib/templates/content/docs/help/intro.md +16 -0
  283. package/lib/templates/content/docs/intl/ant-design-menu-translation.md +74 -0
  284. package/lib/templates/content/docs/intl/intl-namespace.md +129 -0
  285. package/lib/templates/content/docs/intl/vite-plugin-intl.md +87 -0
  286. package/lib/templates/content/docs/intl/webpack-plugin-intl.md +12 -0
  287. package/lib/templates/content/docs/intro.md +18 -0
  288. package/lib/templates/content/docs/knowledge/basic-fullstack.md +238 -0
  289. package/lib/templates/content/docs/mailing/index.md +14 -0
  290. package/lib/templates/content/docs/mailing/mailing-template.md +148 -0
  291. package/lib/templates/content/docs/mobile/App-navigation-generator.md +410 -0
  292. package/lib/templates/content/docs/mobile/MobileTestCases.md +264 -0
  293. package/lib/templates/content/docs/mobile/eas-profile-build.md +107 -0
  294. package/lib/templates/content/docs/mobile/expo-push-notification-setup.md +216 -0
  295. package/lib/templates/content/docs/mobile/index.md +14 -0
  296. package/lib/templates/content/docs/mobile/routes.md +83 -0
  297. package/lib/templates/content/docs/organization/adding-account-context.md +116 -0
  298. package/lib/templates/content/docs/organization/adding-org-mobile-navigation.md +22 -0
  299. package/lib/templates/content/docs/organization/adding-org-web-navigation.md +12 -0
  300. package/lib/templates/content/docs/organization/index.md +20 -0
  301. package/lib/templates/content/docs/organization/initialization.md +20 -0
  302. package/lib/templates/content/docs/organization/organization-resource-vs-resource.md +112 -0
  303. package/lib/templates/content/docs/remix/configuration/component-structure-best-practices.md +152 -0
  304. package/lib/templates/content/docs/remix/configuration/configurations.md +218 -0
  305. package/lib/templates/content/docs/remix/configuration/css-import-and-stylesheets.md +142 -0
  306. package/lib/templates/content/docs/remix/configuration/dont-subcomponent-network.md +166 -0
  307. package/lib/templates/content/docs/remix/configuration/generated-data-loaders.md +122 -0
  308. package/lib/templates/content/docs/remix/configuration/generated-resource-loaders.md +257 -0
  309. package/lib/templates/content/docs/remix/configuration/query-params-generator.md +216 -0
  310. package/lib/templates/content/docs/remix/configuration/routes-extra-icons.md +103 -0
  311. package/lib/templates/content/docs/remix/configuration/routes-json-advanced.md +86 -0
  312. package/lib/templates/content/docs/remix/configuration/routes-json-auth.md +113 -0
  313. package/lib/templates/content/docs/remix/configuration/routes-json-best-practices.md +55 -0
  314. package/lib/templates/content/docs/remix/configuration/routes-json-fields.md +79 -0
  315. package/lib/templates/content/docs/remix/configuration/routes-json-graphql.md +79 -0
  316. package/lib/templates/content/docs/remix/configuration/routes-json-index.md +112 -0
  317. package/lib/templates/content/docs/remix/configuration/routes-json-loaders.md +165 -0
  318. package/lib/templates/content/docs/remix/configuration/routes-json-middleware.md +196 -0
  319. package/lib/templates/content/docs/remix/configuration/routes-json-overview.md +53 -0
  320. package/lib/templates/content/docs/remix/data-loaders.md +43 -0
  321. package/lib/templates/content/docs/remix/devtools/remix-devtools.md +58 -0
  322. package/lib/templates/content/docs/remix/examples/changes-using-servercode.md +79 -0
  323. package/lib/templates/content/docs/remix/extra-icons.md +62 -0
  324. package/lib/templates/content/docs/remix/extra-links.md +65 -0
  325. package/lib/templates/content/docs/remix/generated-data-loaders.md +114 -0
  326. package/lib/templates/content/docs/remix/queryParamsGenerator.md +89 -0
  327. package/lib/templates/content/docs/remix/resources.md +16 -0
  328. package/lib/templates/content/docs/remix/styles.md +132 -0
  329. package/lib/templates/content/docs/remix/wiki.md +12 -0
  330. package/lib/templates/content/docs/security/auth-wrapper/auth-wrapper.md +24 -0
  331. package/lib/templates/content/docs/security/index.md +18 -0
  332. package/lib/templates/content/docs/security/secure-button-mobilenative.md +88 -0
  333. package/lib/templates/content/docs/security/secure-button-web.md +89 -0
  334. package/lib/templates/content/docs/server-side/account-customization.md +82 -0
  335. package/lib/templates/content/docs/server-side/apollo/caching.md +164 -0
  336. package/lib/templates/content/docs/server-side/backend-architecture/FINAL-DECISION.md +209 -0
  337. package/lib/templates/content/docs/server-side/backend-architecture/TRUE-FINAL-ARCHITECTURE.md +603 -0
  338. package/lib/templates/content/docs/server-side/backend-architecture/index1.md +0 -0
  339. package/lib/templates/content/docs/server-side/backend-coding.md +839 -0
  340. package/lib/templates/content/docs/server-side/e2b/manageing-template.md +197 -0
  341. package/lib/templates/content/docs/server-side/index.md +14 -0
  342. package/lib/templates/content/docs/server-side/inngest-functions-module.md +309 -0
  343. package/lib/templates/content/docs/server-side/listen-stripe-events.md +43 -0
  344. package/lib/templates/content/docs/server-side/slug-service.md +323 -0
  345. package/lib/templates/content/docs/tests/index.md +18 -0
  346. package/lib/templates/content/docs/tests/jest-test-debug-vscode.md +40 -0
  347. package/lib/templates/content/docs/tests/known-errors.md +116 -0
  348. package/lib/templates/content/docs/tests/service-test-template.md +118 -0
  349. package/lib/templates/content/docs/tests/test-setup.md +93 -0
  350. package/lib/templates/content/docs/xstate.md +23 -0
  351. package/lib/types.d.ts +37 -0
  352. package/lib/types.d.ts.map +1 -0
  353. package/lib/utils/docsNavigation.d.ts +9 -0
  354. package/lib/utils/docsNavigation.d.ts.map +1 -0
  355. package/lib/utils/docsNavigation.js +37 -0
  356. package/lib/utils/docsNavigation.js.map +1 -0
  357. package/lib/utils/helpCenterUtils.d.ts +26 -0
  358. package/lib/utils/helpCenterUtils.d.ts.map +1 -0
  359. package/lib/utils/index.d.ts +3 -0
  360. package/lib/utils/index.d.ts.map +1 -0
  361. package/lib/utils/index.js +3 -0
  362. package/lib/utils/index.js.map +1 -0
  363. package/lib/utils/markdownLoader.d.ts +36 -0
  364. package/lib/utils/markdownLoader.d.ts.map +1 -0
  365. package/lib/utils/markdownLoader.js +2242 -0
  366. package/lib/utils/markdownLoader.js.map +1 -0
  367. package/package.json +71 -0
@@ -0,0 +1,1245 @@
1
+ # Remix 2.15.3 Upgrade Summary - Frontend Server
2
+
3
+ ## Upgrade Completed: November 2025
4
+
5
+ This document summarizes the changes made to upgrade the `yantra-stack/servers/frontend-server` to **Remix 2.15.3** with v3 future flags.
6
+
7
+ ## Dependency Version Updates
8
+
9
+ As part of this upgrade, the following major dependencies were also updated:
10
+
11
+ ### @common-stack packages (updated to 8.2.2-alpha.0)
12
+
13
+ | Package | Old Version | New Version |
14
+ | ------------------------------------ | -------------- | ----------------- |
15
+ | `@common-stack/env-list-loader` | 7.2.1-alpha.5 | **8.2.2-alpha.0** |
16
+ | `@common-stack/generate-plugin` | 7.2.1-alpha.12 | **8.2.2-alpha.0** |
17
+ | `@common-stack/rollup-vite-utils` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
18
+ | `@common-stack/cache-api-server` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
19
+ | `@common-stack/client-core` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
20
+ | `@common-stack/client-react` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
21
+ | `@common-stack/components-pro` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
22
+ | `@common-stack/core` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
23
+ | `@common-stack/frontend-stack-react` | 7.2.1-alpha.12 | **8.2.2-alpha.0** |
24
+ | `@common-stack/remix-router-redux` | 7.2.1-alpha.5 | **8.2.2-alpha.0** |
25
+ | `@common-stack/server-core` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
26
+ | `@common-stack/server-stack` | 7.2.1-alpha.12 | **8.2.2-alpha.0** |
27
+ | `@common-stack/store-mongo` | 7.2.1-alpha.11 | **8.2.2-alpha.0** |
28
+
29
+ ### @adminide-stack packages (updated to 13.0.4-alpha.x)
30
+
31
+ | Package | Old Version | New Version |
32
+ | -------------------------------------------- | ---------------- | ------------------ |
33
+ | `@adminide-stack/account-api-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
34
+ | `@adminide-stack/extension-module-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
35
+ | `@adminide-stack/marketplace-module-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
36
+ | `@adminide-stack/platform-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
37
+ | `@adminide-stack/project-mgmt-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
38
+ | `@adminide-stack/user-auth0-server` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
39
+ | `@adminide-stack/account-api-browser` | 12.0.4-alpha.351 | **13.0.4-alpha.1** |
40
+ | `@adminide-stack/account-api-client` | 12.0.4-alpha.349 | **13.0.4-alpha.1** |
41
+ | `@adminide-stack/extension-module-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
42
+ | `@adminide-stack/marketplace-module-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
43
+ | `@adminide-stack/mongo-admin-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
44
+ | `@adminide-stack/platform-browser` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
45
+ | `@adminide-stack/platform-client` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
46
+ | `@adminide-stack/project-mgmt-browser` | 12.0.4-alpha.351 | **13.0.4-alpha.1** |
47
+ | `@adminide-stack/react-shared-components` | 12.0.4-alpha.348 | **13.0.4-alpha.0** |
48
+ | `@adminide-stack/user-auth0-browser` | 12.0.4-alpha.349 | **13.0.4-alpha.1** |
49
+
50
+ ### @admin-layout packages (updated to 12.2.1-alpha.x)
51
+
52
+ | Package | Old Version | New Version |
53
+ | ----------------------------------- | ---------------- | ------------------ |
54
+ | `@admin-layout/assets` | 12.0.16-alpha.36 | **12.2.1-alpha.0** |
55
+ | `@admin-layout/tailwind-design-pro` | 12.0.16-alpha.68 | **12.2.1-alpha.5** |
56
+
57
+ ## Changes Applied
58
+
59
+ ### 1. **Entry Client** (`src/entry.client.tsx`)
60
+
61
+ - ✅ Removed `StrictMode` wrapper from hydration
62
+ - ✅ Removed `CacheProvider` from `@emotion/react`
63
+ - ✅ Removed `createEmotionCache` import and usage
64
+ - ✅ Simplified hydration without emotion wrapper
65
+ - **Reason**: Remix 2.15.3 recommends removing StrictMode in production to avoid double-rendering issues. Emotion is no longer needed for SSR styling.
66
+
67
+ ### 2. **Entry Server** (`src/entry.server.tsx`)
68
+
69
+ - ✅ Removed deprecated `abortDelay` prop from `RemixServer`
70
+ - ✅ Changed `ABORT_DELAY` constant to exported `streamTimeout`
71
+ - ✅ Removed `CacheProvider` from `@emotion/react`
72
+ - ✅ Removed `renderStylesToNodeStream` from `@emotion/server`
73
+ - ✅ Removed `createEmotionCache` import and usage
74
+ - ✅ Updated timeout to `streamTimeout + 1000`
75
+ - ✅ Simplified rendering pipeline without emotion styles
76
+ - **Reason**: `abortDelay` is deprecated in Remix 2.15.3, replaced by `streamTimeout` pattern. Emotion SSR is no longer needed.
77
+
78
+ ### 3. **Server Configuration** (`server.js`)
79
+
80
+ - ✅ Removed `installGlobals()` - Not needed with Node.js 20+ (native `Response.json()` support)
81
+ - ✅ Removed unused imports: `readFileSync`, `fileURLToPath`, `dirname`, `join`
82
+ - ✅ Updated JSON import syntax from `JSON.parse(readFileSync(...))` to `import config from '...' with { type: 'json' }`
83
+ - ✅ Added `.well-known/*` handler to ignore Chrome DevTools requests
84
+ - **Reason**: ES2024 standard compliance (Node.js 20.10+), cleaner code
85
+
86
+ **Important**: Requires Node.js 20+ for native `Response.json()` support. Use `nvm use 22` to ensure compatibility.
87
+
88
+ ### 4. **Vite Configuration** (`vite.config.ts`)
89
+
90
+ - ✅ **Removed `routes: routesConfig`** - Must use `routes.ts` file instead (v3_routeConfig flag requires this)
91
+ - ✅ **Removed `installGlobals()`** - Not needed with Node.js 20+ (native `Response.json()` support)
92
+ - ✅ Removed unused imports: `readFileSync`, `postcss`, `defineRoutesConfig`, `performCopyOperations`
93
+ - ✅ Updated JSON import syntax to `with` clause: `import config from './app/cde-webconfig.json' with { type: 'json' }`
94
+ - ✅ Added Future module declaration for `v3_singleFetch` type support
95
+ - ✅ Added v3 future flags:
96
+ ```typescript
97
+ future: {
98
+ unstable_optimizeDeps: true,
99
+ v3_fetcherPersist: true,
100
+ v3_relativeSplatPath: true,
101
+ v3_throwAbortReason: true,
102
+ v3_singleFetch: true,
103
+ v3_lazyRouteDiscovery: true,
104
+ v3_routeConfig: true,
105
+ }
106
+ ```
107
+ - ✅ Added `optimizeDeps.include` for Radix UI packages pre-bundling
108
+ - ✅ Added `optimizeDeps.force: true` for better dependency optimization
109
+ - ✅ Updated `ssr.noExternal` with more Radix UI packages for proper SSR
110
+ - ✅ Updated `cjsInterop` dependencies to include `@rjsf/**`, `react-timer-hook`, `@ant-design/icons`, etc.
111
+ - ✅ Added `worker.format: 'es'` for ES module workers
112
+
113
+ **Important**: The `routes` config option is NOT supported when a `routes.ts` file is present. You must remove `routes: routesConfig` from vite.config.ts and migrate routes to `routes.ts`.
114
+
115
+ ### 5. **Route Configuration** (`src/routes.ts`)
116
+
117
+ - ✅ **NEW FILE**: Created v3 route configuration file
118
+ - Uses `remixRoutesOptionAdapter` for file-based routing
119
+ - Integrates with existing `defineRoutesConfig` from `@common-stack/rollup-vite-utils`
120
+ - Handles production copy operations and sync-meta.json loading
121
+
122
+ ## Packages Added
123
+
124
+ **Location**: `servers/frontend-server/package.json` (devDependencies)
125
+
126
+ ```json
127
+ {
128
+ "devDependencies": {
129
+ "@remix-run/dev": "~2.15.3",
130
+ "@remix-run/fs-routes": "~2.15.3",
131
+ "@remix-run/route-config": "~2.15.3",
132
+ "@remix-run/routes-option-adapter": "~2.15.3",
133
+ "@remix-run/serve": "~2.15.3"
134
+ }
135
+ }
136
+ ```
137
+
138
+ These packages enable the v3 routing configuration system.
139
+
140
+ **Important**: The `@remix-run/fs-routes` package is required to prevent "Response.json is not a function" errors in Remix 2.15.3.
141
+
142
+ **Note**: These should be added to the frontend-server's package.json, NOT the root workspace package.json. This follows the pattern used in adminIde-stack.
143
+
144
+ ## Files Modified
145
+
146
+ 1. `src/entry.client.tsx` - Client hydration entry point
147
+ 2. `src/entry.server.tsx` - Server rendering entry point
148
+ 3. `server.js` - Express server configuration
149
+ 4. `vite.config.ts` - Vite build configuration
150
+ 5. `src/routes.ts` - **NEW**: v3 route configuration
151
+ 6. `src/root.tsx` - Updated to match adminide-stack (imports, data function, Layout updates)
152
+
153
+ ## Additional Configuration Updates
154
+
155
+ ### Root `package.json` Updates
156
+
157
+ - Added `@common-stack/codegen-zod`: `^8.2.2-alpha.0` to devDependencies
158
+ - Added `zod`: `^4.0.0` to resolutions
159
+ - Added `postcss`: `^8.5.1` to resolutions
160
+ - Updated `prettier`: `^2.7.1` → `^3.4.0`
161
+
162
+ ### `cdecode-config.json` Updates
163
+
164
+ - Added Zod schema generation configuration
165
+ - Added `generated-zod-schemas.ts` output with `@common-stack/codegen-zod/graphql` plugin
166
+ - Added `serviceSchemas` configuration for service schema generation
167
+ - Added hook for running `generateAllServiceSchemas.js` after codegen
168
+ - Simplified schema/document paths to use `%discoveredSchemas%` and `%discoveredDocuments%`
169
+
170
+ ### `src/root.tsx` Updates (matching adminide-stack)
171
+
172
+ - Changed import from `json` to `data` from `@remix-run/react`
173
+ - Added `useLoaderData`, `useRouteError` imports
174
+ - Changed `ErrorBoundary` to use `ApplicationErrorHandler, RemixErrorBoundary as ErrorBoundary` from `@admin-layout/tailwind-ui`
175
+ - Added error handling for settings loader with try/catch block
176
+ - Renamed loader data variable to `loaderData` with proper typing `{ locale: any; __ENV__?: any }`
177
+ - Added fallback `|| 'en'` for locale
178
+ - Updated `__ENV__` serialization with `|| {}` for safety
179
+ - Added Symbol.observable polyfill in `<head>` section (CRITICAL: must load before other scripts)
180
+ - Wrapped `App` component with `ApplicationErrorHandler` component
181
+
182
+ ## Verification Steps
183
+
184
+ 1. ✅ TypeScript compilation: No errors
185
+ 2. ✅ Package installation: Both routing packages installed successfully
186
+ 3. ✅ Syntax validation: All files pass linting
187
+ 4. ✅ Future flags: All 6 v3 flags enabled
188
+
189
+ ## Next Steps
190
+
191
+ 1. **Install dependencies**:
192
+
193
+ ```bash
194
+ # From the root of yantra-stack
195
+ yarn
196
+
197
+ # Then run the dependency update script to ensure all deps are aligned
198
+ node tools/update-dependencies.mjs
199
+ ```
200
+
201
+ 2. **Test the application**:
202
+
203
+ ```bash
204
+ cd servers/frontend-server
205
+ yarn dev
206
+ ```
207
+
208
+ 3. **Verify routing**:
209
+ - Ensure all routes load correctly
210
+ - Check for any console warnings/errors
211
+ - Test navigation between routes
212
+
213
+ 4. **Monitor for issues**:
214
+ - Check for hydration mismatches
215
+ - Verify SSR works correctly
216
+ - Test dynamic route loading
217
+
218
+ ## References
219
+
220
+ - Main upgrade guide: `/common-stack/REMIX_2.15.3_UPGRADE_GUIDE.md`
221
+ - Remix 2.15.3 release notes: https://github.com/remix-run/remix/releases/tag/remix%402.15.3
222
+ - Future flags documentation: https://remix.run/docs/en/v2/start/future-flags
223
+
224
+ ## Compatibility Requirements
225
+
226
+ **Node.js Version**: 20+ required (22 recommended)
227
+
228
+ - Use `nvm use 22` before running the application
229
+ - Node.js 20+ has native `Response.json()` support, eliminating the need for `installGlobals()`
230
+
231
+ **Minimum Package Versions** (from main upgrade guide):
232
+
233
+ - `common-stack`: 8.2.2-alpha.0 or greater
234
+ - `adminide-stack`: 13.0.4-alpha.0 or greater
235
+ - `admin-layout`: 12.2.1-alpha.0 or greater
236
+
237
+ All packages must be updated to these minimum versions to ensure compatibility.
238
+
239
+ ---
240
+
241
+ ## Docker Configuration Updates
242
+
243
+ ### `Dockerfile` Updates
244
+
245
+ The Dockerfile must be updated to use Node.js 22 base image:
246
+
247
+ ```dockerfile
248
+ # Before
249
+ FROM node:20-alpine AS base
250
+
251
+ # After
252
+ FROM node:22-alpine AS base
253
+ ```
254
+
255
+ **All Dockerfile stages must use Node.js 22:**
256
+
257
+ ```dockerfile
258
+ # Build stage
259
+ FROM node:22-alpine AS builder
260
+
261
+ # Production stage
262
+ FROM node:22-alpine AS production
263
+
264
+ # Development stage (if applicable)
265
+ FROM node:22-alpine AS development
266
+ ```
267
+
268
+ **Reason**: Node.js 22+ is required for:
269
+
270
+ - Native `Response.json()` support (eliminates need for `installGlobals()`)
271
+ - ES2024 `import ... with { type: 'json' }` syntax support
272
+ - Remix 2.15.3 v3 future flags compatibility
273
+
274
+ ---
275
+
276
+ ## Jenkins Configuration Updates
277
+
278
+ ### `Jenkinsfile` Updates
279
+
280
+ - ✅ Updated `NODEJS_TOOL_VERSION` default to `nodejs22` (was `nodejs20`)
281
+ - ✅ Added `nodejs24` as an option for future compatibility
282
+
283
+ ```groovy
284
+ choice choices: ['nodejs22', 'nodejs20', 'nodejs24'], description: 'Choose NodeJS version', name: 'NODEJS_TOOL_VERSION'
285
+ ```
286
+
287
+ ### Jenkins Build Configuration
288
+
289
+ Ensure all Jenkins build pipelines use Node.js 22:
290
+
291
+ ```groovy
292
+ // In Jenkinsfile or pipeline script
293
+ tools {
294
+ nodejs 'nodejs22'
295
+ }
296
+
297
+ // Or using nvm
298
+ stages {
299
+ stage('Setup') {
300
+ steps {
301
+ sh 'nvm use 22'
302
+ }
303
+ }
304
+ }
305
+ ```
306
+
307
+ **Reason**: Node.js 22+ is required for native `Response.json()` support in Remix 2.15.3.
308
+
309
+ ---
310
+
311
+ ## CRITICAL: Loader Migration (`json` → `data`)
312
+
313
+ ### Breaking Change in Remix 2.15.3
314
+
315
+ With `v3_singleFetch` future flag enabled, all loaders must migrate from using `json()` to `data()`:
316
+
317
+ ```typescript
318
+ // ❌ OLD - Will cause issues with v3_singleFetch
319
+ import { json } from '@remix-run/react';
320
+
321
+ export const loader = async () => {
322
+ return json({ message: 'Hello' });
323
+ };
324
+
325
+ // ✅ NEW - Required for Remix 2.15.3
326
+ import { data } from '@remix-run/react';
327
+
328
+ export const loader = async () => {
329
+ return data({ message: 'Hello' });
330
+ };
331
+ ```
332
+
333
+ ### Files That Need Migration
334
+
335
+ Search your codebase for all files using `json` from `@remix-run/react` or `@remix-run/node`:
336
+
337
+ ```bash
338
+ # Find all files using json import
339
+ grep -r "import.*json.*from '@remix-run" --include="*.tsx" --include="*.ts" packages/ servers/
340
+
341
+ # Find all files using json() in loaders
342
+ grep -r "return json(" --include="*.tsx" --include="*.ts" packages/ servers/
343
+ ```
344
+
345
+ ### Common Locations to Check
346
+
347
+ 1. **Route files** (`routes/*.tsx`)
348
+ 2. **Root layout** (`root.tsx`)
349
+ 3. **Package route modules** (e.g., `packages/*/browser/src/routes/*.tsx`)
350
+ 4. **Server loaders** (any file with `loader` export)
351
+ 5. **Action handlers** (any file with `action` export)
352
+
353
+ ### Migration Pattern
354
+
355
+ ```typescript
356
+ // Before
357
+ import { json, useLoaderData } from '@remix-run/react';
358
+
359
+ export const loader = async ({ request, context, params }) => {
360
+ const data = await fetchData();
361
+ return json(
362
+ { data },
363
+ {
364
+ headers: {
365
+ 'Cache-Control': 'max-age=300',
366
+ },
367
+ },
368
+ );
369
+ };
370
+
371
+ // After
372
+ import { data, useLoaderData } from '@remix-run/react';
373
+
374
+ export const loader = async ({ request, context, params }) => {
375
+ const result = await fetchData();
376
+ return data(
377
+ { data: result },
378
+ {
379
+ headers: [['Cache-Control', 'max-age=300']],
380
+ },
381
+ );
382
+ };
383
+ ```
384
+
385
+ ### Headers Format Change
386
+
387
+ Note that headers format also changes with `data()`:
388
+
389
+ ```typescript
390
+ // ❌ OLD with json() - Object format
391
+ return json(data, {
392
+ headers: {
393
+ 'Cache-Control': 'max-age=300',
394
+ 'Set-Cookie': cookie,
395
+ },
396
+ });
397
+
398
+ // ✅ NEW with data() - Array of tuples format
399
+ return data(result, {
400
+ headers: [
401
+ ['Cache-Control', 'max-age=300'],
402
+ ['Set-Cookie', cookie],
403
+ ],
404
+ });
405
+
406
+ // ✅ With conditional headers
407
+ return data(result, {
408
+ headers: [['Cache-Control', 'max-age=300'], cookie ? ['Set-Cookie', cookie] : null].filter(Boolean) as [
409
+ string,
410
+ string,
411
+ ][],
412
+ });
413
+ ```
414
+
415
+ ### Packages Requiring Loader Updates
416
+
417
+ The following packages commonly have loaders that need migration:
418
+
419
+ | Package | Files to Check |
420
+ | -------------------------------------------- | ---------------- |
421
+ | `@adminide-stack/account-api-browser` | Route loaders |
422
+ | `@adminide-stack/platform-browser` | Route loaders |
423
+ | `@adminide-stack/project-mgmt-browser` | Route loaders |
424
+ | `@adminide-stack/user-auth0-browser` | Route loaders |
425
+ | `@adminide-stack/extension-module-browser` | Route loaders |
426
+ | `@adminide-stack/marketplace-module-browser` | Route loaders |
427
+ | `@admin-layout/client` | Settings loaders |
428
+ | Local `packages/*/browser` | All route files |
429
+
430
+ ### Verification
431
+
432
+ After migration, verify no `json` imports remain:
433
+
434
+ ```bash
435
+ # Should return no results
436
+ grep -r "import.*{ json" --include="*.tsx" --include="*.ts" packages/ servers/ | grep -v "node_modules"
437
+
438
+ # Also check for json from @remix-run/node
439
+ grep -r "json.*from '@remix-run/node'" --include="*.tsx" --include="*.ts" packages/ servers/ | grep -v "node_modules"
440
+ ```
441
+
442
+ ---
443
+
444
+ ## Complete File Contents
445
+
446
+ ### `server.js`
447
+
448
+ ```javascript
449
+ import express from 'express';
450
+ import compression from 'compression';
451
+ import { createRequestHandler } from '@remix-run/express';
452
+ import './env.js';
453
+ import { performCopyOperations } from '@common-stack/rollup-vite-utils/lib/preStartup/configLoader/configLoader.js';
454
+ import config from './app/cde-webconfig.json' with { type: 'json' };
455
+
456
+ Object.keys(config.buildConfig).forEach((key) => {
457
+ global[key] = config.buildConfig[key];
458
+ });
459
+
460
+ const startServer = async () => {
461
+ await performCopyOperations(config);
462
+
463
+ const { corsMiddleware } = await import(
464
+ `./${config.commonPaths.appPath}/${config.commonPaths.frontendStackPath}/backend/middlewares/cors.js`
465
+ );
466
+ const { containerMiddleware } = await import(
467
+ `./${config.commonPaths.appPath}/${config.commonPaths.frontendStackPath}/backend/middlewares/container.js`
468
+ );
469
+ const { loadContext } = await import(
470
+ `./${config.commonPaths.appPath}/${config.commonPaths.frontendStackPath}/load-context.server.js`
471
+ );
472
+
473
+ const viteDevServer =
474
+ process.env.NODE_ENV === 'production'
475
+ ? undefined
476
+ : await import('vite').then((vite) => {
477
+ return vite.createServer({
478
+ server: { middlewareMode: true },
479
+ });
480
+ });
481
+
482
+ const remixHandler = createRequestHandler({
483
+ getLoadContext: loadContext,
484
+ build: viteDevServer
485
+ ? () => viteDevServer.ssrLoadModule('virtual:remix/server-build')
486
+ : await import('./build/server/index.js'),
487
+ });
488
+
489
+ const app = express();
490
+
491
+ app.use(compression());
492
+ app.disable('x-powered-by');
493
+
494
+ if (viteDevServer) {
495
+ app.use(viteDevServer.middlewares);
496
+ } else {
497
+ app.use('/assets', express.static('build/client/assets', { immutable: true, maxAge: '1y' }));
498
+ }
499
+
500
+ app.use(express.static('build/client', { maxAge: '1h' }));
501
+
502
+ app.use(corsMiddleware);
503
+ app.options('*', corsMiddleware);
504
+
505
+ // Ignore Chrome DevTools and other well-known requests
506
+ app.get('/.well-known/*', (req, res) => {
507
+ res.status(404).json({ error: 'Not found' });
508
+ });
509
+ app.use(async (req, res, next) => {
510
+ let isAssetRequest = (url) =>
511
+ /\.[jt]sx?$/.test(url) ||
512
+ /@id\/__x00__virtual:/.test(url) ||
513
+ /@vite\/client/.test(url) ||
514
+ /node_modules\/vite\/dist\/client\/env/.test(url);
515
+
516
+ if (isAssetRequest(req.url)) {
517
+ next();
518
+ } else {
519
+ return await containerMiddleware(req, res, async () => {
520
+ return remixHandler(req, res, next);
521
+ });
522
+ }
523
+ });
524
+
525
+ const port = process.env.PORT || 3000;
526
+ app.listen(port, () => console.log(`Express server listening at http://localhost:${port}`));
527
+ };
528
+
529
+ startServer().catch((err) => {
530
+ console.error('Failed to start server:', err);
531
+ });
532
+ ```
533
+
534
+ ### `vite.config.ts`
535
+
536
+ ```typescript
537
+ import { defineConfig, ConfigEnv, UserConfig } from 'vite';
538
+ import { vitePlugin as remix } from '@remix-run/dev';
539
+ import { dirname, resolve } from 'path';
540
+ import { fileURLToPath } from 'url';
541
+ // import { remixDevTools } from 'remix-development-tools';
542
+ import tsconfigPaths from 'vite-tsconfig-paths';
543
+ import { i18nInternationalizationPlugin } from '@common-stack/rollup-vite-utils/lib/vite-plugins/i18n-internationalization-plugin.js';
544
+ // import { visualizer } from 'rollup-plugin-visualizer';
545
+ import { loadEnvConfig } from '@common-stack/rollup-vite-utils/lib/preStartup/configLoader/envLoader.js';
546
+ import { cjsInterop } from 'vite-plugin-cjs-interop';
547
+ import { mergeWith } from 'lodash-es';
548
+ import config from './app/cde-webconfig.json' with { type: 'json' };
549
+
550
+ declare module '@remix-run/node' {
551
+ // or cloudflare, deno, etc.
552
+ interface Future {
553
+ v3_singleFetch: true;
554
+ }
555
+ }
556
+
557
+ const directoryName = dirname(fileURLToPath(import.meta.url));
558
+
559
+ export default defineConfig(async ({ isSsrBuild }: ConfigEnv): Promise<UserConfig> => {
560
+ console.log('--- IS SSR BUILD:', isSsrBuild);
561
+
562
+ // Load environment variables from dotenv or other config
563
+ const dotEnvResult = loadEnvConfig(directoryName);
564
+
565
+ // Define environment variables for Vite
566
+ const envVariables = {
567
+ __ENV__: JSON.stringify(dotEnvResult?.parsed),
568
+ __SERVER__: true,
569
+ __CLIENT__: false,
570
+ ...Object.fromEntries(
571
+ Object.entries(config.buildConfig).map(([key, value]) => [
572
+ key,
573
+ typeof value === 'string' ? `"${value.replace(/\\/g, '\\\\')}"` : value,
574
+ ]),
575
+ ),
576
+ };
577
+
578
+ // Vite configuration
579
+ const viteConfig = {
580
+ define: envVariables,
581
+ ssr: {
582
+ // Keep small client-only libraries bundled, including all @radix-ui packages
583
+ // to ensure proper CommonJS to ESM interop handled by cjsInterop plugin
584
+ noExternal: [
585
+ 'react-datepicker',
586
+ /^@radix-ui\//,
587
+ '@radix-ui/react-slot',
588
+ '@radix-ui/react-primitive',
589
+ '@radix-ui/react-compose-refs',
590
+ '@radix-ui/react-context',
591
+ '@radix-ui/react-collection',
592
+ '@radix-ui/react-separator',
593
+ ],
594
+ },
595
+ plugins: [
596
+ // remixDevTools({
597
+ // server: {
598
+ // logs: {
599
+ // cookies: true,
600
+ // defer: true,
601
+ // actions: true,
602
+ // loaders: true,
603
+ // cache: true,
604
+ // siteClear: true,
605
+ // },
606
+ // },
607
+ // }),
608
+ i18nInternationalizationPlugin({
609
+ folderName: 'cdm-locales',
610
+ packages: [...config.modules, ...config.i18n.packages],
611
+ namespaceResolution: 'basename' as any,
612
+ }),
613
+ // visualizer({
614
+ // open: true,
615
+ // filename: 'bundle-analysis.html',
616
+ // }),
617
+ cjsInterop({
618
+ dependencies: [
619
+ '@rjsf/**',
620
+ 'react-timer-hook',
621
+ 'rc-util/lib/hooks/useMergedState.js',
622
+ '@ant-design/icons',
623
+ 'rc-picker',
624
+ '@monaco-editor/loader',
625
+ 'react-google-calendar-api',
626
+ '@apollo/client',
627
+ ],
628
+ }),
629
+ remix({
630
+ appDirectory: 'src',
631
+ // routes: routesConfig, // Removed - using routes.ts instead
632
+ future: {
633
+ unstable_optimizeDeps: true,
634
+ v3_fetcherPersist: true,
635
+ v3_relativeSplatPath: true,
636
+ v3_throwAbortReason: true,
637
+ v3_lazyRouteDiscovery: true,
638
+ v3_singleFetch: true,
639
+ v3_routeConfig: true,
640
+ },
641
+ }),
642
+ tsconfigPaths({ ignoreConfigErrors: true }),
643
+ ],
644
+ optimizeDeps: {
645
+ include: [
646
+ '@radix-ui/react-slot',
647
+ '@radix-ui/react-compose-refs',
648
+ '@radix-ui/react-primitive',
649
+ '@radix-ui/react-collection',
650
+ '@radix-ui/react-dialog',
651
+ '@radix-ui/react-select',
652
+ '@radix-ui/react-alert-dialog',
653
+ '@radix-ui/react-popover',
654
+ '@radix-ui/react-tooltip',
655
+ '@radix-ui/react-context-menu',
656
+ ],
657
+ esbuildOptions: {
658
+ target: 'esnext',
659
+ },
660
+ force: true, // Force dependency optimization on every build
661
+ },
662
+ build: {
663
+ target: 'esnext',
664
+ rollupOptions: {
665
+ output: {
666
+ // Ensure that worker files are properly bundled
667
+ format: 'es',
668
+ },
669
+ },
670
+ },
671
+ resolve: {
672
+ alias: {
673
+ '@app': resolve(directoryName, 'app'),
674
+ '@src': resolve(directoryName, 'src'),
675
+ },
676
+ },
677
+ worker: {
678
+ format: 'es', // Use ES modules format for workers
679
+ plugins: () => [], // Return an empty array of plugins
680
+ },
681
+ };
682
+
683
+ // Deep merge custom Vite config from config.json
684
+ // to merge Arrays properly need to concat.
685
+ const result = mergeWith(config.viteConfig, viteConfig, (objValue, srcValue) => {
686
+ if (Array.isArray(objValue)) {
687
+ return objValue.concat(srcValue);
688
+ }
689
+ });
690
+ return result as UserConfig;
691
+ });
692
+ ```
693
+
694
+ ### `src/routes.ts`
695
+
696
+ ```typescript
697
+ import { type RouteConfig } from '@remix-run/route-config';
698
+ import { remixRoutesOptionAdapter } from '@remix-run/routes-option-adapter';
699
+ import { dirname, resolve } from 'path';
700
+ import { fileURLToPath } from 'url';
701
+ import { defineRoutesConfig } from '@common-stack/rollup-vite-utils/lib/vite-wrappers/json-wrappers.js';
702
+ import { performCopyOperations } from '@common-stack/rollup-vite-utils/lib/preStartup/configLoader/configLoader.js';
703
+ import config from '../app/cde-webconfig.json' with { type: 'json' };
704
+
705
+ const directoryName = dirname(fileURLToPath(import.meta.url));
706
+
707
+ export default remixRoutesOptionAdapter(async (defineRoutes) => {
708
+ if (process.env.NODE_ENV === 'production') {
709
+ await performCopyOperations(config);
710
+ }
711
+ let metaJson = null;
712
+ try {
713
+ metaJson = await import('../app/sync-meta.json');
714
+ } catch {
715
+ console.warn('No sync-meta.json found, continuing without metadata.');
716
+ }
717
+ return defineRoutes((routeFn) => {
718
+ defineRoutesConfig(
719
+ routeFn,
720
+ {
721
+ routesFileName: 'routes.json',
722
+ packages: config.modules,
723
+ paths: config.paths,
724
+ iconsRepository: config?.iconsRepository,
725
+ rootPath: resolve(directoryName, '../../..'),
726
+ settings: {
727
+ _useFutureCommonPackage: true,
728
+ },
729
+ },
730
+ metaJson,
731
+ );
732
+ });
733
+ }) satisfies RouteConfig;
734
+ ```
735
+
736
+ ### `src/entry.client.tsx`
737
+
738
+ ```tsx
739
+ /**
740
+ * By default, Remix will handle hydrating your app on the client for you.
741
+ * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
742
+ * For more information, see https://remix.run/file-conventions/entry.client
743
+ */
744
+ import * as React from 'react';
745
+ import 'reflect-metadata';
746
+ import { RemixBrowser } from '@remix-run/react';
747
+ import { startTransition, StrictMode } from 'react';
748
+ import { hydrateRoot } from 'react-dom/client';
749
+ import { ApolloProvider } from '@apollo/client/index.js';
750
+ import { SlotFillProvider, removeUniversalPortals } from '@common-stack/components-pro';
751
+ import { InversifyProvider } from '@common-stack/client-react';
752
+ import { Provider as ReduxProvider } from 'react-redux';
753
+ import i18next from 'i18next';
754
+ import { I18nextProvider, initReactI18next } from 'react-i18next';
755
+ import LanguageDetector from 'i18next-browser-languagedetector';
756
+ import Backend from 'i18next-http-backend';
757
+ // @ts-ignore
758
+ import { getInitialNamespaces } from 'remix-i18next/client';
759
+ // @ts-ignore
760
+ import { createReduxStore } from '@app/frontend-stack-react/config/redux-config.js';
761
+ // @ts-ignore
762
+ import { createClientContainer } from '@app/frontend-stack-react/config/client.service';
763
+ // @ts-ignore
764
+ import clientModules from '@app/frontend-stack-react/modules.js';
765
+ // @ts-ignore
766
+ import config from '@app/cde-webconfig.json';
767
+
768
+ const { apolloClient: client, container, serviceFunc } = createClientContainer();
769
+ const { store } = createReduxStore(client, serviceFunc(), container);
770
+
771
+ (window as any).__remixStore = store;
772
+ removeUniversalPortals((window as any).__SLOT_FILLS__ || []);
773
+
774
+ async function hydrate() {
775
+ if (!i18next.isInitialized && config.i18n.enabled) {
776
+ await i18next
777
+ .use(initReactI18next)
778
+ .use(LanguageDetector)
779
+ .use(Backend)
780
+ .init({
781
+ fallbackLng: config.i18n.fallbackLng,
782
+ defaultNS: config.i18n.defaultNS,
783
+ react: config.i18n.react,
784
+ supportedLngs: config.i18n.supportedLngs,
785
+ backend: config.i18n.backend,
786
+ ns: getInitialNamespaces(),
787
+ detection: {
788
+ order: ['htmlTag'],
789
+ caches: [],
790
+ },
791
+ });
792
+ }
793
+ startTransition(() => {
794
+ hydrateRoot(
795
+ document,
796
+ <I18nextProvider i18n={i18next}>
797
+ <ReduxProvider store={store}>
798
+ <SlotFillProvider>
799
+ <InversifyProvider container={container} modules={clientModules}>
800
+ <ApolloProvider client={client}>
801
+ <RemixBrowser />
802
+ </ApolloProvider>
803
+ </InversifyProvider>
804
+ </SlotFillProvider>
805
+ </ReduxProvider>
806
+ </I18nextProvider>,
807
+ );
808
+ });
809
+ }
810
+
811
+ if (window.requestIdleCallback) {
812
+ window.requestIdleCallback(hydrate);
813
+ } else {
814
+ // Safari doesn't support requestIdleCallback
815
+ // https://caniuse.com/requestidlecallback
816
+ window.setTimeout(hydrate, 1);
817
+ }
818
+ ```
819
+
820
+ ### `src/entry.server.tsx`
821
+
822
+ ```tsx
823
+ /**
824
+ * By default, Remix will handle generating the HTTP Response for you.
825
+ * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
826
+ * For more information, see https://remix.run/file-conventions/entry.server
827
+ */
828
+ import * as React from 'react';
829
+ import 'reflect-metadata';
830
+ (global as any).__CLIENT__ = false;
831
+ (global as any).__SERVER__ = true;
832
+ import { PassThrough, Transform } from 'node:stream';
833
+ import type { EntryContext } from '@remix-run/node';
834
+ import { createReadableStreamFromReadable } from '@remix-run/node';
835
+ import { RemixServer } from '@remix-run/react';
836
+ import { isbot } from 'isbot';
837
+ import { ApolloProvider } from '@apollo/client/index.js';
838
+ import { SlotFillProvider } from '@common-stack/components-pro';
839
+ import { InversifyProvider } from '@common-stack/client-react';
840
+ import { renderToPipeableStream } from 'react-dom/server';
841
+ import { Provider as ReduxProvider } from 'react-redux';
842
+ import { LOCATION_CHANGE } from '@common-stack/remix-router-redux';
843
+ import serialize from 'serialize-javascript';
844
+ import { createInstance } from 'i18next';
845
+ import { I18nextProvider, initReactI18next } from 'react-i18next';
846
+ import Backend from 'i18next-fs-backend';
847
+ import { resolve } from 'node:path';
848
+ // @ts-ignore
849
+ import { i18nextInstance as i18next } from '@app/frontend-stack-react/i18n-localization/i18next.server.js';
850
+ import config from '@app/cde-webconfig.json';
851
+ // @ts-ignore
852
+ import type { IAppLoadContext } from '@common-stack/client-core';
853
+
854
+ // Reject/cancel all pending promises after 5 seconds
855
+ export const streamTimeout = 5000;
856
+
857
+ class ConstantsTransform extends Transform {
858
+ _fills: string[];
859
+ _apolloState: any;
860
+ _reduxState: any;
861
+ _styleSheet: string;
862
+
863
+ constructor(fills: string[], apolloState: any, reduxState: any, styleSheet: any) {
864
+ super();
865
+ this._fills = fills;
866
+ this._apolloState = apolloState;
867
+ this._reduxState = reduxState;
868
+ this._styleSheet = styleSheet;
869
+ }
870
+
871
+ _transform(chunk, encoding, callback) {
872
+ let transformedChunk = chunk.toString();
873
+
874
+ if (transformedChunk.includes('[__APOLLO_STATE__]')) {
875
+ transformedChunk = transformedChunk.replace(
876
+ '[__APOLLO_STATE__]',
877
+ serialize(this._apolloState, { isJSON: true }),
878
+ );
879
+ }
880
+ if (transformedChunk.includes('[__PRELOADED_STATE__]')) {
881
+ transformedChunk = transformedChunk.replace(
882
+ '[__PRELOADED_STATE__]',
883
+ serialize(this._reduxState, { isJSON: true }),
884
+ );
885
+ }
886
+ if (transformedChunk.includes('[__SLOT_FILLS__]')) {
887
+ transformedChunk = transformedChunk.replace('[__SLOT_FILLS__]', serialize(this._fills, { isJSON: true }));
888
+ }
889
+ if (transformedChunk.includes('[__STYLESHEET__]')) {
890
+ transformedChunk = transformedChunk.replace('[__STYLESHEET__]', this._styleSheet);
891
+ }
892
+
893
+ callback(null, transformedChunk);
894
+ }
895
+ }
896
+
897
+ export default async function handleRequest(
898
+ request: Request,
899
+ responseStatusCode: number,
900
+ responseHeaders: Headers,
901
+ remixContext: EntryContext,
902
+ // This is ignored so we can keep it in the template for visibility. Feel
903
+ // free to delete this parameter in your app if you're not using it!
904
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
905
+ loadContext: IAppLoadContext,
906
+ ) {
907
+ const instance = createInstance();
908
+ const lng = await i18next.getLocale(request);
909
+ const ns = i18next.getRouteNamespaces(remixContext);
910
+
911
+ // First, we create a new instance of i18next so every request will have a
912
+ // completely unique instance and not share any state.
913
+ if (config.i18n.enabled) {
914
+ await instance
915
+ .use(initReactI18next) // Tell our instance to use react-i18next
916
+ .use(Backend) // Setup our backend.init({
917
+ .init({
918
+ fallbackLng: config.i18n.fallbackLng,
919
+ defaultNS: config.i18n.defaultNS,
920
+ react: config.i18n.react,
921
+ supportedLngs: config.i18n.supportedLngs,
922
+ lng, // The locale we detected above
923
+ ns, // The namespaces the routes about to render want to use
924
+ backend: {
925
+ loadPath: resolve(config.i18n.backend.loadServerPath),
926
+ },
927
+ });
928
+ }
929
+
930
+ return isbot(request.headers.get('user-agent') || '')
931
+ ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext, loadContext, instance)
932
+ : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext, loadContext, instance);
933
+ }
934
+
935
+ function handleBotRequest(
936
+ request: Request,
937
+ responseStatusCode: number,
938
+ responseHeaders: Headers,
939
+ remixContext: EntryContext,
940
+ loadContext: IAppLoadContext,
941
+ i18nInstance: i18next,
942
+ ) {
943
+ return new Promise((resolve, reject) => {
944
+ let shellRendered = false;
945
+ const { pipe, abort } = renderToPipeableStream(
946
+ <I18nextProvider i18n={i18nInstance}>
947
+ <RemixServer context={remixContext} url={request.url} />
948
+ </I18nextProvider>,
949
+ {
950
+ onAllReady() {
951
+ shellRendered = true;
952
+ const body = new PassThrough();
953
+ const stream = createReadableStreamFromReadable(body);
954
+
955
+ responseHeaders.set('Content-Type', 'text/html');
956
+
957
+ resolve(
958
+ new Response(stream, {
959
+ headers: responseHeaders,
960
+ status: responseStatusCode,
961
+ }),
962
+ );
963
+
964
+ pipe(body);
965
+ },
966
+ onShellError(error: unknown) {
967
+ reject(error);
968
+ },
969
+ onError(error: unknown) {
970
+ responseStatusCode = 500;
971
+ // Log streaming rendering errors from inside the shell. Don't log
972
+ // errors encountered during initial shell rendering since they'll
973
+ // reject and get logged in handleDocumentRequest.
974
+ if (shellRendered) {
975
+ console.error(error);
976
+ }
977
+ },
978
+ },
979
+ );
980
+
981
+ setTimeout(abort, streamTimeout + 1000);
982
+ });
983
+ }
984
+
985
+ function handleBrowserRequest(
986
+ request: Request,
987
+ responseStatusCode: number,
988
+ responseHeaders: Headers,
989
+ remixContext: EntryContext,
990
+ loadContext: IAppLoadContext,
991
+ i18nInstance: i18next,
992
+ ) {
993
+ return new Promise((resolve, reject) => {
994
+ let shellRendered = false;
995
+ const slotFillContext = { fills: {} };
996
+ const { modules: clientModules, container, apolloClient: client, store } = loadContext;
997
+
998
+ const { pathname, search, hash } = new URL(request.url);
999
+ store.dispatch({
1000
+ type: LOCATION_CHANGE,
1001
+ payload: { location: { pathname, search, hash }, action: 'POP' },
1002
+ });
1003
+
1004
+ const { pipe, abort } = renderToPipeableStream(
1005
+ (
1006
+ <I18nextProvider i18n={i18nInstance}>
1007
+ <ReduxProvider store={store}>
1008
+ <SlotFillProvider context={slotFillContext}>
1009
+ <InversifyProvider container={container} modules={clientModules as any}>
1010
+ <ApolloProvider client={client}>
1011
+ <RemixServer context={remixContext} url={request.url} />
1012
+ </ApolloProvider>
1013
+ </InversifyProvider>
1014
+ </SlotFillProvider>
1015
+ </ReduxProvider>
1016
+ </I18nextProvider>
1017
+ ) as any,
1018
+ {
1019
+ onShellReady() {
1020
+ shellRendered = true;
1021
+ const body = new PassThrough();
1022
+ const stream = createReadableStreamFromReadable(body);
1023
+ const apolloState = { ...client.extract() };
1024
+ const reduxState = { ...store.getState() };
1025
+ const fills = Object.keys(slotFillContext.fills);
1026
+ const styleSheet = '';
1027
+
1028
+ const transform = new ConstantsTransform(fills, apolloState, reduxState, styleSheet);
1029
+
1030
+ responseHeaders.set('Content-Type', 'text/html');
1031
+
1032
+ resolve(
1033
+ new Response(stream, {
1034
+ headers: responseHeaders,
1035
+ status: responseStatusCode,
1036
+ }),
1037
+ );
1038
+
1039
+ pipe(transform).pipe(body);
1040
+ },
1041
+ onShellError(error: unknown) {
1042
+ reject(error);
1043
+ },
1044
+ onError(error: unknown) {
1045
+ responseStatusCode = 500;
1046
+ // Log streaming rendering errors from inside the shell. Don't log
1047
+ // errors encountered during initial shell rendering since they'll
1048
+ // reject and get logged in handleDocumentRequest.
1049
+ if (shellRendered) {
1050
+ console.error(error);
1051
+ }
1052
+ reject(error);
1053
+ },
1054
+ },
1055
+ );
1056
+
1057
+ setTimeout(abort, streamTimeout + 1000);
1058
+ });
1059
+ }
1060
+ ```
1061
+
1062
+ ### `src/root.tsx`
1063
+
1064
+ ```tsx
1065
+ import 'reflect-metadata';
1066
+ import * as React from 'react';
1067
+ import {
1068
+ Links,
1069
+ Meta,
1070
+ Outlet,
1071
+ Scripts,
1072
+ ScrollRestoration,
1073
+ useLoaderData,
1074
+ useRouteError,
1075
+ useRouteLoaderData,
1076
+ data,
1077
+ } from '@remix-run/react';
1078
+ // @ts-ignore
1079
+ import publicEnv from '@src/config/public-config';
1080
+ import { PluginArea } from '@common-stack/client-react';
1081
+ import { subscribeReduxRouter } from '@common-stack/remix-router-redux';
1082
+ import { ApplicationErrorHandler, RemixErrorBoundary as ErrorBoundary } from '@admin-layout/tailwind-ui';
1083
+ // @ts-ignore
1084
+ import clientModules, { plugins } from '@app/frontend-stack-react/modules.js';
1085
+ // @ts-ignore
1086
+ import { useChangeLanguage } from 'remix-i18next/react';
1087
+ import { useTranslation } from 'react-i18next';
1088
+ // @ts-ignore
1089
+ import { i18nextInstance as i18next } from '@app/frontend-stack-react/i18n-localization/i18next.server.js';
1090
+ import { LayoutCookieProvider } from '@admin-layout/client';
1091
+ import { settingsLoaderUtil } from '@admin-layout/client/lib/components/UpdateSettings/UpdateSettings.server';
1092
+ import type { IAppLoadContext } from '@common-stack/client-core';
1093
+ import type { IResourceParams } from '@common-stack/core';
1094
+ import { FillRenderProvider, PluginsLoader } from '@common-stack/components-pro';
1095
+
1096
+ // eslint-disable-next-line import/no-unresolved
1097
+ import styles from '../tailwind.css?url';
1098
+
1099
+ export const links = () => [{ rel: 'stylesheet', href: styles }];
1100
+
1101
+ export const loader = async ({
1102
+ request,
1103
+ context,
1104
+ params,
1105
+ }: {
1106
+ request: Request;
1107
+ context: IAppLoadContext;
1108
+ params: IResourceParams;
1109
+ }) => {
1110
+ // Fetch settings with error handling - don't let settings failures break the app
1111
+ let settingsResponse: any = {};
1112
+ try {
1113
+ settingsResponse =
1114
+ (await settingsLoaderUtil({
1115
+ request,
1116
+ context,
1117
+ params,
1118
+ })) || {};
1119
+ } catch (error) {
1120
+ console.error('❌ Failed to load settings, using defaults:', error);
1121
+ // Continue without settings - the app should still work
1122
+ }
1123
+
1124
+ const [locale] = await Promise.all([i18next.getLocale(request)]);
1125
+ const loadedPlugins = await PluginsLoader(plugins, { request, context, params });
1126
+ return data(
1127
+ {
1128
+ __ENV__: publicEnv,
1129
+ locale,
1130
+ settings: settingsResponse?.settings || {},
1131
+ loadedPlugins,
1132
+ },
1133
+ {
1134
+ headers: [
1135
+ ['Cache-Control', 'max-age=300, s-maxage=600'],
1136
+ settingsResponse?.setCookie ? ['Set-Cookie', settingsResponse.setCookie] : null,
1137
+ ].filter(Boolean) as [string, string][],
1138
+ },
1139
+ );
1140
+ };
1141
+
1142
+ export const handle = {
1143
+ i18n: ['common', 'translations', 'projects'],
1144
+ };
1145
+
1146
+ export const shouldRevalidate = () => false;
1147
+
1148
+ export function Layout({ children }: { children: React.ReactNode }) {
1149
+ // useLoaderData is for happy paths with Error boundary it will fail
1150
+ // https://github.com/remix-run/remix/issues/8951#issuecomment-1973321870
1151
+ const loaderData = useRouteLoaderData<{ locale: any; __ENV__?: any }>('root');
1152
+ const locale = loaderData?.locale || 'en';
1153
+
1154
+ const { i18n } = useTranslation();
1155
+
1156
+ useChangeLanguage(locale);
1157
+
1158
+ React.useEffect(() => {
1159
+ subscribeReduxRouter({ store: (window as any).__remixStore, router: window.__remixRouter } as any);
1160
+ }, []);
1161
+
1162
+ const getConstants = () => {
1163
+ if (typeof window === 'undefined') {
1164
+ return (
1165
+ <>
1166
+ <script
1167
+ dangerouslySetInnerHTML={{
1168
+ __html: `window.__ENV__ = ${JSON.stringify((loaderData as any)?.__ENV__ || {})}`,
1169
+ }}
1170
+ />
1171
+ <script
1172
+ src="https://cdnjs.cloudflare.com/ajax/libs/reflect-metadata/0.1.13/Reflect.min.js"
1173
+ integrity="sha512-jvbPH2TH5BSZumEfOJZn9IV+5bSwwN+qG4dvthYe3KCGC3/9HmxZ4phADbt9Pfcp+XSyyfc2vGZ/RMsSUZ9tbQ=="
1174
+ crossOrigin="anonymous"
1175
+ referrerPolicy="no-referrer"
1176
+ ></script>
1177
+ <script>window.__APOLLO_STATE__=[__APOLLO_STATE__]</script>
1178
+ <script>window.__PRELOADED_STATE__=[__PRELOADED_STATE__]</script>
1179
+ <script>window.__SLOT_FILLS__=[__SLOT_FILLS__]</script>
1180
+ <script
1181
+ dangerouslySetInnerHTML={{
1182
+ __html: `if (global === undefined) { var global = window; }`,
1183
+ }}
1184
+ />
1185
+ </>
1186
+ );
1187
+ }
1188
+ return null;
1189
+ };
1190
+
1191
+ return (
1192
+ <html lang={locale} dir={i18n.dir()}>
1193
+ <head>
1194
+ <meta charSet="utf-8" />
1195
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
1196
+ {/* CRITICAL: Load Symbol.observable polyfill BEFORE any other scripts */}
1197
+ <script
1198
+ dangerouslySetInnerHTML={{
1199
+ __html: `
1200
+ (function() {
1201
+ if (typeof Symbol !== 'undefined' && typeof Symbol.for === 'function') {
1202
+ if (!Symbol.observable) {
1203
+ Symbol.observable = Symbol.for('observable');
1204
+ }
1205
+ console.log('[Symbol.observable polyfill] Loaded in head:', Symbol.observable);
1206
+ }
1207
+ })();
1208
+ `,
1209
+ }}
1210
+ />
1211
+ <Meta />
1212
+ <Links />
1213
+ {typeof window === 'undefined' ? `[__STYLESHEET__]` : ''}
1214
+ </head>
1215
+ <body>
1216
+ <PluginArea />
1217
+ <FillRenderProvider>{clientModules.getWrappedRoot(children)}</FillRenderProvider>
1218
+ <ScrollRestoration />
1219
+ <Scripts />
1220
+ {getConstants()}
1221
+ </body>
1222
+ </html>
1223
+ );
1224
+ }
1225
+
1226
+ export default function App() {
1227
+ return (
1228
+ <ApplicationErrorHandler plugins={plugins}>
1229
+ <LayoutCookieProvider>
1230
+ <Outlet />
1231
+ </LayoutCookieProvider>
1232
+ </ApplicationErrorHandler>
1233
+ );
1234
+ }
1235
+
1236
+ export { ErrorBoundary };
1237
+ ```
1238
+
1239
+ ---
1240
+
1241
+ **Upgrade Date**: November 2025
1242
+ **Remix Version**: 2.15.3
1243
+ **Branch**: `feat/remix-2.15.3`
1244
+ **Commit**: `690f644d3f112b1c52b709fbc2d77e5181a1e75c`
1245
+ **Status**: ✅ Complete