diff --git a/themes/bonsai/exampleSite/hugo.toml b/themes/bonsai/exampleSite/hugo.toml
index 07eb530..09b75f7 100644
--- a/themes/bonsai/exampleSite/hugo.toml
+++ b/themes/bonsai/exampleSite/hugo.toml
@@ -7,6 +7,29 @@ theme = "bonsai"
# v0.4 demo (set params.rss = true and remove "RSS" from disableKinds).
disableKinds = ["taxonomy", "term", "sitemap", "404"]
+# Register VCard + Manifest output formats so layouts/_default/vcard.vcf and
+# layouts/_default/manifest.webmanifest get rendered when their params are on.
+[mediaTypes."text/vcard"]
+ suffixes = ["vcf"]
+
+[mediaTypes."application/manifest+json"]
+ suffixes = ["webmanifest"]
+
+[outputs]
+ home = ["HTML", "RSS", "Manifest"]
+
+[outputFormats.VCard]
+ mediaType = "text/vcard"
+ baseName = "vcard"
+ isPlainText = true
+ notAlternative = true
+
+[outputFormats.Manifest]
+ mediaType = "application/manifest+json"
+ baseName = "manifest"
+ isPlainText = true
+ notAlternative = true
+
[params]
name = "Tien Nguyen"
tagline = "Software engineer · tending small things with care"
@@ -21,6 +44,40 @@ disableKinds = ["taxonomy", "term", "sitemap", "404"]
footerText = "© 2026 · made with bonsai"
# ogImageUrl = "/og.png" # optional 1200×630 image for social previews
+ # Phase 1 (v0.5) opt-ins:
+ themeColor = "#c93f63" # matches the sakura palette accent; tints mobile browser chrome
+ # robots = "index,follow" # default; set "noindex,nofollow" to hide from search engines
+ # preloadAvatar = true # default true; preloads params.avatar as LCP image (local paths only)
+
+ # Phase 6 (v0.5) opt-ins:
+ schemaWebSite = true # emit secondary WebSite JSON-LD for richer search results
+ manifest = true # serve /manifest.webmanifest + emit
+ # themeBackground = "#fff5f5" # PWA splash background; defaults to a sensible neutral
+
+ # Phase 3 (v0.5) page-level opt-ins:
+ share = true # render share button (Web Share API + clipboard fallback)
+ qr = true # render collapsible QR code of this page Permalink
+ # vcard = true # serve /vcard.vcf and render a "Save contact" link
+
+ # Phase 4 (v0.5) opt-in click analytics — Google Analytics 4.
+ # GA4 sets cookies — GDPR/PECR/CPRA consent is the site operator's responsibility.
+ # See docs/deployment-guide.md for the consent caveat.
+ # [params.analytics]
+ # measurementId = "G-XXXXXXXXXX"
+ # trackClicks = true # auto-emit data-analytics-event="link:" per link
+ # utmSource = "bio"
+ # utmMedium = "bio"
+ # # utmCampaign = "summer-launch"
+
+# Register VCard output format on home page (only needed when vcard = true)
+# [outputs]
+# home = ["HTML", "RSS", "VCard"]
+# [outputFormats.VCard]
+# mediaType = "text/vcard"
+# baseName = "vcard"
+# isPlainText = true
+# notAlternative = true
+
[[params.links]]
title = "GitHub"
url = "https://github.com/tiennm99"
diff --git a/themes/bonsai/exampleSite/static/_headers b/themes/bonsai/exampleSite/static/_headers
new file mode 100644
index 0000000..b5f1502
--- /dev/null
+++ b/themes/bonsai/exampleSite/static/_headers
@@ -0,0 +1,24 @@
+/*
+ X-Content-Type-Options: nosniff
+ X-Frame-Options: SAMEORIGIN
+ Referrer-Policy: strict-origin-when-cross-origin
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
+ Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self' https://www.google-analytics.com https://*.analytics.google.com https://*.google-analytics.com https://*.googletagmanager.com; font-src 'self'; frame-ancestors 'self'
+
+/css/*
+ Cache-Control: public, max-age=31536000, immutable
+
+/js/*
+ Cache-Control: public, max-age=31536000, immutable
+
+/icons/*
+ Cache-Control: public, max-age=31536000, immutable
+
+/images/*
+ Cache-Control: public, max-age=31536000, immutable
+
+/index.html
+ Cache-Control: public, max-age=3600, must-revalidate
+
+/
+ Cache-Control: public, max-age=3600, must-revalidate
diff --git a/themes/bonsai/exampleSite/vercel.json b/themes/bonsai/exampleSite/vercel.json
new file mode 100644
index 0000000..6142740
--- /dev/null
+++ b/themes/bonsai/exampleSite/vercel.json
@@ -0,0 +1,33 @@
+{
+ "$schema": "https://openapi.vercel.sh/vercel.json",
+ "cleanUrls": true,
+ "trailingSlash": false,
+ "headers": [
+ {
+ "source": "/(.*)",
+ "headers": [
+ { "key": "X-Content-Type-Options", "value": "nosniff" },
+ { "key": "X-Frame-Options", "value": "SAMEORIGIN" },
+ { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
+ { "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" },
+ { "key": "Content-Security-Policy", "value": "default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self' https://www.google-analytics.com https://*.analytics.google.com https://*.google-analytics.com https://*.googletagmanager.com; font-src 'self'; frame-ancestors 'self'" }
+ ]
+ },
+ {
+ "source": "/css/(.*)",
+ "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
+ },
+ {
+ "source": "/js/(.*)",
+ "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
+ },
+ {
+ "source": "/icons/(.*)",
+ "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
+ },
+ {
+ "source": "/images/(.*)",
+ "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
+ }
+ ]
+}