diff --git a/README.md b/README.md
index f43db6a..256fc0f 100644
--- a/README.md
+++ b/README.md
@@ -89,22 +89,29 @@ Mirrors Go's own export convention:
```gastro
---
-ctx := gastro.Context() // lowercase -> private
-err := doSomething() // lowercase -> private
+slug := r.PathValue("slug") // lowercase -> private
+err := doSomething() // lowercase -> private
-Title := "Hello" // Uppercase -> {{ .Title }}
-Items := fetchItems() // Uppercase -> {{ .Items }}
+Title := "Hello" // Uppercase -> {{ .Title }}
+Items := fetchItems() // Uppercase -> {{ .Items }}
---
{{ .Title }}
```
+Frontmatter has ambient `w http.ResponseWriter` and `r *http.Request`.
+The page handler runs for every HTTP method; branch on `r.Method` to
+handle non-GET requests in the same file.
+
### File-Based Routing
-| File | Route |
-|----------------------------|-------------------|
-| `pages/index.gastro` | `GET /` |
-| `pages/about/index.gastro` | `GET /about` |
-| `pages/blog/[slug].gastro` | `GET /blog/{slug}` |
+| File | Route |
+|----------------------------|----------------|
+| `pages/index.gastro` | `/` |
+| `pages/about/index.gastro` | `/about` |
+| `pages/blog/[slug].gastro` | `/blog/{slug}` |
+
+Patterns are method-less; the page handles every method (GET, POST,
+etc.) and branches on `r.Method`.
### Static Assets
diff --git a/docs/architecture.md b/docs/architecture.md
index 1c7771f..5f4903b 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -66,8 +66,10 @@ Three responsibilities, split across files:
Wraps the frontmatter in a valid Go file and parses it with `go/ast`. Extracts:
- All variable declarations (`:=` and `var`)
- Classification: uppercase (exported to template) vs lowercase (private)
-- Detection of `gastro.Context()` calls (marks file as a page)
- Detection of `gastro.Props()` calls (marks file as a component)
+- Marker-rewrite warnings (deprecation of `gastro.Context()`, unknown
+ `gastro.X` symbols) and missing-return findings from
+ `internal/analysis/respwrite.go`
The frontmatter is wrapped in `package __gastro / func __handler() { ... }`
so `go/parser` can handle it. Type declarations (`type Props struct{}`) are
@@ -80,13 +82,33 @@ hoisted to package level since they can't live inside a function body.
Produces Go source code for a page handler or component render function. Uses
`text/template` to emit the generated code. The output includes:
- Package declaration
-- Imports (user's + gastro runtime)
+- Imports (user's + gastro runtime); user paths that overlap the
+ auto-injected set (`net/http`, `log`, `html/template`, `bytes`) are
+ deduped
- Template variable with parsed `html/template`
-- Handler function with frontmatter code, data map, and template execution
-- Panic recovery wrapper
-
-The `gastro.Context()` marker is rewritten to `gastroRuntime.NewContext(w, r)`.
-The `gastro.Props()` marker is stripped (component generation is TODO).
+- Handler function: wraps `w` in `gastroRuntime.NewPageWriter(w)` so
+ body writes are tracked, runs the rewritten frontmatter, and
+ conditionally executes the template only when the body is still
+ uncommitted (Track B)
+- Panic recovery wrapper that consults the wrapped writer to avoid
+ double-writing after a partial response
+
+The consolidated marker rewriter (Track B §4.10) handles the implicit
+`gastro.X` namespace via an allowlist:
+
+| Frontmatter call | Rewritten to |
+|---------------------------|------------------------------------|
+| `gastro.Props()` | `__props` |
+| `gastro.Context()` | `gastroRuntime.NewContext(w, r)` (deprecated; emits warning) |
+| `gastro.From[T](ctx)` | `gastroRuntime.FromContext[T](ctx)` |
+| `gastro.FromOK[T](ctx)` | `gastroRuntime.FromContextOK[T](ctx)` |
+| `gastro.FromContext[T]…` | identity (gastro → gastroRuntime) |
+| `gastro.FromContextOK[T]…`| identity |
+| `gastro.NewSSE(w, r)` | `gastroRuntime.NewSSE(w, r)` |
+| `gastro.Render.X(…)` | `Render.X(…)` |
+
+Anything else under `gastro.X` produces an "unknown gastro runtime
+symbol" warning, keeping the implicit namespace finite.
#### `template.go`
@@ -276,7 +298,7 @@ parser.Parse()
|
v
parser.File {
- Frontmatter: "ctx := gastro.Context()\nTitle := \"Hello\""
+ Frontmatter: "slug := r.PathValue(\"slug\")\nTitle := \"Hello\""
TemplateBody: "{{ .Title }}
"
Imports: ["myapp/db"]
ComponentImports: [{Name: "Card", Path: "components/card.gastro"}]
@@ -287,8 +309,8 @@ parser.File {
| v
| FrontmatterInfo {
| ExportedVars: [{Name: "Title"}]
- | PrivateVars: [{Name: "ctx"}]
- | IsPage: true
+ | PrivateVars: [{Name: "slug"}]
+ | Warnings: [] // Track B marker / missing-return findings
| }
|
+---> codegen.ProcessMarkdownDirectives()
diff --git a/docs/comparison.md b/docs/comparison.md
index 9fa3ffc..1449943 100644
--- a/docs/comparison.md
+++ b/docs/comparison.md
@@ -152,7 +152,7 @@ All five approaches produce a single deployable binary. The differences are in h
| Approach | What You Need to Know | New Concepts |
|----------|----------------------|--------------|
-| **Gastro** | Go + html/template syntax + HTML/CSS | `.gastro` file format, frontmatter conventions, `gastro.Props()` / `gastro.Context()` APIs |
+| **Gastro** | Go + html/template syntax + HTML/CSS | `.gastro` file format, frontmatter conventions, ambient `(w, r)` and `gastro.Props()` |
| **Templ** | Go + the Templ DSL | Templ-specific syntax (looks like Go but is not Go), `@component` calls, `templ` blocks |
| **gomponents** | Go only | The `Node` interface and dot-import pattern. Otherwise it is standard Go. |
| **htmgo** | Go + HTMX attributes | htmgo's element builder API, HTMX concepts (hypermedia-driven), partial rendering |
diff --git a/docs/components.md b/docs/components.md
index 1fad8c2..e686643 100644
--- a/docs/components.md
+++ b/docs/components.md
@@ -55,9 +55,9 @@ import (
PostCard "components/post-card.gastro"
)
-ctx := gastro.Context()
+Title := "Home"
---
-{{ wrap Layout (dict "Title" "Home") }}
+{{ wrap Layout (dict "Title" .Title) }}
{{ PostCard (dict "Title" "My Post" "Slug" "my-post") }}
{{ end }}
```