Booking.com · VS Code Extension
Render .inc and .tmpl affiliate templates locally inside VS Code — with real mock variables, injected page bundles, multi-language support, and AI-assisted mock generation. No server, no deployment.
1 · Install the extension
Search for TMPL Preview in the VS Code Extensions panel (publisher: saabbas) and click Install.
2 · Open a template
Open any .inc or .tmpl file from affiliate_data, then run TMPL: Open Preview to the Side from the command palette (⌘⇧P).
3 · Configure code root (optional but recommended)
Open the TMPL Preview settings panel (gear icon in the sidebar) and set Code root to your ~/git_tree folder. Then tick the repos to search — this unlocks role detection and AI-assisted mocks.
A full rendering pipeline — in your editor, offline.
Tokenizes and evaluates TMPL_VAR, TMPL_IF, TMPL_LOOP, TMPL_FOR, TMPL_CASE, TMPL_WITH, tilde-trim, and more — the full BHC dialect your templates actually use.
Walks template_specific_stylesheets.inc → resolves .concat.css bundles → renders TMPL inside CSS → injects BUI tokens as --bui_color_* variables. What you see matches production styling.
Three-tab panel: Values (variables, loops, functions), Translations, Assets. Edit any value and the preview re-renders live. Values persist per-file in .tmpl-preview/.
Click Fill with AI — the extension sends the template + its action file + any test fixtures to Claude and populates realistic values. Scope-aware: loop-local variables go into the right loop, not the root.
Heuristically detects the role (book, mesgen, extranet, app). For .inc fragments, shows which parent templates include it and lets you pick the render context.
Switch between en-gb, de, ja, ar, and 41 other locales. Translation cache reloads instantly; missing keys render as humanised fallbacks instead of raw [[key_name]] noise.
How was your stay at
Test Hotel
4 nights Amsterdam
Jan 09 — Jan 11
How was your stay at Test Hotel?
Preview renders the full template with mock values. The sidebar shows all variables, their current values, and flags anything missing.
Banners appear above the preview for unresolved includes, empty output, script load failures, and missing variables. Nothing is silent.
Click Fill with AI next to any missing variable cluster and Claude generates contextually accurate values — hotel names, dates, URLs — matching the template's role and structure.
No API key? Click Import from test to pull values from a .t test file in the handler repo. Often more accurate than AI for state-heavy pages.
Gear icon in the TMPL Preview sidebar header — everything in one place, no settings.json hunting.
Integration
Code root
Parent folder containing your repos (e.g. ~/git_tree). Sub-directories appear as searchable repos.
Repositories to search
Pill multi-select. Toggle which repos feed role detection and AI mock generation.
Role segment depth
How many path segments below the repo root form the role label. Default: 1.
AI Assistance
Use Claude CLI as fallback
When role/parent detection fails, asks your local claude CLI. Off by default — prompts and results stay local.
Allowed actions
Granular opt-in: find role · suggest mock values · describe template. Each is independently toggleable.
Preview Defaults
Auto-inject sibling .css / .js
Master toggle. Per-role override table lets you e.g. enable CSS but skip JS for mesgen.
Translation language
45-locale dropdown. Change applies on next render; translation cache is per-language.
Static URL prefix (CDN)
Prefix for resolving CDN URLs in the rendered output. Default: https://t-cf.bstatic.com.
.inc or .tmpl file from affiliate_data with full CSS/JS injection
TMPL_VAR, TMPL_IF/UNLESS, TMPL_LOOP, TMPL_FOR, TMPL_CASE/WHEN, TMPL_WITH, TMPL_SETVAR, TMPL_INLINE
.concat.css) including BUI design tokens
.t files) — no API key needed
.inc under any of its parent templates' CSS/JS context
file:// paths (macOS)
TMPL_FRAGMENT, complex action-supplied vars, and locale-aware translation require the real Perl engine (Perl bridge scaffolded, not yet wired).
b_action branches (iPhone, RTL, mlt, cancellation_tpi…) are NOT auto-injected. Toggle them manually in the Assets tab.
ugcc_review_form_header__property_name shows as "Property name" — readable but not the real translated string.
libs: vendor paths unresolved. Files like libs:bui/9.9.8/… aren't vendored in affiliate_data — 3 bundles show a small gap in low-level BUI base styles.
What's shipping next — roughly in order.
Perl bridge — real BHC rendering
Option-B Bazel bridge (render.pl + bridge.ts) scaffolded, awaiting wiring into the extension. Will add a Re-render with Perl button for 100%-faithful output.
Authoritative role detection (workstream 1)
Async repo-grep that searches codeRoot repos for the template basename in handler files. Settings UI is done; the grep + role-map cache backend is the remaining work.
Dev-menu in browser view (workstream 6)
Floating overlay in the exported HTML: edit mock variables, hit Apply, preview re-renders in the browser without going back to VS Code. Local HTTP server + poll-based refresh.
Patch-protocol sidebar updates
Diff-based DOM updates instead of full HTML replacement. Eliminates the flash on fast typing in the variable inputs.
The preview looks unstyled. What's wrong?
Check that Code root and at least one repo (usually affiliate_data) are configured in Settings. The bundle discovery pipeline needs to locate affiliates/bookings2/…concat.css. Watch View → Output → TMPL Preview for discovery logs.
Variables I set in the sidebar aren't changing the preview.
The variable may be a loop-local rather than a root variable. Check the scope chip next to the input — if it says loop: b_xyz, the value lives inside the loop array. Make sure the loop has at least one item in it (the Values tab shows loop arrays as expandable rows).
The AI mock generation is empty / refuses to run.
Set your Anthropic API key via the command palette: TMPL: Set API Key. Key is stored in VS Code's secure secret storage, never in settings files. Alternatively use Import from test — it pulls values directly from .t test files with no API key required.
Can I use this for non-affiliate_data templates?
Yes, but CSS bundle discovery is tuned to the affiliates/bookings2/ structure. Standalone templates (no include chain) will render immediately; the bundle injection just won't find anything to inject.
Why does my template show untranslated keys like "Num nights city"?
That's the humanised fallback for a translation key the extension can't resolve. Real translations come from _translations.json — if that file isn't present in the workspace, keys are displayed as readable human text instead of raw [[key_name]] noise.
The role pill says "role unknown". How do I fix it?
Click the role pill and pick from the QuickPick — the manual override persists per-file. The heuristic covers most files but may mis-classify templates that don't follow naming conventions. Authoritative repo-grep backend is coming (workstream 1).