veryfront 0.1.93 → 0.1.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
  3. package/esm/src/platform/adapters/fs/veryfront/adapter.js +15 -3
  4. package/esm/src/platform/adapters/fs/veryfront/types.d.ts +2 -0
  5. package/esm/src/platform/adapters/fs/veryfront/types.d.ts.map +1 -1
  6. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +5 -1
  7. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
  8. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +10 -2
  9. package/esm/src/server/handlers/dev/scripts/hmr-scripts.d.ts.map +1 -1
  10. package/esm/src/server/handlers/dev/scripts/hmr-scripts.js +92 -4
  11. package/esm/src/server/handlers/preview/hmr-message-router.d.ts +2 -1
  12. package/esm/src/server/handlers/preview/hmr-message-router.d.ts.map +1 -1
  13. package/esm/src/server/handlers/preview/hmr-message-router.js +15 -5
  14. package/esm/src/server/handlers/preview/hmr.handler.js +1 -1
  15. package/esm/src/server/reload-notifier.d.ts +3 -1
  16. package/esm/src/server/reload-notifier.d.ts.map +1 -1
  17. package/esm/src/utils/version.d.ts +1 -1
  18. package/esm/src/utils/version.js +1 -1
  19. package/package.json +1 -1
  20. package/src/deno.js +1 -1
  21. package/src/src/platform/adapters/fs/veryfront/adapter.ts +18 -4
  22. package/src/src/platform/adapters/fs/veryfront/types.ts +2 -0
  23. package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +18 -3
  24. package/src/src/server/handlers/dev/scripts/hmr-scripts.ts +94 -4
  25. package/src/src/server/handlers/preview/hmr-message-router.ts +15 -5
  26. package/src/src/server/handlers/preview/hmr.handler.ts +1 -1
  27. package/src/src/server/reload-notifier.ts +3 -1
  28. package/src/src/utils/version.ts +1 -1
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/adapter.ts"],"names":[],"mappings":"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"}
@@ -554,7 +554,7 @@ export class VeryfrontFSAdapter {
554
554
  */
555
555
  async triggerCSSPregeneration(files) {
556
556
  try {
557
- const { pregenerateCSSFromFiles, findStylesheetFromFiles } = await import("../../../../html/styles-builder/css-pregeneration.js");
557
+ const { buildPreparedCSSArtifactFromFiles, findStylesheetFromFiles } = await import("../../../../html/styles-builder/css-pregeneration.js");
558
558
  const { resolveStyleContentVersion } = await import("../../../../html/styles-builder/content-version.js");
559
559
  const { createStyleScopeProfile } = await import("../../../../html/styles-builder/style-scope-profile.js");
560
560
  let stylesheetPath;
@@ -564,7 +564,7 @@ export class VeryfrontFSAdapter {
564
564
  logger.debug("Skipping CSS pre-generation without projectDir", {
565
565
  projectSlug: this.projectSlug,
566
566
  });
567
- return;
567
+ return undefined;
568
568
  }
569
569
  try {
570
570
  const { runtime } = await import("../../registry.js");
@@ -587,7 +587,7 @@ export class VeryfrontFSAdapter {
587
587
  releaseId: this.contentContext?.releaseId ?? null,
588
588
  environmentName: this.contentContext?.environmentName ?? null,
589
589
  });
590
- await pregenerateCSSFromFiles({
590
+ const result = await buildPreparedCSSArtifactFromFiles({
591
591
  projectSlug: this.projectSlug,
592
592
  projectVersion,
593
593
  projectDir,
@@ -599,12 +599,24 @@ export class VeryfrontFSAdapter {
599
599
  environment: "preview",
600
600
  buildMode: "production",
601
601
  });
602
+ logger.debug("CSS pre-generation complete", {
603
+ projectSlug: this.projectSlug,
604
+ projectVersion,
605
+ cssHash: result.hash,
606
+ candidateCount: result.candidateCount,
607
+ fromCache: result.fromCache,
608
+ });
609
+ return {
610
+ hash: result.hash,
611
+ assetPath: `/_vf/css/${result.hash}.css`,
612
+ };
602
613
  }
603
614
  catch (error) {
604
615
  logger.warn("CSS pre-generation failed", {
605
616
  projectSlug: this.projectSlug,
606
617
  error: error instanceof Error ? error.message : String(error),
607
618
  });
619
+ return undefined;
608
620
  }
609
621
  }
610
622
  }
@@ -110,6 +110,8 @@ export interface InvalidationProjectContext {
110
110
  environment?: "preview" | "production";
111
111
  branch?: string | null;
112
112
  releaseId?: string | null;
113
+ styleArtifactHash?: string;
114
+ styleAssetPath?: string;
113
115
  }
114
116
  export interface InvalidationCallbacks {
115
117
  clearSSRModuleCache?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,10 @@
1
1
  import type { FileCache } from "../cache/file-cache.js";
2
2
  import type { VeryfrontApiClient } from "../../veryfront-api-client/index.js";
3
3
  import type { ContentSource, InvalidationCallbacks, ResolvedContentContext } from "./types.js";
4
+ interface PreviewStyleArtifactInfo {
5
+ hash: string;
6
+ assetPath: string;
7
+ }
4
8
  interface WebSocketDeps {
5
9
  apiBaseUrl: string;
6
10
  apiToken: string;
@@ -20,7 +24,7 @@ interface WebSocketDeps {
20
24
  pregenerateStyles?: (files: Array<{
21
25
  path: string;
22
26
  content?: string;
23
- }>) => Promise<void>;
27
+ }>) => Promise<PreviewStyleArtifactInfo | undefined>;
24
28
  }
25
29
  export declare class WebSocketManager {
26
30
  private readonly deps;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-manager.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/websocket-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAwB/F,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,qBAAqB,EAAE,qBAAqB,CAAC;IAE7C,iBAAiB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IACvD,gBAAgB,EAAE,MAAM,aAAa,CAAC;IACtC,aAAa,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACxC,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzF;AAED,qBAAa,gBAAgB;IAqBf,OAAO,CAAC,QAAQ,CAAC,IAAI;IApBjC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAsD;IAC9E,OAAO,CAAC,gBAAgB,CAAuD;IAC/E,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,iBAAiB,CAAsD;IAC/E,OAAO,CAAC,0BAA0B,CAAsD;IACxF,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,iCAAiC,CAAqB;IAC9D,OAAO,CAAC,WAAW,CAIjB;gBAE2B,IAAI,EAAE,aAAa;IAEhD,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,8BAA8B;IAOtC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,2BAA2B;IAUnC,cAAc,IAAI;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B;IAID,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA+GhC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,IAAI,IAAI;IA8Bf,OAAO,CAAC,iBAAiB;IAyJzB,OAAO,CAAC,8BAA8B;IA0GtC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,6BAA6B;YAiBvB,4BAA4B;YAyI5B,mBAAmB;IA4IjC,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;CAyBpB"}
1
+ {"version":3,"file":"websocket-manager.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/websocket-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAwB/F,UAAU,wBAAwB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,aAAa;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,qBAAqB,EAAE,qBAAqB,CAAC;IAE7C,iBAAiB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IACvD,gBAAgB,EAAE,MAAM,aAAa,CAAC;IACtC,aAAa,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACxC,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,EAAE,CAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7C,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAClB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,KAC7C,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC,CAAC;CACpD;AAED,qBAAa,gBAAgB;IAqBf,OAAO,CAAC,QAAQ,CAAC,IAAI;IApBjC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAsD;IAC9E,OAAO,CAAC,gBAAgB,CAAuD;IAC/E,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,iBAAiB,CAAsD;IAC/E,OAAO,CAAC,0BAA0B,CAAsD;IACxF,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,iCAAiC,CAAqB;IAC9D,OAAO,CAAC,WAAW,CAIjB;gBAE2B,IAAI,EAAE,aAAa;IAEhD,OAAO,CAAC,uBAAuB;IAK/B,OAAO,CAAC,8BAA8B;IAOtC,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,2BAA2B;IAUnC,cAAc,IAAI;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B;IAID,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA+GhC,OAAO,CAAC,iBAAiB;IAMzB,OAAO,IAAI,IAAI;IA8Bf,OAAO,CAAC,iBAAiB;IAyJzB,OAAO,CAAC,8BAA8B;IA0GtC,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,6BAA6B;YAiBvB,4BAA4B;YA6I5B,mBAAmB;IAgJjC,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,WAAW;CAyBpB"}
@@ -425,6 +425,7 @@ export class WebSocketManager {
425
425
  const contentContext = this.deps.getContentContext();
426
426
  const previewInvalidationPrefixes = this.getPreviewInvalidationPrefixes(contentContext);
427
427
  const previewInvalidationVersion = this.previewInvalidationVersion;
428
+ let preparedStyleArtifact;
428
429
  let succeeded = false;
429
430
  try {
430
431
  logger.debug("Performing selective invalidation", {
@@ -481,10 +482,11 @@ export class WebSocketManager {
481
482
  const cacheKey = buildFileListCacheKey(contentContext);
482
483
  await this.deps.setFileListCache(cacheKey, files);
483
484
  this.deps.clearFileListIndex();
484
- await this.deps.pregenerateStyles?.(files);
485
+ preparedStyleArtifact = await this.deps.pregenerateStyles?.(files);
485
486
  logger.debug("Fresh files cached (memory + Redis)", {
486
487
  cacheKey,
487
488
  fileCount: files.length,
489
+ styleAssetPath: preparedStyleArtifact?.assetPath,
488
490
  });
489
491
  }
490
492
  catch (error) {
@@ -509,6 +511,8 @@ export class WebSocketManager {
509
511
  environment,
510
512
  branch: contentContext?.branch ?? null,
511
513
  releaseId: contentContext?.releaseId ?? null,
514
+ styleArtifactHash: preparedStyleArtifact?.hash,
515
+ styleAssetPath: preparedStyleArtifact?.assetPath,
512
516
  };
513
517
  this.deps.invalidationCallbacks.triggerReload?.(changedPaths, projectContext);
514
518
  logger.info("Selective invalidation complete - HMR triggered", {
@@ -530,6 +534,7 @@ export class WebSocketManager {
530
534
  const contentContext = this.deps.getContentContext();
531
535
  const previewInvalidationPrefixes = this.getPreviewInvalidationPrefixes(contentContext);
532
536
  const previewInvalidationVersion = this.previewInvalidationVersion;
537
+ let preparedStyleArtifact;
533
538
  let succeeded = false;
534
539
  try {
535
540
  logger.debug("CACHE INVALIDATION STARTED - clearing all caches");
@@ -587,10 +592,11 @@ export class WebSocketManager {
587
592
  const cacheKey = buildFileListCacheKey(contentContext);
588
593
  await this.deps.setFileListCache(cacheKey, files);
589
594
  this.deps.clearFileListIndex();
590
- await this.deps.pregenerateStyles?.(files);
595
+ preparedStyleArtifact = await this.deps.pregenerateStyles?.(files);
591
596
  logger.debug("FRESH FILES FETCHED", {
592
597
  cacheKey,
593
598
  fileCount: files.length,
599
+ styleAssetPath: preparedStyleArtifact?.assetPath,
594
600
  });
595
601
  }
596
602
  catch (error) {
@@ -612,6 +618,8 @@ export class WebSocketManager {
612
618
  environment,
613
619
  branch: contentContext?.branch ?? null,
614
620
  releaseId: contentContext?.releaseId ?? null,
621
+ styleArtifactHash: preparedStyleArtifact?.hash,
622
+ styleAssetPath: preparedStyleArtifact?.assetPath,
615
623
  };
616
624
  this.deps.invalidationCallbacks.triggerReload?.(undefined, projectContext);
617
625
  logger.debug("CACHE INVALIDATION COMPLETE", {
@@ -1 +1 @@
1
- {"version":3,"file":"hmr-scripts.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/dev/scripts/hmr-scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmUH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
1
+ {"version":3,"file":"hmr-scripts.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/dev/scripts/hmr-scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA6ZH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -45,11 +45,93 @@ function getUpdateJSFunction(logPrefix) {
45
45
  return false;
46
46
  }
47
47
 
48
+ async function swapTailwindStylesheet(nextHref) {
49
+ const current = document.getElementById('vf-tailwind-css');
50
+ if (!(current instanceof HTMLLinkElement) || !nextHref || !current.parentNode) {
51
+ return false;
52
+ }
53
+
54
+ const nextUrl = new URL(nextHref, window.location.origin).toString();
55
+ const currentHref = current.getAttribute('href');
56
+ const currentUrl = currentHref ? new URL(currentHref, window.location.href).toString() : '';
57
+ if (currentUrl === nextUrl) {
58
+ return true;
59
+ }
60
+
61
+ const pending = current.cloneNode(false);
62
+ if (!(pending instanceof HTMLLinkElement)) {
63
+ return false;
64
+ }
65
+
66
+ pending.removeAttribute('id');
67
+ pending.setAttribute('data-vf-tailwind-pending', 'true');
68
+ pending.href = nextHref;
69
+
70
+ await new Promise((resolve, reject) => {
71
+ const timeoutId = window.setTimeout(() => {
72
+ cleanup(new Error('stylesheet-timeout'));
73
+ }, 5000);
74
+
75
+ let settled = false;
76
+
77
+ function cleanup(error) {
78
+ if (settled) return;
79
+ settled = true;
80
+ window.clearTimeout(timeoutId);
81
+ pending.removeEventListener('load', onLoad);
82
+ pending.removeEventListener('error', onError);
83
+
84
+ if (error) {
85
+ pending.remove();
86
+ reject(error);
87
+ return;
88
+ }
89
+
90
+ pending.removeAttribute('data-vf-tailwind-pending');
91
+ pending.id = 'vf-tailwind-css';
92
+ current.remove();
93
+ resolve(true);
94
+ }
95
+
96
+ function onLoad() {
97
+ cleanup(null);
98
+ }
99
+
100
+ function onError() {
101
+ cleanup(new Error('stylesheet-load-failed'));
102
+ }
103
+
104
+ pending.addEventListener('load', onLoad, { once: true });
105
+ pending.addEventListener('error', onError, { once: true });
106
+ current.parentNode.insertBefore(pending, current.nextSibling);
107
+ });
108
+
109
+ return true;
110
+ }
111
+
112
+ async function applyStyleUpdate(changedPath, styleHref) {
113
+ if (styleHref) {
114
+ try {
115
+ const swapped = await swapTailwindStylesheet(styleHref);
116
+ if (swapped) {
117
+ ${logPrefix === "[HMR]"
118
+ ? `console.log('${logPrefix} Swapped stylesheet:', styleHref);`
119
+ : `dlog('${logPrefix} Swapped stylesheet:', styleHref);`}
120
+ return true;
121
+ }
122
+ } catch (error) {
123
+ console.warn('${logPrefix} Failed to swap stylesheet:', error);
124
+ }
125
+ }
126
+
127
+ return refreshStylesheets(changedPath) || refreshStylesheets();
128
+ }
129
+
48
130
  function getRenderPath() {
49
131
  return window.location.pathname + window.location.search + window.location.hash;
50
132
  }
51
133
 
52
- async function updateJS(path) {
134
+ async function updateJS(path, styleHref) {
53
135
  ${logPrefix === "[HMR]"
54
136
  ? `console.log('${logPrefix} Updating JS module:', path);`
55
137
  : `dlog('${logPrefix} Updating JS module:', path);`}
@@ -69,7 +151,7 @@ function getUpdateJSFunction(logPrefix) {
69
151
  }
70
152
 
71
153
  // Refresh Tailwind CSS (new classes may be needed from JS changes)
72
- refreshStylesheets();
154
+ await applyStyleUpdate(path, styleHref);
73
155
 
74
156
  // Re-render the page with fresh modules
75
157
  if (window.__veryfrontRenderPage) {
@@ -253,6 +335,7 @@ function generateHMRClient(opts) {
253
335
 
254
336
  // Debounce updates to prevent flashing from rapid-fire changes
255
337
  let pendingPaths = [];
338
+ let pendingStyleHref = null;
256
339
  let updateDebounceTimer = null;
257
340
  const UPDATE_DEBOUNCE_MS = 150;
258
341
 
@@ -264,7 +347,7 @@ function generateHMRClient(opts) {
264
347
 
265
348
  // CSS changes: hot-swap stylesheet without full page reload
266
349
  if (update.path.endsWith('.css')) {
267
- const didRefresh = refreshStylesheets(update.path) || refreshStylesheets();
350
+ const didRefresh = await applyStyleUpdate(update.path, update.styleHref);
268
351
  if (!didRefresh) {
269
352
  notifyStudioAndReload('css-update-no-stylesheet');
270
353
  return;
@@ -275,12 +358,17 @@ function generateHMRClient(opts) {
275
358
 
276
359
  // Debounce JS updates — batch rapid updates into single re-render
277
360
  pendingPaths.push(update.path);
361
+ if (typeof update.styleHref === 'string') {
362
+ pendingStyleHref = update.styleHref;
363
+ }
278
364
 
279
365
  if (updateDebounceTimer) clearTimeout(updateDebounceTimer);
280
366
 
281
367
  updateDebounceTimer = setTimeout(async () => {
282
368
  const paths = pendingPaths;
369
+ const styleHref = pendingStyleHref;
283
370
  pendingPaths = [];
371
+ pendingStyleHref = null;
284
372
  updateDebounceTimer = null;
285
373
 
286
374
  if (paths.length > 1) {
@@ -288,7 +376,7 @@ function generateHMRClient(opts) {
288
376
  }
289
377
 
290
378
  // Single re-render handles all paths (server propagates timestamps to all imports)
291
- if (paths.length > 0) await updateJS(paths[0]);
379
+ if (paths.length > 0) await updateJS(paths[0], styleHref);
292
380
  }, UPDATE_DEBOUNCE_MS);
293
381
  }
294
382
  ${getUpdateJSFunction(logPrefix)}
@@ -1,3 +1,4 @@
1
+ import type { ReloadProjectInfo } from "../../reload-notifier.js";
1
2
  interface HMRMetrics {
2
3
  broadcastsSent: number;
3
4
  messagesForwarded: number;
@@ -10,7 +11,7 @@ export declare function getMetrics(): {
10
11
  * Broadcast update to all connected HMR clients, optionally filtered by projectSlug.
11
12
  * No server-side debounce here — ReloadNotifier already debounces (300ms).
12
13
  */
13
- export declare function broadcastUpdate(changedPaths?: string[], projectSlug?: string): void;
14
+ export declare function broadcastUpdate(changedPaths?: string[], project?: ReloadProjectInfo): void;
14
15
  export declare function resetMetrics(): void;
15
16
  export {};
16
17
  //# sourceMappingURL=hmr-message-router.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hmr-message-router.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/hmr-message-router.ts"],"names":[],"mappings":"AAKA,UAAU,UAAU;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAQD,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAE7D;AAOD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAyBnF;AAsBD,wBAAgB,YAAY,IAAI,IAAI,CAInC"}
1
+ {"version":3,"file":"hmr-message-router.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/hmr-message-router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAKlE,UAAU,UAAU;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAQD,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAE7D;AAcD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,IAAI,CA2B1F;AAsBD,wBAAgB,YAAY,IAAI,IAAI,CAInC"}
@@ -9,6 +9,14 @@ const metrics = {
9
9
  export function getMetrics() {
10
10
  return { clients: getClientCount(), ...metrics };
11
11
  }
12
+ function buildStyleUpdatePayload(project) {
13
+ const payload = {};
14
+ if (project?.styleAssetPath)
15
+ payload.styleHref = project.styleAssetPath;
16
+ if (project?.styleArtifactHash)
17
+ payload.styleHash = project.styleArtifactHash;
18
+ return payload;
19
+ }
12
20
  function requiresFullReload(path) {
13
21
  const ext = path.split(".").pop()?.toLowerCase();
14
22
  return ext === "mdx" || ext === "md" || path.includes("veryfront.config");
@@ -17,11 +25,12 @@ function requiresFullReload(path) {
17
25
  * Broadcast update to all connected HMR clients, optionally filtered by projectSlug.
18
26
  * No server-side debounce here — ReloadNotifier already debounces (300ms).
19
27
  */
20
- export function broadcastUpdate(changedPaths, projectSlug) {
28
+ export function broadcastUpdate(changedPaths, project) {
21
29
  logger.debug("broadcastUpdate called", {
22
30
  changedPaths,
23
31
  totalClients: getClientCount(),
24
- projectSlug,
32
+ projectSlug: project?.projectSlug,
33
+ styleAssetPath: project?.styleAssetPath,
25
34
  });
26
35
  const timestamp = Date.now();
27
36
  metrics.broadcastsSent++;
@@ -30,13 +39,14 @@ export function broadcastUpdate(changedPaths, projectSlug) {
30
39
  changedPaths.some((path) => requiresFullReload(path));
31
40
  if (needsFullReload) {
32
41
  const message = JSON.stringify({ type: "reload", timestamp });
33
- broadcastMessage(message, projectSlug);
42
+ broadcastMessage(message, project?.projectSlug);
34
43
  metrics.messagesForwarded++;
35
44
  }
36
45
  else {
46
+ const stylePayload = buildStyleUpdatePayload(project);
37
47
  for (const path of changedPaths) {
38
- const message = JSON.stringify({ type: "update", path, timestamp });
39
- broadcastMessage(message, projectSlug);
48
+ const message = JSON.stringify({ type: "update", path, timestamp, ...stylePayload });
49
+ broadcastMessage(message, project?.projectSlug);
40
50
  metrics.messagesForwarded++;
41
51
  }
42
52
  }
@@ -48,7 +48,7 @@ export class HMRHandler extends BaseHandler {
48
48
  });
49
49
  return;
50
50
  }
51
- broadcastUpdate(changedPaths, project?.projectSlug);
51
+ broadcastUpdate(changedPaths, project);
52
52
  });
53
53
  startPingInterval();
54
54
  logger.debug("Initialized - listening for reload events", {
@@ -1,10 +1,12 @@
1
- interface ReloadProjectInfo {
1
+ export interface ReloadProjectInfo {
2
2
  projectSlug?: string;
3
3
  projectId?: string;
4
4
  projectDir?: string;
5
5
  environment?: "preview" | "production";
6
6
  branch?: string | null;
7
7
  releaseId?: string | null;
8
+ styleArtifactHash?: string;
9
+ styleAssetPath?: string;
8
10
  }
9
11
  type ReloadListener = (changedPaths?: string[], project?: ReloadProjectInfo) => void;
10
12
  type InvalidateListener = () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"reload-notifier.d.ts","sourceRoot":"","sources":["../../../src/src/server/reload-notifier.ts"],"names":[],"mappings":"AAKA,UAAU,iBAAiB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,KAAK,cAAc,GAAG,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;AACrF,KAAK,kBAAkB,GAAG,MAAM,IAAI,CAAC;AACrC,KAAK,kBAAkB,GAAG,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAAC;AAIjE,cAAM,kBAAkB;IACtB,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,mBAAmB,CAAiC;IAC5D,OAAO,CAAC,aAAa,CAAsD;IAC3E,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,cAAc,CAAC,CAAoB;IAC3C,OAAO,CAAC,OAAO,CAIb;IAEF,SAAS,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI;IAK/C,mBAAmB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI;IAK7D,aAAa,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI;IAyC1E,OAAO,CAAC,yBAAyB;IAcjC,OAAO,CAAC,eAAe;IAkBvB,gBAAgB,IAAI,MAAM;IAI1B,0BAA0B,IAAI,MAAM;IAIpC,UAAU,IAAI;QACZ,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,yBAAyB,EAAE,MAAM,CAAC;KACnC;IAQD,KAAK,IAAI,IAAI;CAiBd;AAED,eAAO,MAAM,cAAc,oBAA2B,CAAC"}
1
+ {"version":3,"file":"reload-notifier.d.ts","sourceRoot":"","sources":["../../../src/src/server/reload-notifier.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,KAAK,cAAc,GAAG,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;AACrF,KAAK,kBAAkB,GAAG,MAAM,IAAI,CAAC;AACrC,KAAK,kBAAkB,GAAG,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAAC;AAIjE,cAAM,kBAAkB;IACtB,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,mBAAmB,CAAiC;IAC5D,OAAO,CAAC,aAAa,CAAsD;IAC3E,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,cAAc,CAAC,CAAoB;IAC3C,OAAO,CAAC,OAAO,CAIb;IAEF,SAAS,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI;IAK/C,mBAAmB,CAAC,QAAQ,EAAE,kBAAkB,GAAG,MAAM,IAAI;IAK7D,aAAa,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI;IAyC1E,OAAO,CAAC,yBAAyB;IAcjC,OAAO,CAAC,eAAe;IAkBvB,gBAAgB,IAAI,MAAM;IAI1B,0BAA0B,IAAI,MAAM;IAIpC,UAAU,IAAI;QACZ,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,yBAAyB,EAAE,MAAM,CAAC;KACnC;IAQD,KAAK,IAAI,IAAI;CAiBd;AAED,eAAO,MAAM,cAAc,oBAA2B,CAAC"}
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "0.1.93";
1
+ export declare const VERSION = "0.1.95";
2
2
  export declare function normalizeVeryfrontVersion(version: string | undefined): string | undefined;
3
3
  export declare function resolveRuntimeVersion(options?: {
4
4
  veryfrontVersion?: string;
@@ -2,7 +2,7 @@ import denoConfig from "../../deno.js";
2
2
  import { getEnv } from "../platform/compat/process.js";
3
3
  // Keep in sync with deno.json version.
4
4
  // scripts/release.ts updates this constant during releases.
5
- export const VERSION = "0.1.93";
5
+ export const VERSION = "0.1.95";
6
6
  export function normalizeVeryfrontVersion(version) {
7
7
  if (!version)
8
8
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -724,9 +724,9 @@ export class VeryfrontFSAdapter implements FSAdapter {
724
724
  */
725
725
  private async triggerCSSPregeneration(
726
726
  files: Array<{ path: string; content?: string }>,
727
- ): Promise<void> {
727
+ ): Promise<{ hash: string; assetPath: string } | undefined> {
728
728
  try {
729
- const { pregenerateCSSFromFiles, findStylesheetFromFiles } = await import(
729
+ const { buildPreparedCSSArtifactFromFiles, findStylesheetFromFiles } = await import(
730
730
  "../../../../html/styles-builder/css-pregeneration.js"
731
731
  );
732
732
  const { resolveStyleContentVersion } = await import(
@@ -744,7 +744,7 @@ export class VeryfrontFSAdapter implements FSAdapter {
744
744
  logger.debug("Skipping CSS pre-generation without projectDir", {
745
745
  projectSlug: this.projectSlug,
746
746
  });
747
- return;
747
+ return undefined;
748
748
  }
749
749
 
750
750
  try {
@@ -769,7 +769,7 @@ export class VeryfrontFSAdapter implements FSAdapter {
769
769
  environmentName: this.contentContext?.environmentName ?? null,
770
770
  });
771
771
 
772
- await pregenerateCSSFromFiles({
772
+ const result = await buildPreparedCSSArtifactFromFiles({
773
773
  projectSlug: this.projectSlug,
774
774
  projectVersion,
775
775
  projectDir,
@@ -781,11 +781,25 @@ export class VeryfrontFSAdapter implements FSAdapter {
781
781
  environment: "preview",
782
782
  buildMode: "production",
783
783
  });
784
+
785
+ logger.debug("CSS pre-generation complete", {
786
+ projectSlug: this.projectSlug,
787
+ projectVersion,
788
+ cssHash: result.hash,
789
+ candidateCount: result.candidateCount,
790
+ fromCache: result.fromCache,
791
+ });
792
+
793
+ return {
794
+ hash: result.hash,
795
+ assetPath: `/_vf/css/${result.hash}.css`,
796
+ };
784
797
  } catch (error) {
785
798
  logger.warn("CSS pre-generation failed", {
786
799
  projectSlug: this.projectSlug,
787
800
  error: error instanceof Error ? error.message : String(error),
788
801
  });
802
+ return undefined;
789
803
  }
790
804
  }
791
805
  }
@@ -120,6 +120,8 @@ export interface InvalidationProjectContext {
120
120
  environment?: "preview" | "production";
121
121
  branch?: string | null;
122
122
  releaseId?: string | null;
123
+ styleArtifactHash?: string;
124
+ styleAssetPath?: string;
123
125
  }
124
126
 
125
127
  export interface InvalidationCallbacks {
@@ -26,6 +26,11 @@ const WS_RECONNECT_MAX_FAILURES = 10;
26
26
  const WS_HEARTBEAT_INTERVAL_MS = 60000;
27
27
  const WS_HEARTBEAT_TIMEOUT_MS = 300000;
28
28
 
29
+ interface PreviewStyleArtifactInfo {
30
+ hash: string;
31
+ assetPath: string;
32
+ }
33
+
29
34
  interface WebSocketDeps {
30
35
  apiBaseUrl: string;
31
36
  apiToken: string;
@@ -43,7 +48,9 @@ interface WebSocketDeps {
43
48
  cacheKey: string,
44
49
  files: Array<{ path: string; content?: string }>,
45
50
  ) => Promise<void>;
46
- pregenerateStyles?: (files: Array<{ path: string; content?: string }>) => Promise<void>;
51
+ pregenerateStyles?: (
52
+ files: Array<{ path: string; content?: string }>,
53
+ ) => Promise<PreviewStyleArtifactInfo | undefined>;
47
54
  }
48
55
 
49
56
  export class WebSocketManager {
@@ -557,6 +564,7 @@ export class WebSocketManager {
557
564
  const contentContext = this.deps.getContentContext();
558
565
  const previewInvalidationPrefixes = this.getPreviewInvalidationPrefixes(contentContext);
559
566
  const previewInvalidationVersion = this.previewInvalidationVersion;
567
+ let preparedStyleArtifact: PreviewStyleArtifactInfo | undefined;
560
568
  let succeeded = false;
561
569
 
562
570
  try {
@@ -630,11 +638,12 @@ export class WebSocketManager {
630
638
  const cacheKey = buildFileListCacheKey(contentContext);
631
639
  await this.deps.setFileListCache(cacheKey, files);
632
640
  this.deps.clearFileListIndex();
633
- await this.deps.pregenerateStyles?.(files);
641
+ preparedStyleArtifact = await this.deps.pregenerateStyles?.(files);
634
642
 
635
643
  logger.debug("Fresh files cached (memory + Redis)", {
636
644
  cacheKey,
637
645
  fileCount: files.length,
646
+ styleAssetPath: preparedStyleArtifact?.assetPath,
638
647
  });
639
648
  } catch (error) {
640
649
  logger.warn("Failed to fetch files during selective invalidation", {
@@ -664,6 +673,8 @@ export class WebSocketManager {
664
673
  environment,
665
674
  branch: contentContext?.branch ?? null,
666
675
  releaseId: contentContext?.releaseId ?? null,
676
+ styleArtifactHash: preparedStyleArtifact?.hash,
677
+ styleAssetPath: preparedStyleArtifact?.assetPath,
667
678
  };
668
679
 
669
680
  this.deps.invalidationCallbacks.triggerReload?.(changedPaths, projectContext);
@@ -691,6 +702,7 @@ export class WebSocketManager {
691
702
  const contentContext = this.deps.getContentContext();
692
703
  const previewInvalidationPrefixes = this.getPreviewInvalidationPrefixes(contentContext);
693
704
  const previewInvalidationVersion = this.previewInvalidationVersion;
705
+ let preparedStyleArtifact: PreviewStyleArtifactInfo | undefined;
694
706
  let succeeded = false;
695
707
 
696
708
  try {
@@ -773,11 +785,12 @@ export class WebSocketManager {
773
785
  const cacheKey = buildFileListCacheKey(contentContext);
774
786
  await this.deps.setFileListCache(cacheKey, files);
775
787
  this.deps.clearFileListIndex();
776
- await this.deps.pregenerateStyles?.(files);
788
+ preparedStyleArtifact = await this.deps.pregenerateStyles?.(files);
777
789
 
778
790
  logger.debug("FRESH FILES FETCHED", {
779
791
  cacheKey,
780
792
  fileCount: files.length,
793
+ styleAssetPath: preparedStyleArtifact?.assetPath,
781
794
  });
782
795
  } catch (error) {
783
796
  logger.warn("Failed to fetch files during invalidation", { error });
@@ -801,6 +814,8 @@ export class WebSocketManager {
801
814
  environment,
802
815
  branch: contentContext?.branch ?? null,
803
816
  releaseId: contentContext?.releaseId ?? null,
817
+ styleArtifactHash: preparedStyleArtifact?.hash,
818
+ styleAssetPath: preparedStyleArtifact?.assetPath,
804
819
  };
805
820
 
806
821
  this.deps.invalidationCallbacks.triggerReload?.(undefined, projectContext);
@@ -57,11 +57,95 @@ function getUpdateJSFunction(logPrefix: string): string {
57
57
  return false;
58
58
  }
59
59
 
60
+ async function swapTailwindStylesheet(nextHref) {
61
+ const current = document.getElementById('vf-tailwind-css');
62
+ if (!(current instanceof HTMLLinkElement) || !nextHref || !current.parentNode) {
63
+ return false;
64
+ }
65
+
66
+ const nextUrl = new URL(nextHref, window.location.origin).toString();
67
+ const currentHref = current.getAttribute('href');
68
+ const currentUrl = currentHref ? new URL(currentHref, window.location.href).toString() : '';
69
+ if (currentUrl === nextUrl) {
70
+ return true;
71
+ }
72
+
73
+ const pending = current.cloneNode(false);
74
+ if (!(pending instanceof HTMLLinkElement)) {
75
+ return false;
76
+ }
77
+
78
+ pending.removeAttribute('id');
79
+ pending.setAttribute('data-vf-tailwind-pending', 'true');
80
+ pending.href = nextHref;
81
+
82
+ await new Promise((resolve, reject) => {
83
+ const timeoutId = window.setTimeout(() => {
84
+ cleanup(new Error('stylesheet-timeout'));
85
+ }, 5000);
86
+
87
+ let settled = false;
88
+
89
+ function cleanup(error) {
90
+ if (settled) return;
91
+ settled = true;
92
+ window.clearTimeout(timeoutId);
93
+ pending.removeEventListener('load', onLoad);
94
+ pending.removeEventListener('error', onError);
95
+
96
+ if (error) {
97
+ pending.remove();
98
+ reject(error);
99
+ return;
100
+ }
101
+
102
+ pending.removeAttribute('data-vf-tailwind-pending');
103
+ pending.id = 'vf-tailwind-css';
104
+ current.remove();
105
+ resolve(true);
106
+ }
107
+
108
+ function onLoad() {
109
+ cleanup(null);
110
+ }
111
+
112
+ function onError() {
113
+ cleanup(new Error('stylesheet-load-failed'));
114
+ }
115
+
116
+ pending.addEventListener('load', onLoad, { once: true });
117
+ pending.addEventListener('error', onError, { once: true });
118
+ current.parentNode.insertBefore(pending, current.nextSibling);
119
+ });
120
+
121
+ return true;
122
+ }
123
+
124
+ async function applyStyleUpdate(changedPath, styleHref) {
125
+ if (styleHref) {
126
+ try {
127
+ const swapped = await swapTailwindStylesheet(styleHref);
128
+ if (swapped) {
129
+ ${
130
+ logPrefix === "[HMR]"
131
+ ? `console.log('${logPrefix} Swapped stylesheet:', styleHref);`
132
+ : `dlog('${logPrefix} Swapped stylesheet:', styleHref);`
133
+ }
134
+ return true;
135
+ }
136
+ } catch (error) {
137
+ console.warn('${logPrefix} Failed to swap stylesheet:', error);
138
+ }
139
+ }
140
+
141
+ return refreshStylesheets(changedPath) || refreshStylesheets();
142
+ }
143
+
60
144
  function getRenderPath() {
61
145
  return window.location.pathname + window.location.search + window.location.hash;
62
146
  }
63
147
 
64
- async function updateJS(path) {
148
+ async function updateJS(path, styleHref) {
65
149
  ${
66
150
  logPrefix === "[HMR]"
67
151
  ? `console.log('${logPrefix} Updating JS module:', path);`
@@ -83,7 +167,7 @@ function getUpdateJSFunction(logPrefix: string): string {
83
167
  }
84
168
 
85
169
  // Refresh Tailwind CSS (new classes may be needed from JS changes)
86
- refreshStylesheets();
170
+ await applyStyleUpdate(path, styleHref);
87
171
 
88
172
  // Re-render the page with fresh modules
89
173
  if (window.__veryfrontRenderPage) {
@@ -271,6 +355,7 @@ function generateHMRClient(opts: HMRScriptOptions): string {
271
355
 
272
356
  // Debounce updates to prevent flashing from rapid-fire changes
273
357
  let pendingPaths = [];
358
+ let pendingStyleHref = null;
274
359
  let updateDebounceTimer = null;
275
360
  const UPDATE_DEBOUNCE_MS = 150;
276
361
 
@@ -282,7 +367,7 @@ function generateHMRClient(opts: HMRScriptOptions): string {
282
367
 
283
368
  // CSS changes: hot-swap stylesheet without full page reload
284
369
  if (update.path.endsWith('.css')) {
285
- const didRefresh = refreshStylesheets(update.path) || refreshStylesheets();
370
+ const didRefresh = await applyStyleUpdate(update.path, update.styleHref);
286
371
  if (!didRefresh) {
287
372
  notifyStudioAndReload('css-update-no-stylesheet');
288
373
  return;
@@ -293,12 +378,17 @@ function generateHMRClient(opts: HMRScriptOptions): string {
293
378
 
294
379
  // Debounce JS updates — batch rapid updates into single re-render
295
380
  pendingPaths.push(update.path);
381
+ if (typeof update.styleHref === 'string') {
382
+ pendingStyleHref = update.styleHref;
383
+ }
296
384
 
297
385
  if (updateDebounceTimer) clearTimeout(updateDebounceTimer);
298
386
 
299
387
  updateDebounceTimer = setTimeout(async () => {
300
388
  const paths = pendingPaths;
389
+ const styleHref = pendingStyleHref;
301
390
  pendingPaths = [];
391
+ pendingStyleHref = null;
302
392
  updateDebounceTimer = null;
303
393
 
304
394
  if (paths.length > 1) {
@@ -306,7 +396,7 @@ function generateHMRClient(opts: HMRScriptOptions): string {
306
396
  }
307
397
 
308
398
  // Single re-render handles all paths (server propagates timestamps to all imports)
309
- if (paths.length > 0) await updateJS(paths[0]);
399
+ if (paths.length > 0) await updateJS(paths[0], styleHref);
310
400
  }, UPDATE_DEBOUNCE_MS);
311
401
  }
312
402
  ${getUpdateJSFunction(logPrefix)}
@@ -1,4 +1,5 @@
1
1
  import { serverLogger } from "../../../utils/index.js";
2
+ import type { ReloadProjectInfo } from "../../reload-notifier.js";
2
3
  import { getClientCount, getOpenSockets } from "./hmr-client-manager.js";
3
4
 
4
5
  const logger = serverLogger.component("hmr-handler");
@@ -19,6 +20,13 @@ export function getMetrics(): { clients: number } & HMRMetrics {
19
20
  return { clients: getClientCount(), ...metrics };
20
21
  }
21
22
 
23
+ function buildStyleUpdatePayload(project?: ReloadProjectInfo): Record<string, string> {
24
+ const payload: Record<string, string> = {};
25
+ if (project?.styleAssetPath) payload.styleHref = project.styleAssetPath;
26
+ if (project?.styleArtifactHash) payload.styleHash = project.styleArtifactHash;
27
+ return payload;
28
+ }
29
+
22
30
  function requiresFullReload(path: string): boolean {
23
31
  const ext = path.split(".").pop()?.toLowerCase();
24
32
  return ext === "mdx" || ext === "md" || path.includes("veryfront.config");
@@ -28,11 +36,12 @@ function requiresFullReload(path: string): boolean {
28
36
  * Broadcast update to all connected HMR clients, optionally filtered by projectSlug.
29
37
  * No server-side debounce here — ReloadNotifier already debounces (300ms).
30
38
  */
31
- export function broadcastUpdate(changedPaths?: string[], projectSlug?: string): void {
39
+ export function broadcastUpdate(changedPaths?: string[], project?: ReloadProjectInfo): void {
32
40
  logger.debug("broadcastUpdate called", {
33
41
  changedPaths,
34
42
  totalClients: getClientCount(),
35
- projectSlug,
43
+ projectSlug: project?.projectSlug,
44
+ styleAssetPath: project?.styleAssetPath,
36
45
  });
37
46
 
38
47
  const timestamp = Date.now();
@@ -44,12 +53,13 @@ export function broadcastUpdate(changedPaths?: string[], projectSlug?: string):
44
53
 
45
54
  if (needsFullReload) {
46
55
  const message = JSON.stringify({ type: "reload", timestamp });
47
- broadcastMessage(message, projectSlug);
56
+ broadcastMessage(message, project?.projectSlug);
48
57
  metrics.messagesForwarded++;
49
58
  } else {
59
+ const stylePayload = buildStyleUpdatePayload(project);
50
60
  for (const path of changedPaths) {
51
- const message = JSON.stringify({ type: "update", path, timestamp });
52
- broadcastMessage(message, projectSlug);
61
+ const message = JSON.stringify({ type: "update", path, timestamp, ...stylePayload });
62
+ broadcastMessage(message, project?.projectSlug);
53
63
  metrics.messagesForwarded++;
54
64
  }
55
65
  }
@@ -78,7 +78,7 @@ export class HMRHandler extends BaseHandler {
78
78
  return;
79
79
  }
80
80
 
81
- broadcastUpdate(changedPaths, project?.projectSlug);
81
+ broadcastUpdate(changedPaths, project);
82
82
  });
83
83
 
84
84
  startPingInterval();
@@ -3,13 +3,15 @@ import { serverLogger } from "../utils/index.js";
3
3
 
4
4
  const logger = serverLogger.component("reload-notifier");
5
5
 
6
- interface ReloadProjectInfo {
6
+ export interface ReloadProjectInfo {
7
7
  projectSlug?: string;
8
8
  projectId?: string;
9
9
  projectDir?: string;
10
10
  environment?: "preview" | "production";
11
11
  branch?: string | null;
12
12
  releaseId?: string | null;
13
+ styleArtifactHash?: string;
14
+ styleAssetPath?: string;
13
15
  }
14
16
 
15
17
  type ReloadListener = (changedPaths?: string[], project?: ReloadProjectInfo) => void;
@@ -3,7 +3,7 @@ import { getEnv } from "../platform/compat/process.js";
3
3
 
4
4
  // Keep in sync with deno.json version.
5
5
  // scripts/release.ts updates this constant during releases.
6
- export const VERSION = "0.1.93";
6
+ export const VERSION = "0.1.95";
7
7
 
8
8
  export function normalizeVeryfrontVersion(version: string | undefined): string | undefined {
9
9
  if (!version) return undefined;