From 8e5d98e87f48a1eaef1c69b142df93cefe96669a Mon Sep 17 00:00:00 2001
From: Martin Trapp <94928215+martrapp@users.noreply.github.com>
Date: Thu, 19 Feb 2026 15:17:00 +0100
Subject: [PATCH 1/3] Adds tests for transition flag behavior
Improves confidence in transform metadata by validating how transition and head propagation flags are derived across key directive combinations.
Prevents regressions by confirming that only actual transition directives enable transition handling, while defer-only rendering still preserves head propagation.
---
internal/transform/transform_test.go | 48 ++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/internal/transform/transform_test.go b/internal/transform/transform_test.go
index 91885ec05..d4df35362 100644
--- a/internal/transform/transform_test.go
+++ b/internal/transform/transform_test.go
@@ -314,6 +314,54 @@ func TestFullTransform(t *testing.T) {
}
}
+func TestTransformTransitionAndHeadPropagationFlags(t *testing.T) {
+ tests := []struct {
+ name string
+ source string
+ wantTransition bool
+ wantHeadPropagation bool
+ }{
+ {
+ name: "server:defer only",
+ source: ``,
+ wantTransition: false,
+ wantHeadPropagation: true,
+ },
+ {
+ name: "transition directive",
+ source: `
`,
+ wantTransition: true,
+ wantHeadPropagation: true,
+ },
+ {
+ name: "transition:persist-props alone does not count as transition directive",
+ source: ``,
+ wantTransition: false,
+ wantHeadPropagation: false,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ doc, err := astro.Parse(strings.NewReader(tt.source))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ transformOptions := TransformOptions{}
+ ExtractStyles(doc, &transformOptions)
+ Transform(doc, transformOptions, handler.NewHandler(tt.source, "/test.astro"))
+
+ if doc.Transition != tt.wantTransition {
+ t.Fatalf("unexpected doc.Transition value: want %v, got %v", tt.wantTransition, doc.Transition)
+ }
+ if doc.HeadPropagation != tt.wantHeadPropagation {
+ t.Fatalf("unexpected doc.HeadPropagation value: want %v, got %v", tt.wantHeadPropagation, doc.HeadPropagation)
+ }
+ })
+ }
+}
+
func TestTransformTrailingSpace(t *testing.T) {
tests := []struct {
name string
From c26b0b52d4a854d80bd76ca9356b1eb187cc82f4 Mon Sep 17 00:00:00 2001
From: Martin Trapp <94928215+martrapp@users.noreply.github.com>
Date: Thu, 19 Feb 2026 15:17:47 +0100
Subject: [PATCH 2/3] Separates server:defer from transition detection
Prevents deferred server rendering from being treated as a transition feature.
Keeps head propagation enabled for deferred content, while only transition-specific attributes trigger transition state and related scoping.
---
internal/transform/transform.go | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/internal/transform/transform.go b/internal/transform/transform.go
index af66dd5fe..cd2d01db3 100644
--- a/internal/transform/transform.go
+++ b/internal/transform/transform.go
@@ -51,11 +51,14 @@ func Transform(doc *astro.Node, opts TransformOptions, h *handler.Handler) *astr
if shouldScope {
ScopeElement(n, opts)
}
- if HasAttr(n, TRANSITION_ANIMATE) || HasAttr(n, TRANSITION_NAME) || HasAttr(n, TRANSITION_PERSIST) || HasAttr(n, SERVER_DEFER) {
+ if HasAttr(n, TRANSITION_ANIMATE) || HasAttr(n, TRANSITION_NAME) || HasAttr(n, TRANSITION_PERSIST) {
doc.Transition = true
doc.HeadPropagation = true
getOrCreateTransitionScope(n, &opts, i)
}
+ if HasAttr(n, SERVER_DEFER) {
+ doc.HeadPropagation = true
+ }
if len(definedVars) > 0 {
didAdd := AddDefineVars(n, definedVars)
if !didAddDefinedVars {
From 0012bc89272df1c8a4ca555f1255d29c8e5b94cb Mon Sep 17 00:00:00 2001
From: Martin Trapp <94928215+martrapp@users.noreply.github.com>
Date: Thu, 19 Feb 2026 15:34:21 +0100
Subject: [PATCH 3/3] Adds changeset
---
.changeset/brown-tires-melt.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/brown-tires-melt.md
diff --git a/.changeset/brown-tires-melt.md b/.changeset/brown-tires-melt.md
new file mode 100644
index 000000000..741b573c1
--- /dev/null
+++ b/.changeset/brown-tires-melt.md
@@ -0,0 +1,5 @@
+---
+"@astrojs/compiler": patch
+---
+
+Fixes an issue where `server:defer` was treated like a transition directive, causing ViewTransitions CSS to be included even when no `transition:*` directives were used.