@bleedingdev/modern-js-create 3.2.0-ultramodern.52 → 3.2.0-ultramodern.53

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 (2) hide show
  1. package/dist/index.js +453 -857
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -1436,6 +1436,8 @@ import { ultramodernLocalisedUrls } from './src/routes/ultramodern-route-metadat
1436
1436
  type ZephyrRspackConfig = Parameters<ReturnType<typeof withZephyrRspack>>[0];
1437
1437
 
1438
1438
  const zephyrEnabled = process.env['ULTRAMODERN_ZEPHYR'] !== 'false';
1439
+ const cloudflareDeployEnabled =
1440
+ process.env['MODERNJS_DEPLOY'] === 'cloudflare';
1439
1441
 
1440
1442
  const zephyrRspackPlugin = () => ({
1441
1443
  name: 'ultramodern-zephyr-rspack-plugin',
@@ -1526,13 +1528,17 @@ ${bffPluginEntry} moduleFederationPlugin(),
1526
1528
  ]);
1527
1529
  },
1528
1530
  },
1529
- deploy: {
1530
- target: 'cloudflare',
1531
- worker: {
1532
- name: cloudflareWorkerName,
1533
- ssr: true,
1534
- },
1535
- },
1531
+ ...(cloudflareDeployEnabled
1532
+ ? {
1533
+ deploy: {
1534
+ target: 'cloudflare',
1535
+ worker: {
1536
+ name: cloudflareWorkerName,
1537
+ ssr: true,
1538
+ },
1539
+ },
1540
+ }
1541
+ : {}),
1536
1542
  server: {
1537
1543
  port,
1538
1544
  publicDir: './locales',
@@ -1983,6 +1989,10 @@ function createAppEnvDts(app, remotes = remoteApps) {
1983
1989
  return `/// <reference types='@modern-js/app-tools/types' />
1984
1990
 
1985
1991
  declare const ULTRAMODERN_SITE_URL: string;
1992
+ declare module '*.svg' {
1993
+ const url: string;
1994
+ export default url;
1995
+ }
1986
1996
  ${remoteModuleDeclarations ? `\n${remoteModuleDeclarations}` : ''}`;
1987
1997
  }
1988
1998
  function createServiceModernConfigFor(service = effectService) {
@@ -2066,522 +2076,13 @@ function createCssTokenImport(scope) {
2066
2076
  return `@import '${ultramodern_workspace_packageName(scope, 'shared-design-tokens')}/tokens.css';\n`;
2067
2077
  }
2068
2078
  function createShellStyles(enableTailwind, scope) {
2069
- return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2070
-
2071
- @layer ultramodern-shell-base {
2072
- :root {
2073
- color: var(--um-color-foreground);
2074
- background: var(--um-color-canvas);
2075
- font-family:
2076
- Geist,
2077
- Inter,
2078
- ui-sans-serif,
2079
- system-ui,
2080
- -apple-system,
2081
- BlinkMacSystemFont,
2082
- "Segoe UI",
2083
- sans-serif;
2084
- }
2085
-
2086
- body {
2087
- margin: 0;
2079
+ return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}`;
2088
2080
  }
2089
-
2090
- main {
2091
- min-height: 100vh;
2092
- padding: 2rem;
2093
- }
2094
-
2095
- nav {
2096
- display: flex;
2097
- gap: 0.75rem;
2098
- margin-bottom: 2rem;
2099
- }
2100
-
2101
- a {
2102
- color: var(--um-color-link);
2103
- }
2104
-
2105
- .commerce-shell {
2106
- background: #f1eadc;
2107
- color: #0b0a08;
2108
- min-height: 100vh;
2109
- padding: 1.5rem clamp(1rem, 4vw, 3rem) 4rem;
2110
- }
2111
-
2112
- .commerce-shell-actions {
2113
- align-items: center;
2114
- display: flex;
2115
- flex-wrap: wrap;
2116
- gap: 0.75rem;
2117
- justify-content: flex-end;
2118
- margin: -4.25rem auto 3rem;
2119
- max-width: 88rem;
2120
- }
2121
-
2122
- .commerce-language {
2123
- margin: 0;
2124
- }
2125
-
2126
- .commerce-page {
2127
- margin: 3rem auto 0;
2128
- max-width: 88rem;
2129
- }
2130
-
2131
- .commerce-hero {
2132
- padding: 4rem 0 2rem;
2133
- }
2134
-
2135
- .commerce-eyebrow {
2136
- color: #00624b;
2137
- font-size: 0.85rem;
2138
- font-weight: 850;
2139
- letter-spacing: 0.16rem;
2140
- text-transform: uppercase;
2141
- }
2142
-
2143
- .commerce-title {
2144
- font-size: clamp(2.5rem, 6vw, 4.8rem);
2145
- line-height: 0.95;
2146
- margin: 0.65rem 0 1.4rem;
2147
- max-width: 58rem;
2148
- }
2149
-
2150
- .commerce-lede {
2151
- color: #555149;
2152
- font-size: 1.2rem;
2153
- line-height: 1.65;
2154
- max-width: 42rem;
2155
- }
2156
-
2157
- .commerce-checkout {
2158
- align-items: center;
2159
- display: flex;
2160
- flex-wrap: wrap;
2161
- gap: 0.75rem;
2162
- margin-top: 1.5rem;
2163
- }
2164
-
2165
- .commerce-pill,
2166
- .commerce-button,
2167
- .commerce-link-button,
2168
- .commerce-cart-button {
2169
- align-items: center;
2170
- border-radius: 999px;
2171
- border: 0.0625rem solid rgba(23, 23, 23, 0.14);
2172
- box-shadow: 0 0.25rem 0.75rem rgba(20, 17, 10, 0.08);
2173
- color: #14120d;
2174
- display: inline-flex;
2175
- font: inherit;
2176
- font-weight: 750;
2177
- justify-content: center;
2178
- min-height: 2.5rem;
2179
- padding: 0.65rem 1.05rem;
2180
- text-decoration: none;
2181
- }
2182
-
2183
- .commerce-button {
2184
- background: #00624b;
2185
- border-color: #00624b;
2186
- color: #ffffff;
2187
- }
2188
-
2189
- .commerce-link-button,
2190
- .commerce-pill,
2191
- .commerce-cart-button {
2192
- background: rgba(255, 255, 255, 0.92);
2193
- }
2194
-
2195
- .commerce-boundary-toggle {
2196
- align-items: center;
2197
- background: rgba(255, 255, 255, 0.94);
2198
- border: 0.0625rem solid rgba(23, 23, 23, 0.12);
2199
- border-radius: 0.8rem;
2200
- bottom: 1.5rem;
2201
- box-shadow: 0 0.75rem 2rem rgba(18, 15, 10, 0.14);
2202
- color: #14120d;
2203
- display: flex;
2204
- gap: 0.65rem;
2205
- left: 1.5rem;
2206
- padding: 0.8rem 1rem;
2207
- position: fixed;
2208
- z-index: 80;
2209
- }
2210
-
2211
- .commerce-boundary-toggle input {
2212
- accent-color: #00624b;
2213
- height: 1rem;
2214
- width: 1rem;
2215
- }
2216
-
2217
- @media (max-width: 860px) {
2218
- .commerce-shell-actions {
2219
- justify-content: flex-start;
2220
- margin-top: 1rem;
2221
- }
2222
- }
2223
- }
2224
-
2225
- @layer ultramodern-shell-overlay {
2226
- .boundary-overlay {
2227
- inset: 0;
2228
- pointer-events: none;
2229
- position: fixed;
2230
- z-index: 70;
2081
+ function createRemoteStyles(enableTailwind, scope, _app) {
2082
+ return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}`;
2231
2083
  }
2232
-
2233
- .boundary-overlay__box {
2234
- border: 0.0625rem solid var(--boundary-color);
2235
- border-radius: 0.55rem;
2236
- box-shadow:
2237
- 0 0 0 0.0625rem rgba(255, 255, 255, 0.72),
2238
- 0 0.35rem 1.25rem color-mix(in srgb, var(--boundary-color) 20%, transparent);
2239
- position: fixed;
2240
- }
2241
-
2242
- .boundary-overlay__label {
2243
- background: color-mix(in srgb, var(--boundary-color) 88%, white);
2244
- border-radius: 999px;
2245
- color: #0b0a08;
2246
- font-size: 0.7rem;
2247
- font-weight: 850;
2248
- line-height: 1;
2249
- padding: 0.3rem 0.55rem;
2250
- position: absolute;
2251
- right: 0.35rem;
2252
- top: 0.35rem;
2253
- white-space: nowrap;
2254
- }
2255
-
2256
- .boundary-overlay__box[data-label-placement="above"] .boundary-overlay__label {
2257
- bottom: calc(100% + 0.25rem);
2258
- top: auto;
2259
- }
2260
- }
2261
- `;
2262
- }
2263
- function createRemoteStyles(enableTailwind, scope, app) {
2264
- if ([
2265
- 'explore',
2266
- 'decide',
2267
- 'checkout'
2268
- ].includes(app.domain ?? '')) return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2269
-
2270
- @layer ultramodern-remote-${app.domain} {
2271
- .commerce-shell {
2272
- background: #f1eadc;
2273
- color: #0b0a08;
2274
- min-height: 100vh;
2275
- padding: 1.5rem clamp(1rem, 4vw, 3rem) 4rem;
2276
- }
2277
-
2278
- .commerce-header,
2279
- .commerce-footer {
2280
- align-items: center;
2281
- background: rgba(255, 255, 255, 0.86);
2282
- box-shadow: 0 0.625rem 1.875rem rgba(25, 20, 12, 0.08);
2283
- display: flex;
2284
- gap: 1.25rem;
2285
- justify-content: space-between;
2286
- margin: 0 auto;
2287
- max-width: 88rem;
2288
- padding: 1.25rem 1.75rem;
2289
- }
2290
-
2291
- .commerce-logo {
2292
- font-size: 1.35rem;
2293
- font-weight: 800;
2294
- }
2295
-
2296
- .commerce-nav,
2297
- .commerce-actions,
2298
- .commerce-language {
2299
- align-items: center;
2300
- display: flex;
2301
- flex-wrap: wrap;
2302
- gap: 0.75rem;
2303
- }
2304
-
2305
- .commerce-nav {
2306
- margin: 0;
2307
- }
2308
-
2309
- .commerce-pill,
2310
- .commerce-button,
2311
- .commerce-link-button,
2312
- .commerce-cart-button,
2313
- .commerce-quantity-button {
2314
- align-items: center;
2315
- border-radius: 999px;
2316
- border: 0.0625rem solid rgba(23, 23, 23, 0.14);
2317
- box-shadow: 0 0.25rem 0.75rem rgba(20, 17, 10, 0.08);
2318
- color: #14120d;
2319
- display: inline-flex;
2320
- font: inherit;
2321
- font-weight: 750;
2322
- justify-content: center;
2323
- min-height: 2.5rem;
2324
- padding: 0.65rem 1.05rem;
2325
- text-decoration: none;
2326
- }
2327
-
2328
- .commerce-button {
2329
- background: #00624b;
2330
- border-color: #00624b;
2331
- color: #ffffff;
2332
- }
2333
-
2334
- .commerce-link-button,
2335
- .commerce-pill,
2336
- .commerce-cart-button,
2337
- .commerce-quantity-button {
2338
- background: rgba(255, 255, 255, 0.92);
2339
- }
2340
-
2341
- .commerce-page {
2342
- margin: 3rem auto 0;
2343
- max-width: 88rem;
2344
- }
2345
-
2346
- .commerce-product {
2347
- align-items: center;
2348
- display: grid;
2349
- gap: clamp(2rem, 5vw, 4rem);
2350
- grid-template-columns: minmax(0, 1fr) minmax(20rem, 0.95fr);
2351
- }
2352
-
2353
- .commerce-product-media {
2354
- aspect-ratio: 1 / 0.92;
2355
- background:
2356
- linear-gradient(180deg, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0) 42%),
2357
- linear-gradient(135deg, #97c66d 0 20%, #6f9748 20% 34%, #d6c15d 34% 36%, #6a8f3e 36% 46%, #315824 46% 64%, #8bb85e 64% 100%);
2358
- border: 1.25rem solid #ffe987;
2359
- border-radius: 1.6rem;
2360
- box-shadow: inset 0 -7rem 8rem rgba(58, 77, 35, 0.22);
2361
- overflow: hidden;
2362
- }
2363
-
2364
- .commerce-product-media::after {
2365
- background:
2366
- radial-gradient(circle at 27% 76%, #1e2422 0 5%, transparent 5.4%),
2367
- radial-gradient(circle at 55% 76%, #1e2422 0 6%, transparent 6.4%),
2368
- linear-gradient(0deg, #004b7b 0 100%);
2369
- border-radius: 1.2rem;
2370
- content: "";
2371
- display: block;
2372
- height: 19%;
2373
- margin: 58% auto 0;
2374
- width: 42%;
2375
- }
2376
-
2377
- .commerce-eyebrow {
2378
- color: #00624b;
2379
- font-size: 0.85rem;
2380
- font-weight: 850;
2381
- letter-spacing: 0.16rem;
2382
- text-transform: uppercase;
2383
- }
2384
-
2385
- .commerce-title {
2386
- font-size: clamp(2.5rem, 6vw, 4.8rem);
2387
- line-height: 0.95;
2388
- margin: 0.65rem 0 1.4rem;
2389
- }
2390
-
2391
- .commerce-lede {
2392
- color: #555149;
2393
- font-size: 1.2rem;
2394
- line-height: 1.65;
2395
- max-width: 42rem;
2396
- }
2397
-
2398
- .commerce-facts {
2399
- display: grid;
2400
- gap: 1rem;
2401
- grid-template-columns: repeat(3, minmax(0, 1fr));
2402
- margin: 2rem 0;
2403
- }
2404
-
2405
- .commerce-fact,
2406
- .commerce-card,
2407
- .commerce-cart-panel {
2408
- background: rgba(255, 255, 255, 0.92);
2409
- border-radius: 1rem;
2410
- box-shadow: 0 0.5rem 1.25rem rgba(25, 20, 12, 0.08);
2411
- padding: 1.25rem;
2412
- }
2413
-
2414
- .commerce-fact span,
2415
- .commerce-card span {
2416
- color: #767067;
2417
- display: block;
2418
- font-weight: 750;
2419
- margin-bottom: 0.45rem;
2420
- }
2421
-
2422
- .commerce-fact strong {
2423
- font-size: 1.1rem;
2424
- }
2425
-
2426
- .commerce-checkout {
2427
- align-items: center;
2428
- display: flex;
2429
- flex-wrap: wrap;
2430
- gap: 0.75rem;
2431
- }
2432
-
2433
- .commerce-section-title {
2434
- font-size: 1.8rem;
2435
- margin: 4.5rem 0 1.5rem;
2436
- }
2437
-
2438
- .commerce-grid {
2439
- display: grid;
2440
- gap: 1rem;
2441
- grid-template-columns: repeat(2, minmax(0, 1fr));
2442
- }
2443
-
2444
- .commerce-card strong {
2445
- display: block;
2446
- font-size: 1.45rem;
2447
- }
2448
-
2449
- .commerce-cart-panel {
2450
- margin-top: 2rem;
2451
- }
2452
-
2453
- .commerce-cart-line {
2454
- align-items: center;
2455
- border-top: 0.0625rem solid rgba(23, 23, 23, 0.12);
2456
- display: grid;
2457
- gap: 1rem;
2458
- grid-template-columns: minmax(0, 1fr) auto;
2459
- padding: 1rem 0;
2460
- }
2461
-
2462
- .commerce-cart-line:first-of-type {
2463
- border-top: 0;
2464
- }
2465
-
2466
- .commerce-quantity {
2467
- align-items: center;
2468
- display: flex;
2469
- gap: 0.45rem;
2470
- }
2471
-
2472
- .commerce-quantity-button {
2473
- min-height: 2rem;
2474
- min-width: 2rem;
2475
- padding: 0.25rem;
2476
- }
2477
-
2478
- .commerce-boundary-toggle {
2479
- align-items: center;
2480
- background: rgba(255, 255, 255, 0.92);
2481
- border-radius: 0.8rem;
2482
- bottom: 1.5rem;
2483
- box-shadow: 0 0.75rem 2rem rgba(18, 15, 10, 0.14);
2484
- display: flex;
2485
- gap: 0.65rem;
2486
- left: 1.5rem;
2487
- padding: 0.8rem 1rem;
2488
- position: fixed;
2489
- z-index: 80;
2490
- }
2491
-
2492
- .commerce-boundary-toggle input {
2493
- accent-color: #00624b;
2494
- height: 1rem;
2495
- width: 1rem;
2496
- }
2497
-
2498
- @media (max-width: 860px) {
2499
- .commerce-header,
2500
- .commerce-footer,
2501
- .commerce-product,
2502
- .commerce-grid,
2503
- .commerce-facts {
2504
- grid-template-columns: 1fr;
2505
- }
2506
-
2507
- .commerce-header,
2508
- .commerce-footer {
2509
- align-items: flex-start;
2510
- flex-direction: column;
2511
- }
2512
-
2513
- .commerce-product-media {
2514
- min-height: 20rem;
2515
- }
2516
- }
2517
- }
2518
- `;
2519
- return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2520
-
2521
- @layer ultramodern-remote-${app.domain ?? app.id} {
2522
- [data-app-id="${app.id}"] {
2523
- color: var(--um-color-foreground);
2524
- background: var(--um-color-surface);
2525
- font-family:
2526
- Geist,
2527
- Inter,
2528
- ui-sans-serif,
2529
- system-ui,
2530
- -apple-system,
2531
- BlinkMacSystemFont,
2532
- "Segoe UI",
2533
- sans-serif;
2534
- min-height: 100vh;
2535
- }
2536
-
2537
- [data-app-id="${app.id}"] main {
2538
- min-height: 100vh;
2539
- padding: 2rem;
2540
- }
2541
-
2542
- [data-app-id="${app.id}"] nav {
2543
- display: flex;
2544
- gap: 0.75rem;
2545
- margin-bottom: 2rem;
2546
- }
2547
-
2548
- [data-app-id="${app.id}"] a {
2549
- color: var(--um-color-link);
2550
- }
2551
-
2552
- [data-mf-remote="${app.id}"] {
2553
- border: 0.0625rem solid color-mix(in srgb, var(--um-color-accent) 30%, transparent);
2554
- border-radius: 0.5rem;
2555
- padding: 1rem;
2556
- }
2557
- }
2558
- `;
2559
- }
2560
- function createServiceStyles(enableTailwind, scope, service) {
2561
- return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}
2562
-
2563
- @layer ultramodern-effect-service {
2564
- [data-app-id="${service.id}"] {
2565
- color: var(--um-color-foreground);
2566
- background: var(--um-color-surface);
2567
- font-family:
2568
- Geist,
2569
- Inter,
2570
- ui-sans-serif,
2571
- system-ui,
2572
- -apple-system,
2573
- BlinkMacSystemFont,
2574
- "Segoe UI",
2575
- sans-serif;
2576
- min-height: 100vh;
2577
- }
2578
-
2579
- [data-app-id="${service.id}"] main {
2580
- min-height: 100vh;
2581
- padding: 2rem;
2582
- }
2583
- }
2584
- `;
2084
+ function createServiceStyles(enableTailwind, scope, _service) {
2085
+ return `${enableTailwind ? "@import 'tailwindcss';\n" : ''}${createCssTokenImport(scope)}`;
2585
2086
  }
2586
2087
  function createAppStyles(enableTailwind, scope, app) {
2587
2088
  return 'shell' === app.kind ? createShellStyles(enableTailwind, scope) : createRemoteStyles(enableTailwind, scope, app);
@@ -2602,6 +2103,86 @@ export default {
2602
2103
  } satisfies Config;
2603
2104
  `;
2604
2105
  }
2106
+ function createCommerceAssetSvg(title, palette) {
2107
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" role="img" aria-label="${title}">
2108
+ <defs>
2109
+ <linearGradient id="sky" x1="0" x2="0" y1="0" y2="1">
2110
+ <stop offset="0" stop-color="${palette.sky}"/>
2111
+ <stop offset="1" stop-color="#fff8dc"/>
2112
+ </linearGradient>
2113
+ <linearGradient id="field" x1="0" x2="1" y1="0" y2="1">
2114
+ <stop offset="0" stop-color="${palette.ground}"/>
2115
+ <stop offset="1" stop-color="${palette.accent}"/>
2116
+ </linearGradient>
2117
+ </defs>
2118
+ <rect width="1440" height="900" fill="url(#sky)"/>
2119
+ <path d="M0 566c172-78 330-102 474-72 125 26 219 91 340 106 170 21 339-74 626-43v343H0z" fill="url(#field)"/>
2120
+ <path d="M0 686c205-70 451-66 738 12 287 77 521 66 702-33v235H0z" fill="#4f7f38" opacity=".55"/>
2121
+ <g fill="none" stroke="#fff6b7" stroke-linecap="round" stroke-width="10" opacity=".55">
2122
+ <path d="M108 820c205-138 382-202 530-192"/>
2123
+ <path d="M322 862c176-134 338-198 486-193"/>
2124
+ <path d="M583 886c119-121 260-190 422-207"/>
2125
+ <path d="M868 878c95-94 207-153 336-176"/>
2126
+ </g>
2127
+ <g transform="translate(430 430)">
2128
+ <circle cx="170" cy="210" r="92" fill="#161616"/>
2129
+ <circle cx="170" cy="210" r="54" fill="#d7c46d"/>
2130
+ <circle cx="514" cy="214" r="108" fill="#161616"/>
2131
+ <circle cx="514" cy="214" r="63" fill="#d7c46d"/>
2132
+ <path d="M194 142h194l72-100h114c49 0 89 39 89 88v57H625l-51-90H452l-78 114H209z" fill="${palette.tractor}"/>
2133
+ <path d="M283 67h134l-54 73H249z" fill="#c9ecff" opacity=".72"/>
2134
+ <path d="M120 184h430v54H120z" fill="${palette.tractor}"/>
2135
+ <path d="M578 52l60-35M618 37l34 72" stroke="#171717" stroke-linecap="round" stroke-width="14"/>
2136
+ <path d="M90 236h578" stroke="#171717" stroke-linecap="round" stroke-width="18"/>
2137
+ </g>
2138
+ </svg>
2139
+ `;
2140
+ }
2141
+ function commerceAssetsForApp(app) {
2142
+ if ('shell' === app.kind) return {
2143
+ 'src/assets/hero-field.svg': createCommerceAssetSvg('Tractor crossing cultivated fields', {
2144
+ accent: '#d6b85d',
2145
+ ground: '#84ad58',
2146
+ sky: '#9fd6e8',
2147
+ tractor: '#005f73'
2148
+ })
2149
+ };
2150
+ if ('remote-explore' === app.id) return {
2151
+ 'src/assets/autonomy.svg': createCommerceAssetSvg('Autonomous tractor concept', {
2152
+ accent: '#c26a2e',
2153
+ ground: '#668f55',
2154
+ sky: '#d5e7de',
2155
+ tractor: '#f2a51a'
2156
+ }),
2157
+ 'src/assets/field-loader.svg': createCommerceAssetSvg('Field Loader 112 tractor', {
2158
+ accent: '#d6b85d',
2159
+ ground: '#84ad58',
2160
+ sky: '#9fd6e8',
2161
+ tractor: '#00624b'
2162
+ }),
2163
+ 'src/assets/orchard.svg': createCommerceAssetSvg('Orchard tractor between tight rows', {
2164
+ accent: '#b45b2d',
2165
+ ground: '#6f9b4a',
2166
+ sky: '#c9ebff',
2167
+ tractor: '#1d5d9b'
2168
+ }),
2169
+ 'src/assets/vineyard.svg': createCommerceAssetSvg('Vineyard narrow tractor', {
2170
+ accent: '#b88d58',
2171
+ ground: '#5e8a45',
2172
+ sky: '#f1dcb9',
2173
+ tractor: '#914d76'
2174
+ })
2175
+ };
2176
+ if ('remote-decide' === app.id) return {
2177
+ 'src/assets/field-loader.svg': createCommerceAssetSvg('Field Loader 112 tractor detail', {
2178
+ accent: '#d6b85d',
2179
+ ground: '#84ad58',
2180
+ sky: '#9fd6e8',
2181
+ tractor: '#00624b'
2182
+ })
2183
+ };
2184
+ return {};
2185
+ }
2605
2186
  function createLocalizedHeadComponent() {
2606
2187
  return `const fallbackLanguage = 'en';
2607
2188
  const supportedLanguages = ['en', 'cs'] as const;
@@ -2756,302 +2337,269 @@ function createShellPage() {
2756
2337
  return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2757
2338
  import { Helmet } from '@modern-js/runtime/head';
2758
2339
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2759
- import { useEffect, useState, type ComponentType } from 'react';
2760
- import BoundaryOverlay from '../boundary-overlay';
2340
+ import heroField from '../../assets/hero-field.svg';
2341
+ import ShellFrame from '../shell-frame';
2342
+ import { StorePicker } from '../remote-components';
2761
2343
  import { ultramodernLocalisedUrls } from '../ultramodern-route-metadata';
2762
2344
  import { ultramodernUiMarker } from '../../ultramodern-build';
2763
2345
 
2764
- const languageCodes = ['en', 'cs'] as const;
2765
-
2766
2346
  ${createLocalizedHeadComponent()}
2767
- type HomeRouteRemotes = {
2768
- Header: ComponentType;
2769
- MiniCart: ComponentType;
2770
- StorePicker: ComponentType;
2771
- };
2772
-
2773
- const useHomeRouteRemotes = () => {
2774
- const [remotes, setRemotes] = useState<HomeRouteRemotes | null>(null);
2775
-
2776
- useEffect(() => {
2777
- let mounted = true;
2778
- import('../remote-components').then(({ Header, MiniCart, StorePicker }) => {
2779
- if (mounted) {
2780
- setRemotes({ Header, MiniCart, StorePicker });
2781
- }
2782
- });
2783
-
2784
- return () => {
2785
- mounted = false;
2786
- };
2787
- }, []);
2788
-
2789
- return remotes;
2790
- };
2791
-
2792
2347
  export default function ShellHome() {
2793
2348
  const { i18nInstance, language } = useModernI18n();
2794
2349
  const t = i18nInstance['t'].bind(i18nInstance);
2795
- const location = useLocation();
2796
- const suffix = locationSuffix(location);
2797
- const remotes = useHomeRouteRemotes();
2798
- const Header = remotes?.Header;
2799
- const MiniCart = remotes?.MiniCart;
2800
- const StorePicker = remotes?.StorePicker;
2801
2350
 
2802
2351
  return (
2803
- <main className="commerce-shell">
2352
+ <ShellFrame>
2804
2353
  <LocalizedHead />
2805
- <BoundaryOverlay />
2806
- {Header ? <Header /> : null}
2807
- <div className="commerce-shell-actions">
2808
- <nav aria-label={t('shell.language.switcher')} className="commerce-language">
2809
- {languageCodes.map(code => (
2810
- <a
2811
- aria-current={language === code ? 'page' : undefined}
2812
- className="commerce-pill"
2813
- href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
2814
- key={code}
2815
- >
2816
- {t(\`shell.language.\${code}\`)}
2817
- </a>
2818
- ))}
2819
- </nav>
2820
- {MiniCart ? <MiniCart /> : null}
2821
- </div>
2822
- <section className="commerce-page commerce-hero">
2823
- <p className="commerce-eyebrow">{t('shell.hero.eyebrow')}</p>
2824
- <h1 className="commerce-title">{t('shell.title')}</h1>
2825
- <p className="commerce-lede">{t('shell.hero.lede')}</p>
2826
- <div className="commerce-checkout">
2827
- <a className="commerce-button" href={\`/\${language}/tractors/field-loader-112\`}>
2354
+ <section className="mx-auto grid max-w-7xl items-center gap-8 py-8 md:grid-cols-[0.9fr_1.1fr] lg:gap-14">
2355
+ <div className="min-w-0">
2356
+ <p className="text-xs font-black uppercase tracking-[0.18em] text-emerald-800">{t('shell.hero.eyebrow')}</p>
2357
+ <h1 className="mt-3 max-w-3xl text-5xl font-black leading-none tracking-normal text-stone-950 md:text-7xl">{t('shell.title')}</h1>
2358
+ <p className="mt-5 max-w-2xl text-lg leading-8 text-stone-600">{t('shell.hero.lede')}</p>
2359
+ <div className="mt-7 flex flex-wrap gap-3">
2360
+ <a className="inline-flex min-h-11 items-center justify-center rounded-full bg-emerald-800 px-5 font-bold text-white shadow-lg shadow-stone-900/10" href={\`/\${language}/tractors/field-loader-112\`}>
2828
2361
  {t('shell.hero.primary')}
2829
- </a>
2830
- <a className="commerce-link-button" href={\`/\${language}/tractors\`}>
2362
+ </a>
2363
+ <a className="inline-flex min-h-11 items-center justify-center rounded-full border border-stone-900/15 bg-white/90 px-5 font-bold text-stone-950 shadow-lg shadow-stone-900/10" href={\`/\${language}/tractors\`}>
2831
2364
  {t('shell.hero.secondary')}
2832
- </a>
2365
+ </a>
2366
+ </div>
2833
2367
  </div>
2368
+ <img alt="" className="aspect-[16/10] w-full rounded-3xl bg-stone-200 object-cover shadow-2xl shadow-stone-900/20" src={heroField} />
2834
2369
  </section>
2835
- {StorePicker ? <StorePicker /> : null}
2836
- <p data-testid="ultramodern-preset">presetUltramodern workspace</p>
2837
- <p data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
2370
+ <StorePicker />
2371
+ <p className="sr-only" data-testid="ultramodern-preset">presetUltramodern workspace</p>
2372
+ <p className="sr-only" data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
2838
2373
  {ultramodernUiMarker.appId}:{ultramodernUiMarker.version}
2839
2374
  </p>
2840
- </main>
2375
+ </ShellFrame>
2841
2376
  );
2842
2377
  }
2843
2378
  `;
2844
2379
  }
2845
2380
  function createShellTractorsPage() {
2846
- return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2847
- import { Helmet } from '@modern-js/runtime/head';
2381
+ return `import { Helmet } from '@modern-js/runtime/head';
2848
2382
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2849
- import { useEffect, useState, type ComponentType } from 'react';
2850
- import BoundaryOverlay from '../../boundary-overlay';
2383
+ import ShellFrame from '../../shell-frame';
2384
+ import { Recommendations } from '../../remote-components';
2851
2385
  import { ultramodernLocalisedUrls } from '../../ultramodern-route-metadata';
2852
2386
 
2853
- const languageCodes = ['en', 'cs'] as const;
2854
-
2855
2387
  ${createLocalizedHeadComponent()}
2856
- type TractorsRouteRemotes = {
2857
- Header: ComponentType;
2858
- MiniCart: ComponentType;
2859
- Recommendations: ComponentType;
2860
- };
2861
-
2862
- const useTractorsRouteRemotes = () => {
2863
- const [remotes, setRemotes] = useState<TractorsRouteRemotes | null>(null);
2864
-
2865
- useEffect(() => {
2866
- let mounted = true;
2867
- import('../../remote-components').then(({ Header, MiniCart, Recommendations }) => {
2868
- if (mounted) {
2869
- setRemotes({ Header, MiniCart, Recommendations });
2870
- }
2871
- });
2872
-
2873
- return () => {
2874
- mounted = false;
2875
- };
2876
- }, []);
2877
-
2878
- return remotes;
2879
- };
2880
-
2881
2388
  export default function ShellTractorsPage() {
2882
- const { i18nInstance, language } = useModernI18n();
2883
- const t = i18nInstance['t'].bind(i18nInstance);
2884
- const location = useLocation();
2885
- const suffix = locationSuffix(location);
2886
- const remotes = useTractorsRouteRemotes();
2887
- const Header = remotes?.Header;
2888
- const MiniCart = remotes?.MiniCart;
2889
- const Recommendations = remotes?.Recommendations;
2890
-
2891
2389
  return (
2892
- <main className="commerce-shell">
2390
+ <ShellFrame>
2893
2391
  <LocalizedHead />
2894
- <BoundaryOverlay />
2895
- {Header ? <Header /> : null}
2896
- <div className="commerce-shell-actions">
2897
- <nav aria-label={t('shell.language.switcher')} className="commerce-language">
2898
- {languageCodes.map(code => (
2899
- <a
2900
- aria-current={language === code ? 'page' : undefined}
2901
- className="commerce-pill"
2902
- href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
2903
- key={code}
2904
- >
2905
- {t(\`shell.language.\${code}\`)}
2906
- </a>
2907
- ))}
2908
- </nav>
2909
- {MiniCart ? <MiniCart /> : null}
2910
- </div>
2911
- {Recommendations ? <Recommendations /> : null}
2912
- </main>
2392
+ <Recommendations />
2393
+ </ShellFrame>
2913
2394
  );
2914
2395
  }
2915
2396
  `;
2916
2397
  }
2917
2398
  function createShellProductPage() {
2918
- return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2919
- import { Helmet } from '@modern-js/runtime/head';
2399
+ return `import { Helmet } from '@modern-js/runtime/head';
2920
2400
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2921
- import { useEffect, useState, type ComponentType } from 'react';
2922
- import BoundaryOverlay from '../../../boundary-overlay';
2401
+ import ShellFrame from '../../../shell-frame';
2402
+ import { ProductPage } from '../../../remote-components';
2923
2403
  import { ultramodernLocalisedUrls } from '../../../ultramodern-route-metadata';
2924
2404
 
2925
- const languageCodes = ['en', 'cs'] as const;
2926
-
2927
2405
  ${createLocalizedHeadComponent()}
2928
- type ProductRouteRemotes = {
2929
- Header: ComponentType;
2930
- MiniCart: ComponentType;
2931
- ProductPage: ComponentType;
2932
- };
2933
-
2934
- const useProductRouteRemotes = () => {
2935
- const [remotes, setRemotes] = useState<ProductRouteRemotes | null>(null);
2936
-
2937
- useEffect(() => {
2938
- let mounted = true;
2939
- import('../../../remote-components').then(
2940
- ({ Header, MiniCart, ProductPage }) => {
2941
- if (mounted) {
2942
- setRemotes({ Header, MiniCart, ProductPage });
2943
- }
2944
- },
2945
- );
2946
-
2947
- return () => {
2948
- mounted = false;
2949
- };
2950
- }, []);
2951
-
2952
- return remotes;
2953
- };
2954
-
2955
2406
  export default function ShellProductPage() {
2956
- const { i18nInstance, language } = useModernI18n();
2957
- const t = i18nInstance['t'].bind(i18nInstance);
2958
- const location = useLocation();
2959
- const suffix = locationSuffix(location);
2960
- const remotes = useProductRouteRemotes();
2961
- const Header = remotes?.Header;
2962
- const MiniCart = remotes?.MiniCart;
2963
- const ProductPage = remotes?.ProductPage;
2964
-
2965
2407
  return (
2966
- <main className="commerce-shell">
2408
+ <ShellFrame>
2967
2409
  <LocalizedHead />
2968
- <BoundaryOverlay />
2969
- {Header ? <Header /> : null}
2970
- <div className="commerce-shell-actions">
2971
- <nav aria-label={t('shell.language.switcher')} className="commerce-language">
2972
- {languageCodes.map(code => (
2973
- <a
2974
- aria-current={language === code ? 'page' : undefined}
2975
- className="commerce-pill"
2976
- href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
2977
- key={code}
2978
- >
2979
- {t(\`shell.language.\${code}\`)}
2980
- </a>
2981
- ))}
2982
- </nav>
2983
- {MiniCart ? <MiniCart /> : null}
2984
- </div>
2985
- {ProductPage ? <ProductPage /> : null}
2986
- </main>
2410
+ <ProductPage />
2411
+ </ShellFrame>
2987
2412
  );
2988
2413
  }
2989
2414
  `;
2990
2415
  }
2991
2416
  function createShellCartPage() {
2992
- return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2993
- import { Helmet } from '@modern-js/runtime/head';
2417
+ return `import { Helmet } from '@modern-js/runtime/head';
2994
2418
  import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2995
- import { useEffect, useState, type ComponentType } from 'react';
2996
- import BoundaryOverlay from '../../boundary-overlay';
2419
+ import ShellFrame from '../../shell-frame';
2420
+ import { CartPage } from '../../remote-components';
2997
2421
  import { ultramodernLocalisedUrls } from '../../ultramodern-route-metadata';
2998
2422
 
2999
- const languageCodes = ['en', 'cs'] as const;
3000
-
3001
2423
  ${createLocalizedHeadComponent()}
3002
- type CartRouteRemotes = {
3003
- CartPage: ComponentType;
3004
- Header: ComponentType;
2424
+ export default function ShellCartPage() {
2425
+ return (
2426
+ <ShellFrame showCart={false}>
2427
+ <LocalizedHead />
2428
+ <CartPage />
2429
+ </ShellFrame>
2430
+ );
2431
+ }
2432
+ `;
2433
+ }
2434
+ function createShellFrameComponent() {
2435
+ return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2436
+ import { useLocation } from '@modern-js/plugin-tanstack/runtime';
2437
+ import type { ReactNode } from 'react';
2438
+ import BoundaryOverlay from './boundary-overlay';
2439
+ import { Header, MiniCart } from './remote-components';
2440
+ import { ultramodernLocalisedUrls } from './ultramodern-route-metadata';
2441
+
2442
+ const supportedLanguages = ['en', 'cs'] as const;
2443
+ type SupportedLanguage = (typeof supportedLanguages)[number];
2444
+
2445
+ type ShellFrameProps = {
2446
+ children: ReactNode;
2447
+ showCart?: boolean;
3005
2448
  };
3006
2449
 
3007
- const useCartRouteRemotes = () => {
3008
- const [remotes, setRemotes] = useState<CartRouteRemotes | null>(null);
2450
+ const localisedUrls = ultramodernLocalisedUrls as Record<
2451
+ string,
2452
+ Record<SupportedLanguage, string>
2453
+ >;
2454
+
2455
+ const isSupportedLanguage = (value: string): value is SupportedLanguage =>
2456
+ supportedLanguages.includes(value as SupportedLanguage);
3009
2457
 
3010
- useEffect(() => {
3011
- let mounted = true;
3012
- import('../../remote-components').then(({ CartPage, Header }) => {
3013
- if (mounted) {
3014
- setRemotes({ CartPage, Header });
2458
+ const normalisePath = (pathname: string) => {
2459
+ const normalised = pathname.replace(/\\/+$/u, '').replace(/\\/+/gu, '/');
2460
+ return normalised.length > 0 ? normalised : '/';
2461
+ };
2462
+
2463
+ const stripLanguagePrefix = (pathname: string) => {
2464
+ const segments = normalisePath(pathname).split('/').filter(Boolean);
2465
+ if (segments.length > 0 && isSupportedLanguage(segments[0] ?? '')) {
2466
+ segments.shift();
2467
+ }
2468
+ return \`/\${segments.join('/')}\`;
2469
+ };
2470
+
2471
+ const escapeRegExp = (value: string) =>
2472
+ value.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
2473
+
2474
+ const paramName = (segment: string) => segment.slice(1).replace(/\\?$/u, '');
2475
+
2476
+ const matchPattern = (pathname: string, pattern: string) => {
2477
+ const names: string[] = [];
2478
+ const source = normalisePath(pattern)
2479
+ .split('/')
2480
+ .filter(Boolean)
2481
+ .map(segment => {
2482
+ if (segment.startsWith(':')) {
2483
+ names.push(paramName(segment));
2484
+ return segment.endsWith('?') ? '(?:/([^/]+))?' : '/([^/]+)';
3015
2485
  }
3016
- });
2486
+ return \`/\${escapeRegExp(segment)}\`;
2487
+ })
2488
+ .join('');
2489
+ const match = new RegExp(\`^\${source || '/'}$\`).exec(normalisePath(pathname));
3017
2490
 
3018
- return () => {
3019
- mounted = false;
3020
- };
3021
- }, []);
2491
+ if (!match) {
2492
+ return undefined;
2493
+ }
3022
2494
 
3023
- return remotes;
2495
+ return names.reduce<Record<string, string>>((params, name, index) => {
2496
+ params[name] = decodeURIComponent(match[index + 1] ?? '');
2497
+ return params;
2498
+ }, {});
3024
2499
  };
3025
2500
 
3026
- export default function ShellCartPage() {
2501
+ const buildPath = (pattern: string, params: Record<string, string>) => {
2502
+ const path = normalisePath(pattern)
2503
+ .split('/')
2504
+ .filter(Boolean)
2505
+ .map(segment => {
2506
+ if (!segment.startsWith(':')) {
2507
+ return segment;
2508
+ }
2509
+ const value = params[paramName(segment)];
2510
+ return value ? encodeURIComponent(value) : '';
2511
+ })
2512
+ .filter(Boolean)
2513
+ .join('/');
2514
+
2515
+ return \`/\${path}\`;
2516
+ };
2517
+
2518
+ const resolveLocalisedPath = (
2519
+ pathname: string,
2520
+ targetLanguage: SupportedLanguage,
2521
+ ) => {
2522
+ const pathWithoutLanguage = stripLanguagePrefix(pathname);
2523
+
2524
+ for (const entry of Object.values(localisedUrls)) {
2525
+ const targetPattern = entry[targetLanguage];
2526
+ if (!targetPattern) {
2527
+ continue;
2528
+ }
2529
+
2530
+ for (const language of supportedLanguages) {
2531
+ const sourcePattern = entry[language];
2532
+ const params = sourcePattern
2533
+ ? matchPattern(pathWithoutLanguage, sourcePattern)
2534
+ : undefined;
2535
+ if (params) {
2536
+ return buildPath(targetPattern, params);
2537
+ }
2538
+ }
2539
+ }
2540
+
2541
+ return pathWithoutLanguage;
2542
+ };
2543
+
2544
+ const localizedPath = (pathname: string, language: SupportedLanguage) => {
2545
+ const pathWithoutLanguage = resolveLocalisedPath(pathname, language);
2546
+ return pathWithoutLanguage === '/' ? \`/\${language}\` : \`/\${language}\${pathWithoutLanguage}\`;
2547
+ };
2548
+
2549
+ const locationSuffix = (location: {
2550
+ hash?: unknown;
2551
+ search?: unknown;
2552
+ searchStr?: unknown;
2553
+ }) => {
2554
+ const locationSearch =
2555
+ typeof location.searchStr === 'string'
2556
+ ? location.searchStr
2557
+ : typeof location.search === 'string'
2558
+ ? location.search
2559
+ : '';
2560
+ const locationHash = typeof location.hash === 'string' ? location.hash : '';
2561
+
2562
+ return \`\${locationSearch}\${locationHash}\`;
2563
+ };
2564
+
2565
+ export default function ShellFrame({ children, showCart = true }: ShellFrameProps) {
3027
2566
  const { i18nInstance, language } = useModernI18n();
3028
2567
  const t = i18nInstance['t'].bind(i18nInstance);
3029
2568
  const location = useLocation();
3030
2569
  const suffix = locationSuffix(location);
3031
- const remotes = useCartRouteRemotes();
3032
- const Header = remotes?.Header;
3033
- const CartPage = remotes?.CartPage;
3034
2570
 
3035
2571
  return (
3036
- <main className="commerce-shell">
3037
- <LocalizedHead />
2572
+ <main className="min-h-screen bg-um-canvas px-4 py-5 text-um-foreground sm:px-6 lg:px-12">
3038
2573
  <BoundaryOverlay />
3039
- {Header ? <Header /> : null}
3040
- <div className="commerce-shell-actions">
3041
- <nav aria-label={t('shell.language.switcher')} className="commerce-language">
3042
- {languageCodes.map(code => (
3043
- <a
3044
- aria-current={language === code ? 'page' : undefined}
3045
- className="commerce-pill"
3046
- href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
3047
- key={code}
3048
- >
3049
- {t(\`shell.language.\${code}\`)}
3050
- </a>
3051
- ))}
3052
- </nav>
2574
+ <div className="mx-auto flex min-h-20 max-w-7xl flex-wrap items-center justify-between gap-3 bg-white/90 px-4 py-3 shadow-xl shadow-stone-900/10 sm:px-6">
2575
+ <Header />
2576
+ <div className="ml-auto flex min-w-0 items-center gap-2">
2577
+ <label className="sr-only" htmlFor="ultramodern-language">
2578
+ {t('shell.language.switcher')}
2579
+ </label>
2580
+ <select
2581
+ className="h-10 rounded-full border border-stone-900/15 bg-white px-3 text-sm font-extrabold text-stone-950 shadow-lg shadow-stone-900/5"
2582
+ id="ultramodern-language"
2583
+ onChange={event => {
2584
+ const nextLanguage = event.currentTarget.value;
2585
+ if (isSupportedLanguage(nextLanguage)) {
2586
+ window.location.assign(
2587
+ \`\${localizedPath(location.pathname, nextLanguage)}\${suffix}\`,
2588
+ );
2589
+ }
2590
+ }}
2591
+ value={language}
2592
+ >
2593
+ {supportedLanguages.map(code => (
2594
+ <option key={code} value={code}>
2595
+ {t(\`shell.language.\${code}\`)}
2596
+ </option>
2597
+ ))}
2598
+ </select>
2599
+ {showCart ? <MiniCart /> : null}
2600
+ </div>
3053
2601
  </div>
3054
- {CartPage ? <CartPage /> : null}
2602
+ {children}
3055
2603
  </main>
3056
2604
  );
3057
2605
  }
@@ -3179,8 +2727,9 @@ export default function BoundaryOverlay() {
3179
2727
 
3180
2728
  return (
3181
2729
  <>
3182
- <label className="commerce-boundary-toggle">
2730
+ <label className="fixed bottom-5 left-5 z-[80] flex items-center gap-2 rounded-xl border border-stone-900/10 bg-white/95 px-4 py-3 text-sm font-semibold text-stone-950 shadow-2xl shadow-stone-900/15">
3183
2731
  <input
2732
+ className="size-4 accent-emerald-800"
3184
2733
  checked={enabled}
3185
2734
  onChange={event => setEnabled(event.currentTarget.checked)}
3186
2735
  type="checkbox"
@@ -3188,15 +2737,16 @@ export default function BoundaryOverlay() {
3188
2737
  <span>{toggleLabel}</span>
3189
2738
  </label>
3190
2739
  {enabled ? (
3191
- <div aria-hidden="true" className="boundary-overlay">
2740
+ <div aria-hidden="true" className="pointer-events-none fixed inset-0 z-[70]">
3192
2741
  {boxes.map(box => (
3193
2742
  <div
3194
- className="boundary-overlay__box"
2743
+ className="fixed rounded-lg border"
3195
2744
  data-label-placement={box.labelPlacement}
3196
2745
  key={box.id}
3197
2746
  style={
3198
2747
  {
3199
- '--boundary-color': box.color,
2748
+ borderColor: box.color,
2749
+ boxShadow: \`0 0 0 1px rgba(255,255,255,.72), 0 6px 20px color-mix(in srgb, \${box.color} 20%, transparent)\`,
3200
2750
  height: box.height,
3201
2751
  left: box.left,
3202
2752
  top: box.top,
@@ -3204,7 +2754,12 @@ export default function BoundaryOverlay() {
3204
2754
  } as CSSProperties
3205
2755
  }
3206
2756
  >
3207
- <span className="boundary-overlay__label">{box.label}</span>
2757
+ <span
2758
+ className={\`absolute right-1 top-1 whitespace-nowrap rounded-full px-2 py-1 text-[0.7rem] font-black leading-none text-stone-950 \${box.labelPlacement === 'above' ? 'bottom-[calc(100%+0.25rem)] top-auto' : ''}\`}
2759
+ style={{ backgroundColor: box.color }}
2760
+ >
2761
+ {box.label}
2762
+ </span>
3208
2763
  </div>
3209
2764
  ))}
3210
2765
  </div>
@@ -3233,55 +2788,70 @@ const loadRemoteComponent = async (specifier: string) => {
3233
2788
 
3234
2789
  const remoteFallback =
3235
2790
  ({ error }: { error: Error }) =>
3236
- <div data-remote-error={error.name}>Remote unavailable</div>;
2791
+ <div className="rounded-xl border border-red-900/20 bg-red-50 px-4 py-3 text-sm font-semibold text-red-900" data-remote-error={error.name}>Remote unavailable</div>;
2792
+
2793
+ const HeaderLoading = () => (
2794
+ <div className="flex min-w-0 flex-1 items-center gap-5" data-mf-boundary="explore">
2795
+ <div className="h-6 w-28 rounded-full bg-stone-200" />
2796
+ <div className="hidden h-5 w-44 rounded-full bg-stone-100 sm:block" />
2797
+ </div>
2798
+ );
2799
+
2800
+ const MiniCartLoading = () => (
2801
+ <div className="h-10 w-28 rounded-full bg-stone-100" data-mf-boundary="checkout" />
2802
+ );
2803
+
2804
+ const PanelLoading = () => (
2805
+ <section className="mx-auto mt-10 max-w-7xl rounded-2xl bg-white/75 p-6 shadow-xl shadow-stone-900/10">
2806
+ <div className="h-5 w-40 rounded-full bg-stone-200" />
2807
+ <div className="mt-5 grid gap-4 md:grid-cols-2">
2808
+ <div className="h-36 rounded-xl bg-stone-100" />
2809
+ <div className="h-36 rounded-xl bg-stone-100" />
2810
+ </div>
2811
+ </section>
2812
+ );
3237
2813
 
3238
2814
  export const Header = createLazyComponent({
3239
2815
  export: 'default',
3240
2816
  fallback: remoteFallback,
3241
2817
  instance: getInstance(),
3242
2818
  loader: () => loadRemoteComponent('explore/Header'),
3243
- loading: null,
3244
- noSSR: true,
2819
+ loading: <HeaderLoading />,
3245
2820
  });
3246
2821
  export const StorePicker = createLazyComponent({
3247
2822
  export: 'default',
3248
2823
  fallback: remoteFallback,
3249
2824
  instance: getInstance(),
3250
2825
  loader: () => loadRemoteComponent('explore/StorePicker'),
3251
- loading: null,
3252
- noSSR: true,
2826
+ loading: <PanelLoading />,
3253
2827
  });
3254
2828
  export const Recommendations = createLazyComponent({
3255
2829
  export: 'default',
3256
2830
  fallback: remoteFallback,
3257
2831
  instance: getInstance(),
3258
2832
  loader: () => loadRemoteComponent('explore/Recommendations'),
3259
- loading: null,
3260
- noSSR: true,
2833
+ loading: <PanelLoading />,
3261
2834
  });
3262
2835
  export const ProductPage = createLazyComponent({
3263
2836
  export: 'default',
3264
2837
  fallback: remoteFallback,
3265
2838
  instance: getInstance(),
3266
2839
  loader: () => loadRemoteComponent('decide/ProductPage'),
3267
- loading: null,
3268
- noSSR: true,
2840
+ loading: <PanelLoading />,
3269
2841
  });
3270
2842
  export const MiniCart = createLazyComponent({
3271
2843
  export: 'default',
3272
2844
  fallback: remoteFallback,
3273
2845
  instance: getInstance(),
3274
2846
  loader: () => loadRemoteComponent('checkout/MiniCart'),
3275
- loading: null,
3276
- noSSR: true,
2847
+ loading: <MiniCartLoading />,
3277
2848
  });
3278
2849
  export const CartPage = createLazyComponent({
3279
2850
  export: 'default',
3280
2851
  fallback: remoteFallback,
3281
2852
  instance: getInstance(),
3282
2853
  loader: () => loadRemoteComponent('checkout/CartPage'),
3283
- loading: null,
3284
- noSSR: true,
2854
+ loading: <PanelLoading />,
3285
2855
  });
3286
2856
  `;
3287
2857
  }
@@ -3327,12 +2897,13 @@ export default function ${toPascalCase(app.id)}Home() {
3327
2897
  const location = useLocation();
3328
2898
  const suffix = locationSuffix(location);
3329
2899
  ${effectBffState} return (
3330
- <main>
2900
+ <main className="min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8">
3331
2901
  <LocalizedHead />
3332
- <nav aria-label={t('${app.domain}.language.switcher')}>
2902
+ <nav aria-label={t('${app.domain}.language.switcher')} className="flex gap-3">
3333
2903
  {supportedLanguages.map(code => (
3334
2904
  <a
3335
2905
  aria-current={language === code ? 'page' : undefined}
2906
+ className="rounded-full border border-stone-900/15 bg-white px-4 py-2 text-sm font-bold text-stone-950 no-underline"
3336
2907
  href={\`\${localizedPath(location.pathname, code)}\${suffix}\`}
3337
2908
  key={code}
3338
2909
  >
@@ -3340,9 +2911,9 @@ ${effectBffState} return (
3340
2911
  </a>
3341
2912
  ))}
3342
2913
  </nav>
3343
- <h1>{t('${app.domain}.title')}</h1>
3344
- <p data-mf-role="${app.kind}">{t('${app.domain}.role')}</p>
3345
- <p data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
2914
+ <h1 className="mt-10 text-5xl font-black">{t('${app.domain}.title')}</h1>
2915
+ <p className="mt-3 text-lg text-stone-600" data-mf-role="${app.kind}">{t('${app.domain}.role')}</p>
2916
+ <p className="sr-only" data-build-marker={ultramodernUiMarker.build} data-testid="ultramodern-ui-marker">
3346
2917
  {ultramodernUiMarker.appId}:{ultramodernUiMarker.version}
3347
2918
  </p>
3348
2919
  ${effectBffMarkup} </main>
@@ -3370,9 +2941,9 @@ function createRemoteEntry(app) {
3370
2941
  `;
3371
2942
  return `export default function ${toPascalCase(app.domain ?? app.id)}Route() {
3372
2943
  return (
3373
- <section data-mf-remote="${app.id}" data-mf-expose="./Route">
3374
- <h2>${app.displayName}</h2>
3375
- <p>Route surface for ${app.domain ?? app.id}.</p>
2944
+ <section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10" data-mf-remote="${app.id}" data-mf-expose="./Route">
2945
+ <h2 className="text-2xl font-black">${app.displayName}</h2>
2946
+ <p className="mt-2 text-stone-600">Route surface for ${app.domain ?? app.id}.</p>
3376
2947
  </section>
3377
2948
  );
3378
2949
  }
@@ -3383,9 +2954,9 @@ function createRemoteWidget(app) {
3383
2954
  const body = 'vertical' === app.kind ? `Owns the ${app.domain} vertical route surface.` : 'Provides shared UI primitives for the workspace.';
3384
2955
  return `export default function ${componentName}() {
3385
2956
  return (
3386
- <section data-mf-remote="${app.id}">
3387
- <h2>${app.displayName}</h2>
3388
- <p>${body}</p>
2957
+ <section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10" data-mf-remote="${app.id}">
2958
+ <h2 className="text-2xl font-black">${app.displayName}</h2>
2959
+ <p className="mt-2 text-stone-600">${body}</p>
3389
2960
  </section>
3390
2961
  );
3391
2962
  }
@@ -3399,23 +2970,27 @@ export default function Header() {
3399
2970
  const t = i18nInstance['t'].bind(i18nInstance);
3400
2971
 
3401
2972
  return (
3402
- <header className="commerce-header" data-mf-boundary="explore">
3403
- <a className="commerce-logo" href={\`/\${language}\`}>Acre & Iron</a>
3404
- <nav aria-label={t('explore.header.navigation')} className="commerce-nav">
3405
- <a href={\`/\${language}/tractors\`}>{t('explore.header.machines')}</a>
3406
- <a href={\`/\${language}/stores\`}>{t('explore.header.stores')}</a>
2973
+ <header className="flex min-w-0 flex-1 flex-wrap items-center gap-x-8 gap-y-2" data-mf-boundary="explore">
2974
+ <a className="whitespace-nowrap text-xl font-black tracking-normal text-stone-950 no-underline" href={\`/\${language}\`}>Acre & Iron</a>
2975
+ <nav aria-label={t('explore.header.navigation')} className="flex items-center gap-5">
2976
+ <a className="text-sm font-extrabold text-stone-900 no-underline" href={\`/\${language}/tractors\`}>{t('explore.header.machines')}</a>
2977
+ <a className="text-sm font-extrabold text-stone-900 no-underline" href={\`/\${language}/stores\`}>{t('explore.header.stores')}</a>
3407
2978
  </nav>
3408
2979
  </header>
3409
2980
  );
3410
2981
  }
3411
2982
  `;
3412
2983
  if ('remote-explore' === app.id && './Recommendations' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
2984
+ import autonomyImage from '../assets/autonomy.svg';
2985
+ import fieldLoaderImage from '../assets/field-loader.svg';
2986
+ import orchardImage from '../assets/orchard.svg';
2987
+ import vineyardImage from '../assets/vineyard.svg';
3413
2988
 
3414
2989
  const tractors = [
3415
- { badge: 'explore.recommendations.bestRows', name: 'Orchard Tractor', slug: 'orchard-tractor' },
3416
- { badge: 'explore.recommendations.aiFirst', name: 'Autonomy Retrofit Kit', slug: 'autonomy-retrofit-kit' },
3417
- { badge: 'explore.recommendations.loaderReady', name: 'Field Loader 112', slug: 'field-loader-112' },
3418
- { badge: 'explore.recommendations.vineyard', name: 'Vineyard Narrow 80', slug: 'vineyard-narrow-80' },
2990
+ { badge: 'explore.recommendations.bestRows', image: orchardImage, name: 'Orchard Tractor', slug: 'orchard-tractor' },
2991
+ { badge: 'explore.recommendations.aiFirst', image: autonomyImage, name: 'Autonomy Retrofit Kit', slug: 'autonomy-retrofit-kit' },
2992
+ { badge: 'explore.recommendations.loaderReady', image: fieldLoaderImage, name: 'Field Loader 112', slug: 'field-loader-112' },
2993
+ { badge: 'explore.recommendations.vineyard', image: vineyardImage, name: 'Vineyard Narrow 80', slug: 'vineyard-narrow-80' },
3419
2994
  ] as const;
3420
2995
 
3421
2996
  export default function Recommendations() {
@@ -3423,13 +2998,14 @@ export default function Recommendations() {
3423
2998
  const t = i18nInstance['t'].bind(i18nInstance);
3424
2999
 
3425
3000
  return (
3426
- <section className="commerce-page" data-mf-boundary="explore">
3427
- <h2 className="commerce-section-title">{t('explore.recommendations.title')}</h2>
3428
- <div className="commerce-grid">
3001
+ <section className="mx-auto mt-12 max-w-7xl" data-mf-boundary="explore">
3002
+ <h2 className="text-3xl font-black tracking-normal text-stone-950">{t('explore.recommendations.title')}</h2>
3003
+ <div className="mt-5 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
3429
3004
  {tractors.map(tractor => (
3430
- <a className="commerce-card" href={\`/\${language}/tractors/\${tractor.slug}\`} key={tractor.slug}>
3431
- <span>{t(tractor.badge)}</span>
3432
- <strong>{tractor.name}</strong>
3005
+ <a className="block rounded-2xl bg-white/90 p-4 text-stone-950 no-underline shadow-xl shadow-stone-900/10 transition hover:-translate-y-0.5 hover:shadow-2xl" href={\`/\${language}/tractors/\${tractor.slug}\`} key={tractor.slug}>
3006
+ <img alt="" className="aspect-video w-full rounded-xl bg-stone-200 object-cover" src={tractor.image} />
3007
+ <span className="mt-4 block text-xs font-black uppercase tracking-[0.16em] text-amber-700">{t(tractor.badge)}</span>
3008
+ <strong className="mt-2 block text-xl font-black leading-tight">{tractor.name}</strong>
3433
3009
  </a>
3434
3010
  ))}
3435
3011
  </div>
@@ -3438,22 +3014,26 @@ export default function Recommendations() {
3438
3014
  }
3439
3015
  `;
3440
3016
  if ('remote-explore' === app.id && './StorePicker' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
3017
+ import fieldLoaderImage from '../assets/field-loader.svg';
3018
+ import vineyardImage from '../assets/vineyard.svg';
3441
3019
 
3442
3020
  export default function StorePicker() {
3443
3021
  const { i18nInstance } = useModernI18n();
3444
3022
  const t = i18nInstance['t'].bind(i18nInstance);
3445
3023
 
3446
3024
  return (
3447
- <section className="commerce-page" data-mf-boundary="explore">
3448
- <h2 className="commerce-section-title">{t('explore.stores.title')}</h2>
3449
- <div className="commerce-grid">
3450
- <article className="commerce-card">
3451
- <span>{t('explore.stores.northRegion')}</span>
3452
- <strong>Bohemia Field Supply</strong>
3025
+ <section className="mx-auto mt-12 max-w-7xl" data-mf-boundary="explore">
3026
+ <h2 className="text-3xl font-black tracking-normal text-stone-950">{t('explore.stores.title')}</h2>
3027
+ <div className="mt-5 grid gap-4 md:grid-cols-2">
3028
+ <article className="rounded-2xl bg-white/90 p-4 shadow-xl shadow-stone-900/10">
3029
+ <img alt="" className="aspect-video w-full rounded-xl bg-stone-200 object-cover" src={fieldLoaderImage} />
3030
+ <span className="mt-4 block text-xs font-black uppercase tracking-[0.16em] text-emerald-800">{t('explore.stores.northRegion')}</span>
3031
+ <strong className="mt-2 block text-2xl font-black">Bohemia Field Supply</strong>
3453
3032
  </article>
3454
- <article className="commerce-card">
3455
- <span>{t('explore.stores.southRegion')}</span>
3456
- <strong>Moravia Iron Works</strong>
3033
+ <article className="rounded-2xl bg-white/90 p-4 shadow-xl shadow-stone-900/10">
3034
+ <img alt="" className="aspect-video w-full rounded-xl bg-stone-200 object-cover" src={vineyardImage} />
3035
+ <span className="mt-4 block text-xs font-black uppercase tracking-[0.16em] text-emerald-800">{t('explore.stores.southRegion')}</span>
3036
+ <strong className="mt-2 block text-2xl font-black">Moravia Iron Works</strong>
3457
3037
  </article>
3458
3038
  </div>
3459
3039
  </section>
@@ -3461,12 +3041,13 @@ export default function StorePicker() {
3461
3041
  }
3462
3042
  `;
3463
3043
  if ('remote-explore' === app.id && './Footer' === expose) return `export default function Footer() {
3464
- return <footer className="commerce-footer" data-mf-boundary="explore">Acre & Iron</footer>;
3044
+ return <footer className="mx-auto mt-12 max-w-7xl text-sm font-bold text-stone-600" data-mf-boundary="explore">Acre & Iron</footer>;
3465
3045
  }
3466
3046
  `;
3467
3047
  if ('./Widget' === expose) return createRemoteWidget(app);
3468
3048
  const componentName = `${toPascalCase(app.domain ?? app.id)}${toPascalCase(expose.replace(/^\.\//u, ''))}`;
3469
3049
  if ('remote-decide' === app.id && './ProductPage' === expose) return `import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
3050
+ import fieldLoaderImage from '../assets/field-loader.svg';
3470
3051
  import { AddToCart, Recommendations } from './remote-components';
3471
3052
 
3472
3053
  export default function ${componentName}() {
@@ -3475,16 +3056,16 @@ export default function ${componentName}() {
3475
3056
 
3476
3057
  return (
3477
3058
  <>
3478
- <section className="commerce-page commerce-product" data-mf-boundary="decide" data-mf-remote="${app.id}" data-mf-expose="${expose}">
3479
- <div className="commerce-product-media" aria-hidden="true" />
3059
+ <section className="mx-auto mt-10 grid max-w-7xl items-center gap-8 md:grid-cols-[1fr_0.95fr] lg:gap-14" data-mf-boundary="decide" data-mf-remote="${app.id}" data-mf-expose="${expose}">
3060
+ <img alt="" className="aspect-[1/0.9] w-full rounded-3xl border-[18px] border-amber-200 bg-stone-200 object-cover shadow-2xl shadow-stone-900/20" src={fieldLoaderImage} />
3480
3061
  <div>
3481
- <p className="commerce-eyebrow">{t('decide.product.eyebrow')}</p>
3482
- <h1 className="commerce-title">Field Loader 112</h1>
3483
- <p className="commerce-lede">{t('decide.product.lede')}</p>
3484
- <div className="commerce-facts">
3485
- <article className="commerce-fact"><span>{t('decide.product.price')}</span><strong>EUR 42,500</strong></article>
3486
- <article className="commerce-fact"><span>{t('decide.product.power')}</span><strong>112 hp</strong></article>
3487
- <article className="commerce-fact"><span>{t('decide.product.availability')}</span><strong>{t('decide.product.inStock')}</strong></article>
3062
+ <p className="text-xs font-black uppercase tracking-[0.18em] text-emerald-800">{t('decide.product.eyebrow')}</p>
3063
+ <h1 className="mt-3 text-5xl font-black leading-none tracking-normal text-stone-950 md:text-7xl">Field Loader 112</h1>
3064
+ <p className="mt-5 max-w-2xl text-lg leading-8 text-stone-600">{t('decide.product.lede')}</p>
3065
+ <div className="mt-8 grid gap-4 sm:grid-cols-3">
3066
+ <article className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10"><span className="block text-sm font-bold text-stone-500">{t('decide.product.price')}</span><strong className="mt-2 block text-lg font-black">EUR 42,500</strong></article>
3067
+ <article className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10"><span className="block text-sm font-bold text-stone-500">{t('decide.product.power')}</span><strong className="mt-2 block text-lg font-black">112 hp</strong></article>
3068
+ <article className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10"><span className="block text-sm font-bold text-stone-500">{t('decide.product.availability')}</span><strong className="mt-2 block text-lg font-black">{t('decide.product.inStock')}</strong></article>
3488
3069
  </div>
3489
3070
  <AddToCart />
3490
3071
  </div>
@@ -3503,11 +3084,11 @@ export default function ${componentName}() {
3503
3084
  const cart = useCartLines();
3504
3085
 
3505
3086
  return (
3506
- <div className="commerce-checkout" data-mf-boundary="checkout">
3507
- <button className="commerce-button" onClick={cart.addFieldLoader} type="button">
3087
+ <div className="mt-8 flex flex-wrap gap-3" data-mf-boundary="checkout">
3088
+ <button className="inline-flex min-h-11 items-center justify-center rounded-full bg-emerald-800 px-5 font-bold text-white shadow-lg shadow-stone-900/10" onClick={cart.addFieldLoader} type="button">
3508
3089
  {t('checkout.actions.addToCart')}
3509
3090
  </button>
3510
- <a className="commerce-link-button" href={\`/\${language}/cart\`}>
3091
+ <a className="inline-flex min-h-11 items-center justify-center rounded-full border border-stone-900/15 bg-white/90 px-5 font-bold text-stone-950 shadow-lg shadow-stone-900/10" href={\`/\${language}/cart\`}>
3511
3092
  {t('checkout.actions.viewCart')}
3512
3093
  </a>
3513
3094
  </div>
@@ -3524,7 +3105,7 @@ export default function ${componentName}() {
3524
3105
  const count = cart.lines.reduce((sum, line) => sum + line.quantity, 0);
3525
3106
 
3526
3107
  return (
3527
- <a className="commerce-cart-button" data-mf-boundary="checkout" href={\`/\${language}/cart\`}>
3108
+ <a className="inline-flex h-10 shrink-0 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 text-sm font-extrabold text-stone-950 no-underline shadow-lg shadow-stone-900/5" data-mf-boundary="checkout" href={\`/\${language}/cart\`}>
3528
3109
  {t('checkout.cart.title')} ({count})
3529
3110
  </a>
3530
3111
  );
@@ -3539,24 +3120,24 @@ export default function ${componentName}() {
3539
3120
  const cart = useCartLines();
3540
3121
 
3541
3122
  return (
3542
- <section className="commerce-page" data-mf-boundary="checkout" data-mf-remote="${app.id}" data-mf-expose="${expose}">
3543
- <h1 className="commerce-title">{t('checkout.cart.title')}</h1>
3544
- <div className="commerce-cart-panel">
3123
+ <section className="mx-auto mt-10 max-w-7xl" data-mf-boundary="checkout" data-mf-remote="${app.id}" data-mf-expose="${expose}">
3124
+ <h1 className="text-5xl font-black leading-none tracking-normal text-stone-950 md:text-7xl">{t('checkout.cart.title')}</h1>
3125
+ <div className="mt-8 rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10">
3545
3126
  {cart.lines.length === 0 ? (
3546
3127
  <p>{t('checkout.cart.empty')}</p>
3547
3128
  ) : (
3548
3129
  <>
3549
3130
  {cart.lines.map(line => (
3550
- <article className="commerce-cart-line" key={line.id}>
3131
+ <article className="grid gap-4 border-t border-stone-900/10 py-4 first:border-t-0 sm:grid-cols-[1fr_auto] sm:items-center" key={line.id}>
3551
3132
  <div>
3552
- <strong>{line.name}</strong>
3553
- <p>EUR {line.price.toLocaleString('en-US')}</p>
3133
+ <strong className="text-lg font-black">{line.name}</strong>
3134
+ <p className="text-stone-600">EUR {line.price.toLocaleString('en-US')}</p>
3554
3135
  </div>
3555
- <div className="commerce-quantity">
3556
- <button className="commerce-quantity-button" onClick={() => cart.decrement(line.id)} type="button">-</button>
3557
- <span>{line.quantity}</span>
3558
- <button className="commerce-quantity-button" onClick={() => cart.increment(line.id)} type="button">+</button>
3559
- <button className="commerce-link-button" onClick={() => cart.remove(line.id)} type="button">
3136
+ <div className="flex flex-wrap items-center gap-2">
3137
+ <button className="inline-flex size-9 items-center justify-center rounded-full border border-stone-900/15 bg-white font-black" onClick={() => cart.decrement(line.id)} type="button">-</button>
3138
+ <span className="min-w-6 text-center font-black">{line.quantity}</span>
3139
+ <button className="inline-flex size-9 items-center justify-center rounded-full border border-stone-900/15 bg-white font-black" onClick={() => cart.increment(line.id)} type="button">+</button>
3140
+ <button className="inline-flex min-h-10 items-center justify-center rounded-full border border-stone-900/15 bg-white px-4 font-bold text-stone-950" onClick={() => cart.remove(line.id)} type="button">
3560
3141
  {t('checkout.actions.remove')}
3561
3142
  </button>
3562
3143
  </div>
@@ -3572,9 +3153,9 @@ export default function ${componentName}() {
3572
3153
  `;
3573
3154
  return `export default function ${componentName}() {
3574
3155
  return (
3575
- <section data-mf-remote="${app.id}" data-mf-expose="${expose}">
3576
- <h2>${app.displayName} ${expose.replace(/^\.\//u, '')}</h2>
3577
- <p>Module Federation surface owned by ${app.ownership.team}.</p>
3156
+ <section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10" data-mf-remote="${app.id}" data-mf-expose="${expose}">
3157
+ <h2 className="text-2xl font-black">${app.displayName} ${expose.replace(/^\.\//u, '')}</h2>
3158
+ <p className="mt-2 text-stone-600">Module Federation surface owned by ${app.ownership.team}.</p>
3578
3159
  </section>
3579
3160
  );
3580
3161
  }
@@ -3599,23 +3180,40 @@ const loadRemoteComponent = async (specifier: string) => {
3599
3180
 
3600
3181
  const remoteFallback =
3601
3182
  ({ error }: { error: Error }) =>
3602
- <div data-remote-error={error.name}>Remote unavailable</div>;
3183
+ <div className="rounded-xl border border-red-900/20 bg-red-50 px-4 py-3 text-sm font-semibold text-red-900" data-remote-error={error.name}>Remote unavailable</div>;
3184
+
3185
+ const AddToCartLoading = () => (
3186
+ <div className="mt-8 flex gap-3" data-mf-boundary="checkout">
3187
+ <div className="h-11 w-32 rounded-full bg-stone-200" />
3188
+ <div className="h-11 w-28 rounded-full bg-white/80" />
3189
+ </div>
3190
+ );
3191
+
3192
+ const RecommendationsLoading = () => (
3193
+ <section className="mx-auto mt-12 max-w-7xl" data-mf-boundary="explore">
3194
+ <div className="h-8 w-64 rounded-full bg-stone-200" />
3195
+ <div className="mt-5 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
3196
+ <div className="h-48 rounded-2xl bg-white/80" />
3197
+ <div className="h-48 rounded-2xl bg-white/80" />
3198
+ <div className="h-48 rounded-2xl bg-white/80" />
3199
+ <div className="h-48 rounded-2xl bg-white/80" />
3200
+ </div>
3201
+ </section>
3202
+ );
3603
3203
 
3604
3204
  export const AddToCart = createLazyComponent({
3605
3205
  export: 'default',
3606
3206
  fallback: remoteFallback,
3607
3207
  instance: getInstance(),
3608
3208
  loader: () => loadRemoteComponent('checkout/AddToCart'),
3609
- loading: null,
3610
- noSSR: true,
3209
+ loading: <AddToCartLoading />,
3611
3210
  });
3612
3211
  export const Recommendations = createLazyComponent({
3613
3212
  export: 'default',
3614
3213
  fallback: remoteFallback,
3615
3214
  instance: getInstance(),
3616
3215
  loader: () => loadRemoteComponent('explore/Recommendations'),
3617
- loading: null,
3618
- noSSR: true,
3216
+ loading: <RecommendationsLoading />,
3619
3217
  });
3620
3218
  `;
3621
3219
  }
@@ -3749,17 +3347,9 @@ function createAppLocaleMessages(app, language) {
3749
3347
  };
3750
3348
  }
3751
3349
  function createDesignButton() {
3752
- return `import { designTokens } from '../tokens';
3753
-
3754
- export default function Button({ label }: { label: string }) {
3350
+ return `export default function Button({ label }: { label: string }) {
3755
3351
  return (
3756
- <button
3757
- type="button"
3758
- style={{
3759
- borderRadius: designTokens.radius.control,
3760
- color: designTokens.color.foreground,
3761
- }}
3762
- >
3352
+ <button className="rounded-full text-um-foreground" type="button">
3763
3353
  {label}
3764
3354
  </button>
3765
3355
  );
@@ -3875,14 +3465,12 @@ export function useCartLines() {
3875
3465
  `;
3876
3466
  }
3877
3467
  function createSharedDesignTokensCss() {
3878
- return `@layer ultramodern-shared-tokens {
3879
- :root {
3880
- --um-color-accent: #2f8f68;
3881
- --um-color-canvas: #f1eadc;
3882
- --um-color-foreground: #133225;
3883
- --um-color-link: #166b4b;
3884
- --um-color-surface: #f6fbf7;
3885
- }
3468
+ return `@theme {
3469
+ --color-um-accent: #2f8f68;
3470
+ --color-um-canvas: #f1eadc;
3471
+ --color-um-foreground: #133225;
3472
+ --color-um-link: #166b4b;
3473
+ --color-um-surface: #f6fbf7;
3886
3474
  }
3887
3475
  `;
3888
3476
  }
@@ -5788,10 +5376,12 @@ function writeApp(targetDir, scope, app, packageSource, enableTailwind) {
5788
5376
  }
5789
5377
  writeFile(targetDir, `${app.directory}/module-federation.config.ts`, 'shell' === app.kind ? createShellModuleFederationConfig() : createRemoteModuleFederationConfig(app));
5790
5378
  writeFile(targetDir, `${app.directory}/src/routes/layout.tsx`, createLayout(app.id));
5379
+ for (const [relativePath, content] of Object.entries(commerceAssetsForApp(app)))writeFile(targetDir, `${app.directory}/${relativePath}`, content);
5791
5380
  writeFile(targetDir, `${app.directory}/src/routes/[lang]/page.tsx`, 'shell' === app.kind ? createShellPage() : createRemotePage(app));
5792
5381
  for (const route of createRouteOwnedI18nPaths(app))if ('/' !== route.canonicalPath && 'shell' !== app.kind) writeFile(targetDir, createRoutePageFilePath(app, route.canonicalPath), createRouteAliasPage(route.canonicalPath));
5793
5382
  if ('shell' === app.kind) {
5794
5383
  writeFile(targetDir, `${app.directory}/src/routes/remote-components.tsx`, createShellRemoteComponents());
5384
+ writeFile(targetDir, `${app.directory}/src/routes/shell-frame.tsx`, createShellFrameComponent());
5795
5385
  writeFile(targetDir, `${app.directory}/src/routes/boundary-overlay.tsx`, createShellBoundaryOverlay());
5796
5386
  writeFile(targetDir, `${app.directory}/src/effect/recommendations-client.ts`, createShellEffectClient(scope));
5797
5387
  writeFile(targetDir, `${app.directory}/src/routes/[lang]/tractors/page.tsx`, createShellTractorsPage());
@@ -5824,7 +5414,13 @@ function writeEffectService(targetDir, scope, packageSource, enableTailwind, ser
5824
5414
  writeFile(targetDir, `${service.directory}/src/ultramodern-build.ts`, createUltramodernBuildModule(scope, service));
5825
5415
  writeFile(targetDir, `${service.directory}/src/routes/layout.tsx`, createLayout(service.id));
5826
5416
  writeFile(targetDir, `${service.directory}/src/routes/page.tsx`, `export default function ${toPascalCase(service.id)}Home() {
5827
- return <main>${service.id} Effect service</main>;
5417
+ return (
5418
+ <main className="min-h-screen bg-um-canvas px-4 py-6 text-um-foreground sm:px-8">
5419
+ <section className="rounded-2xl bg-white/90 p-5 shadow-xl shadow-stone-900/10">
5420
+ <h1 className="text-3xl font-black">${service.id} Effect service</h1>
5421
+ </section>
5422
+ </main>
5423
+ );
5828
5424
  }
5829
5425
  `);
5830
5426
  writeFile(targetDir, `${service.directory}/src/routes/index.css`, createServiceStyles(enableTailwind, scope, service));