feat(exampleSite): showcase v0.5 opt-ins + ship deploy templates

Updates exampleSite hugo.toml with v0.5 parameters for multi-section bio,
QR code, vCard, share button, analytics, and OG image generation.
Includes Vercel and Netlify deployment configuration templates.

Enables one-click deployment for new users.
This commit is contained in:
tiennm99 committed 2026-05-15 19:51:18 +07:00
1 parent 4c75ce93fd
commit 7cd9833860
3 files changed
+114

No files matched your search

+57
View File
@@ -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 <link rel="manifest">
# 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:<slug>" 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"
+24
View File
@@ -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
+33
View File
@@ -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" }]
}
]
}