[{"data":1,"prerenderedAt":5979},["ShallowReactive",2],{"published-article-paths":3,"search-navigation":348,"\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts":421,"\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts-surround":1055},[4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346],{"path":5},"\u002Fde\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":7},"\u002Fde\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":9},"\u002Fde\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":11},"\u002Fde\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":13},"\u002Fde\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":15},"\u002Fde\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":17},"\u002Fde\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":19},"\u002Fde\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":21},"\u002Fde\u002Farticle\u002Fsetup-antigravity-2",{"path":23},"\u002Fde\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":25},"\u002Fde\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":27},"\u002Fde\u002Farticle\u002Fsync-obsidian-across-devices",{"path":29},"\u002Fde\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":31},"\u002Fde\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":33},"\u002Fde\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":35},"\u002Fde\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":37},"\u002Fen\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":39},"\u002Fen\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":41},"\u002Fen\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":43},"\u002Fen\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":45},"\u002Fen\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":47},"\u002Fen\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":49},"\u002Fen\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":51},"\u002Fen\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":53},"\u002Fen\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":55},"\u002Fen\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":57},"\u002Fen\u002Farticle\u002Fsetup-antigravity-2",{"path":59},"\u002Fen\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":61},"\u002Fen\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":63},"\u002Fen\u002Farticle\u002Fsync-obsidian-across-devices",{"path":65},"\u002Fen\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":67},"\u002Fen\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":69},"\u002Fen\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":71},"\u002Fen\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":73},"\u002Fes\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":75},"\u002Fes\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":77},"\u002Fes\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":79},"\u002Fes\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":81},"\u002Fes\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":83},"\u002Fes\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":85},"\u002Fes\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":87},"\u002Fes\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":89},"\u002Fes\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":91},"\u002Fes\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":93},"\u002Fes\u002Farticle\u002Fsetup-antigravity-2",{"path":95},"\u002Fes\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":97},"\u002Fes\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":99},"\u002Fes\u002Farticle\u002Fsync-obsidian-across-devices",{"path":101},"\u002Fes\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":103},"\u002Fes\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":105},"\u002Fes\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":107},"\u002Fes\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":109},"\u002Ffr\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":111},"\u002Ffr\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":113},"\u002Ffr\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":115},"\u002Ffr\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":117},"\u002Ffr\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":119},"\u002Ffr\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":121},"\u002Ffr\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":123},"\u002Ffr\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":125},"\u002Ffr\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":127},"\u002Ffr\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":129},"\u002Ffr\u002Farticle\u002Fsetup-antigravity-2",{"path":131},"\u002Ffr\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":133},"\u002Ffr\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":135},"\u002Ffr\u002Farticle\u002Fsync-obsidian-across-devices",{"path":137},"\u002Ffr\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":139},"\u002Ffr\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":141},"\u002Ffr\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":143},"\u002Ffr\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":145},"\u002Fid\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":147},"\u002Fid\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":149},"\u002Fid\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":151},"\u002Fid\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":153},"\u002Fid\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":155},"\u002Fid\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":157},"\u002Fid\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":159},"\u002Fid\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":161},"\u002Fid\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":163},"\u002Fid\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":165},"\u002Fid\u002Farticle\u002Fsetup-antigravity-2",{"path":167},"\u002Fid\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":169},"\u002Fid\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":171},"\u002Fid\u002Farticle\u002Fsync-obsidian-across-devices",{"path":173},"\u002Fid\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":175},"\u002Fid\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":177},"\u002Fid\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":179},"\u002Fid\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":181},"\u002Fja\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":183},"\u002Fja\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":185},"\u002Fja\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":187},"\u002Fja\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":189},"\u002Fja\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":191},"\u002Fja\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":193},"\u002Fja\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":195},"\u002Fja\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":197},"\u002Fja\u002Farticle\u002Fsetup-antigravity-2",{"path":199},"\u002Fja\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":201},"\u002Fja\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":203},"\u002Fja\u002Farticle\u002Fsync-obsidian-across-devices",{"path":205},"\u002Fja\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":207},"\u002Fja\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":209},"\u002Fja\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":211},"\u002Fja\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":213},"\u002Fpt\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":215},"\u002Fpt\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":217},"\u002Fpt\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":219},"\u002Fpt\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":221},"\u002Fpt\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":223},"\u002Fpt\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":225},"\u002Fpt\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":227},"\u002Fpt\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":229},"\u002Fpt\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":231},"\u002Fpt\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":233},"\u002Fpt\u002Farticle\u002Fsetup-antigravity-2",{"path":235},"\u002Fpt\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":237},"\u002Fpt\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":239},"\u002Fpt\u002Farticle\u002Fsync-obsidian-across-devices",{"path":241},"\u002Fpt\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":243},"\u002Fpt\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":245},"\u002Fpt\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":247},"\u002Fpt\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":249},"\u002Ftw\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":251},"\u002Ftw\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":253},"\u002Ftw\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":255},"\u002Ftw\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":257},"\u002Ftw\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":259},"\u002Ftw\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":261},"\u002Ftw\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":263},"\u002Ftw\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":265},"\u002Ftw\u002Farticle\u002Fsetup-antigravity-2",{"path":267},"\u002Ftw\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":269},"\u002Ftw\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":271},"\u002Ftw\u002Farticle\u002Fsync-obsidian-across-devices",{"path":273},"\u002Ftw\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":275},"\u002Ftw\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":277},"\u002Ftw\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":279},"\u002Ftw\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":281},"\u002Fvi\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":283},"\u002Fvi\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":285},"\u002Fvi\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":287},"\u002Fvi\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":289},"\u002Fvi\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":291},"\u002Fvi\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":293},"\u002Fvi\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":295},"\u002Fvi\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":297},"\u002Fvi\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":299},"\u002Fvi\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":301},"\u002Fvi\u002Farticle\u002Fsetup-antigravity-2",{"path":303},"\u002Fvi\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":305},"\u002Fvi\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":307},"\u002Fvi\u002Farticle\u002Fsync-obsidian-across-devices",{"path":309},"\u002Fvi\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":311},"\u002Fvi\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":313},"\u002Fvi\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":315},"\u002Fvi\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":317},"\u002Fzh\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":319},"\u002Fzh\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":321},"\u002Fzh\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":323},"\u002Fzh\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":325},"\u002Fzh\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":327},"\u002Fzh\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":329},"\u002Fzh\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":331},"\u002Fzh\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":333},"\u002Fzh\u002Farticle\u002Fsetup-antigravity-2",{"path":335},"\u002Fzh\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":337},"\u002Fzh\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":339},"\u002Fzh\u002Farticle\u002Fsync-obsidian-across-devices",{"path":341},"\u002Fzh\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":343},"\u002Fzh\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":345},"\u002Fzh\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":347},"\u002Fzh\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",[349,353,357,361,365,369,373,377,381,385,389,393,397,401,405,409,413,417],{"title":350,"path":351,"stem":352},"AI Agent Skills: What They Are & How to Create Them","\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them","en\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"title":354,"path":355,"stem":356},"Bringing Buzz to DeepSeek Harness: Taught to Speak Nostr","\u002Farticle\u002Fbringing-buzz-to-deepseek-harness","en\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"title":358,"path":359,"stem":360},"Solving AI Agent Skills Fragmentation with npx skills","\u002Farticle\u002Fcentralised-the-skills-for-agents","en\u002Farticle\u002Fcentralised-the-skills-for-agents",{"title":362,"path":363,"stem":364},"How to Expose Hermes Agent Privately with Cloudflare WARP","\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp","en\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"title":366,"path":367,"stem":368},"How AI Agent Skills Replace Nuxt App Scaffolding Scripts","\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts","en\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"title":370,"path":371,"stem":372},"Stop Exposing Your Vault: Secure NodeWarden with Cloudflare","\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare","en\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"title":374,"path":375,"stem":376},"How to Deploy Hermes Agent on a Linux VPS","\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server","en\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"title":378,"path":379,"stem":380},"Self-Host Your Travel Itineraries with TREK and Docker","\u002Farticle\u002Fself-hosted-travel-planner-trek","en\u002Farticle\u002Fself-hosted-travel-planner-trek",{"title":382,"path":383,"stem":384},"Self-Host Block's Buzz: Shared AI Agent Workspace","\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues","en\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"title":386,"path":387,"stem":388},"How to Self-Host a BitWarden Compatible Server Nodewarden","\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare","en\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"title":390,"path":391,"stem":392},"Google Antigravity 2 Hands-On: Setup & First Impressions","\u002Farticle\u002Fsetup-antigravity-2","en\u002Farticle\u002Fsetup-antigravity-2",{"title":394,"path":395,"stem":396},"NetSuite AI Connector Guide: MCP Setup & Use Cases","\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude","en\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"title":398,"path":399,"stem":400},"Switch Between Multiple Cloudflare WARP Orgs on Mac","\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac","en\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"title":402,"path":403,"stem":404},"How to Sync Obsidian Vaults Across Devices Securely","\u002Farticle\u002Fsync-obsidian-across-devices","en\u002Farticle\u002Fsync-obsidian-across-devices",{"title":406,"path":407,"stem":408},"Testing Claude Fable 5: A Financial Analysis Review","\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis","en\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"title":410,"path":411,"stem":412},"Guide to Browser and Scheduler in Antigravity 2","\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2","en\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"title":414,"path":415,"stem":416},"Build a Persistent AI Memory System on Cloudflare","\u002Farticle\u002Fuse-cloudflare-as-ai-memory","en\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"title":418,"path":419,"stem":420},"Antigravity 2 in Action: AI Agents, Skills, and MCP","\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2","en\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"id":422,"title":366,"author":423,"body":424,"category":1033,"date":1035,"description":1036,"extension":1037,"image":1038,"imageAlt":1039,"isPublished":486,"meta":1040,"minRead":490,"navigation":486,"path":45,"seo":1046,"stem":368,"tags":1048,"updatedAt":1053,"__hash__":1054},"article\u002Fen\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts.md","",{"type":425,"value":426,"toc":1026},"minimark",[427,445,450,453,578,581,611,617,621,636,653,657,669,836,840,928,932,941,962,970,985,996,999,1005,1008,1014,1022],[428,429,430,431,435,436,439,440,444],"p",{},"When we start a new app using the Nuxt framework, we have to go through tedious steps like installing modules and setting up configurations such as ",[432,433,434],"code",{},"nuxt.config.ts"," and ",[432,437,438],{},"wrangler.jsonc",". A script can solve this problem, but it hits its limits as variations increase. This is why we explored and replaced scripts with an ",[441,442,443],"strong",{},"agent skill",".",[446,447,449],"h2",{"id":448},"what-traditional-shell-scripts-are-good-at","What Traditional Shell Scripts Are Good At",[428,451,452],{},"A script is good at executing a fixed set of instructions in sequence with hardcoded decisions.",[454,455,459],"pre",{"className":456,"code":457,"language":458,"meta":423,"style":423},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","#!\u002Fusr\u002Fbin\u002Fenv bash\nset -e\n\nnpx nuxi@latest init \"$1\" --template minimal --packageManager pnpm --no-gitInit -M @nuxt\u002Fui,@nuxthub\u002Fcore,@vueuse\u002Fnuxt\n\ncd \"$1\"\n\ncp ~\u002Ftemplates\u002Fnuxt.config.ts .\ncp ~\u002Ftemplates\u002Fwrangler.jsonc .\n","bash",[432,460,461,470,481,488,533,538,551,556,568],{"__ignoreMap":423},[462,463,466],"span",{"class":464,"line":465},"line",1,[462,467,469],{"class":468},"sHwdD","#!\u002Fusr\u002Fbin\u002Fenv bash\n",[462,471,473,477],{"class":464,"line":472},2,[462,474,476],{"class":475},"s2Zo4","set",[462,478,480],{"class":479},"sfazB"," -e\n",[462,482,484],{"class":464,"line":483},3,[462,485,487],{"emptyLinePlaceholder":486},true,"\n",[462,489,491,495,498,501,505,509,512,515,518,521,524,527,530],{"class":464,"line":490},4,[462,492,494],{"class":493},"sBMFI","npx",[462,496,497],{"class":479}," nuxi@latest",[462,499,500],{"class":479}," init",[462,502,504],{"class":503},"sMK4o"," \"",[462,506,508],{"class":507},"sHdIc","$1",[462,510,511],{"class":503},"\"",[462,513,514],{"class":479}," --template",[462,516,517],{"class":479}," minimal",[462,519,520],{"class":479}," --packageManager",[462,522,523],{"class":479}," pnpm",[462,525,526],{"class":479}," --no-gitInit",[462,528,529],{"class":479}," -M",[462,531,532],{"class":479}," @nuxt\u002Fui,@nuxthub\u002Fcore,@vueuse\u002Fnuxt\n",[462,534,536],{"class":464,"line":535},5,[462,537,487],{"emptyLinePlaceholder":486},[462,539,541,544,546,548],{"class":464,"line":540},6,[462,542,543],{"class":475},"cd",[462,545,504],{"class":503},[462,547,508],{"class":507},[462,549,550],{"class":503},"\"\n",[462,552,554],{"class":464,"line":553},7,[462,555,487],{"emptyLinePlaceholder":486},[462,557,559,562,565],{"class":464,"line":558},8,[462,560,561],{"class":493},"cp",[462,563,564],{"class":479}," ~\u002Ftemplates\u002Fnuxt.config.ts",[462,566,567],{"class":479}," .\n",[462,569,571,573,576],{"class":464,"line":570},9,[462,572,561],{"class":493},[462,574,575],{"class":479}," ~\u002Ftemplates\u002Fwrangler.jsonc",[462,577,567],{"class":479},[428,579,580],{},"This script works until the following occurs:",[582,583,584,591,601],"ul",{},[585,586,587,590],"li",{},[441,588,589],{},"Fixed defaults."," The script hardcodes the Nuxt UI module; what if we want the Ant Design UI module? Every new module option requires another argument from the user.",[585,592,593,596,597,600],{},[441,594,595],{},"It can't read the user's intent."," \"Build me a blog\" needs ",[432,598,599],{},"@nuxt\u002Fcontent","; \"build me a website with newsletters\" needs Cloudflare D1 + Drizzle. A script can't tell the difference—each variation needs a new script.",[585,602,603,606,607,610],{},[441,604,605],{},"It goes stale silently."," Nuxt's conventions change between major versions. Nuxt 4 changed the source directory to ",[432,608,609],{},"app\u002F",". A script that is written for Nuxt 3 quietly scaffolds the wrong layout and never alerts the user.",[428,612,613,616],{},[441,614,615],{},"App scaffolding"," is a decision issue, not an execution issue. The script will not scale when the number of decisions increases.",[446,618,620],{"id":619},"why-use-an-ai-agent-skill-over-traditional-scripts","Why Use an AI Agent Skill Over Traditional Scripts?",[428,622,623,624,627,628,631,632,635],{},"An agent skill is not a set of code that executes, but a ",[441,625,626],{},"set of knowledge the AI agent follows",". It contains ",[432,629,630],{},"SKILL.md"," and can bundle any other files the task requires (such as reference documents, templates, and executable scripts). The article, ",[633,634,350],"a",{"href":351},", explains how an agent skill works. A skill maintains a script's diligence while adding the reasonable judgements that a script lacks:",[582,637,638,641,644,647,650],{},[585,639,640],{},"Infers the user's intention to determine whether the app needs a database.",[585,642,643],{},"Decides which optional modules are needed from the specified list. For example, Nuxt Content, i18n, and analytics are opt-in when requested by the user.",[585,645,646],{},"Adapts to the current ecosystem using the latest Nuxt framework, NuxtHub for Cloudflare bindings, and Wrangler for deployment.",[585,648,649],{},"Recovers when a step fails.",[585,651,652],{},"Verifies against a final checklist before handing the project over.",[446,654,656],{"id":655},"behind-the-scenes-of-our-nuxt-cloudflare-scaffolding-skill","Behind the Scenes of Our Nuxt & Cloudflare Scaffolding Skill",[428,658,659,660,668],{},"The skill, ",[633,661,665],{"href":662,"rel":663},"https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fscaffold-nuxt-cloudflare-app-skill",[664],"nofollow",[432,666,667],{},"scaffold-nuxt-cloudflare-app-skill",", walks through a production-oriented scaffold:",[670,671,672,704,725,751,781,816,822],"ol",{},[585,673,674,677,678],{},[441,675,676],{},"Clarify anything"," that cannot be inferred:\n",[582,679,680,691,694],{},[585,681,682,683,686,687,690],{},"UI kit (",[441,684,685],{},"Nuxt UI"," by default or ",[441,688,689],{},"Antdv Next",");",[585,692,693],{},"Whether a database is required (such as Cloudflare D1);",[585,695,696,697,700,701,703],{},"Extra modules like ",[432,698,699],{},"@nuxtjs\u002Fi18n"," or ",[432,702,599],{}," for CMS features.",[585,705,706,709,710,713,714,717,718,721,722,444],{},[441,707,708],{},"Scaffolds the base app"," with ",[432,711,712],{},"pnpm dlx nuxi@latest init"," for the latest version of the Nuxt framework with ",[432,715,716],{},"pnpm"," as the package manager. It then sets native-build allowlists so Cloudflare's build environment can compile ",[432,719,720],{},"better-sqlite3","\u002F",[432,723,724],{},"sharp",[585,726,727,730,731,700,734,737,738,737,741,737,744,737,747,750],{},[441,728,729],{},"Installs modules from a decision table",": ",[432,732,733],{},"@nuxt\u002Fui",[432,735,736],{},"@antdv-next\u002Fnuxt",", ",[432,739,740],{},"@nuxt\u002Fimage",[432,742,743],{},"@nuxtjs\u002Fseo",[432,745,746],{},"@nuxthub\u002Fcore",[432,748,749],{},"@vueuse\u002Fnuxt",", plus Drizzle\u002FD1, Nuxt Content, and i18n only when selected.",[585,752,753,756,757],{},[441,754,755],{},"Lays out the directory structure",":\n",[582,758,759,763,768,773,778],{},[585,760,761],{},[432,762,609],{},[585,764,765],{},[432,766,767],{},"server\u002F",[585,769,770],{},[432,771,772],{},"shared\u002F",[585,774,775],{},[432,776,777],{},"tests\u002F",[585,779,780],{},"root config files.",[585,782,783,756,788],{},[441,784,785,786],{},"Configures ",[432,787,434],{},[582,789,790,799,806,811],{},[585,791,792,721,795,798],{},[432,793,794],{},"site.url",[432,796,797],{},"site.name"," for SEO",[585,800,801,802,805],{},"NuxtHub ",[432,803,804],{},"hub"," block for Cloudflare",[585,807,808],{},[432,809,810],{},"routeRules",[585,812,813],{},[432,814,815],{},"compatibilityDate",[585,817,818],{},[441,819,785,820],{},[432,821,438],{},[585,823,824,827,828,831,832,835],{},[441,825,826],{},"Sets up Vitest and ESLint",", then runs a ",[441,829,830],{},"final checklist"," including ",[432,833,834],{},"pnpm install && pnpm dev"," before considering the job done.",[446,837,839],{"id":838},"shell-scripts-vs-ai-agent-skills-a-side-by-side-comparison","Shell Scripts vs AI Agent Skills: A Side-by-Side Comparison",[841,842,843,858],"table",{},[844,845,846],"thead",{},[847,848,849,852,855],"tr",{},[850,851],"th",{},[850,853,854],{},"Script",[850,856,857],{},"Skill",[859,860,861,873,884,895,906,917],"tbody",{},[847,862,863,867,870],{},[864,865,866],"td",{},"User's intent",[864,868,869],{},"❌ fixed defaults",[864,871,872],{},"✅ adapts to the request",[847,874,875,878,881],{},[864,876,877],{},"Decision making",[864,879,880],{},"only if you pre-code flags",[864,882,883],{},"✅ judged at runtime",[847,885,886,889,892],{},[864,887,888],{},"Version changes",[864,890,891],{},"manual rewrite",[864,893,894],{},"✅ checks the current state",[847,896,897,900,903],{},[864,898,899],{},"Error recovery",[864,901,902],{},"halts",[864,904,905],{},"✅ fixes and continues",[847,907,908,911,914],{},[864,909,910],{},"Result verification",[864,912,913],{},"❌",[864,915,916],{},"✅ final checklist",[847,918,919,922,925],{},[864,920,921],{},"Maintenance cost",[864,923,924],{},"flags sprawl, version bumps",[864,926,927],{},"editing Markdown, not code",[446,929,931],{"id":930},"how-to-install-ai-agent-skills-with-the-npx-skills-cli","How to Install AI Agent Skills with the npx skills CLI",[428,933,934,935,940],{},"Installation is a single command with the ",[633,936,939],{"href":937,"rel":938},"https:\u002F\u002Fgithub.com\u002Fvercel-labs\u002Fskills",[664],"skills CLI",":",[454,942,944],{"className":456,"code":943,"language":458,"meta":423,"style":423},"npx skills add https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fscaffold-nuxt-cloudflare-app-skill.git -g\n",[432,945,946],{"__ignoreMap":423},[462,947,948,950,953,956,959],{"class":464,"line":465},[462,949,494],{"class":493},[462,951,952],{"class":479}," skills",[462,954,955],{"class":479}," add",[462,957,958],{"class":479}," https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fscaffold-nuxt-cloudflare-app-skill.git",[462,960,961],{"class":479}," -g\n",[428,963,964,965],{},"The CLI clones the repo, finds the skill, and asks which of the 77 supported agents should get it:\n",[966,967],"img",{"alt":968,"src":969},"Command line interface showing the installation of the Nuxt scaffolding skill using the npx skills add CLI command","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20AI%20Agent%20Skills%20Replace%20Nuxt%20App%20Scaffolding%20Scripts\u002Fnpx-skills-add-scaffold-nuxt-installation.webp",[428,971,972,973,976,977,980,981],{},"We went with ",[441,974,975],{},"Symlink"," (the recommended method), which installs the skill once in ",[432,978,979],{},"~\u002F.agents\u002Fskills"," and points every selected agent to this single copy.\n",[966,982],{"alt":983,"src":984},"Terminal screen displaying the installation summary and symlink setup for the centralized agent skills","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20AI%20Agent%20Skills%20Replace%20Nuxt%20App%20Scaffolding%20Scripts\u002Fnpx-skills-installation-summary-details.webp",[582,986,987],{},[585,988,989],{},[990,991,992,993,995],"em",{},"Please refer to this article, ",[633,994,358],{"href":359},", on how to centralise agent skills in a single source of truth.",[428,997,998],{},"Opening Claude Code confirms the skill is successfully installed.",[428,1000,1001],{},[966,1002],{"alt":1003,"src":1004},"Claude Code command line interface showing the newly installed scaffold-nuxt slash command active and ready for use","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20AI%20Agent%20Skills%20Replace%20Nuxt%20App%20Scaffolding%20Scripts\u002Fclaude-code-scaffold-nuxt-slash-command-active.webp",[428,1006,1007],{},"From there, a natural-language prompt is all it takes:",[1009,1010,1011],"blockquote",{},[428,1012,1013],{},"\"Scaffold a new Nuxt app deployed to Cloudflare Workers — Nuxt UI, a blog section, and a D1 database\"",[428,1015,1016,1017,1021],{},"The skill is open source; check out the ",[633,1018,1020],{"href":662,"rel":1019},[664],"GitHub repo"," and give it a try.",[1023,1024,1025],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":472,"depth":483,"links":1027},[1028,1029,1030,1031,1032],{"id":448,"depth":472,"text":449},{"id":619,"depth":472,"text":620},{"id":655,"depth":472,"text":656},{"id":838,"depth":472,"text":839},{"id":930,"depth":472,"text":931},[1034],"ai-agents","2026-08-25","Scaffold Nuxt on Cloudflare Workers easily. Learn why we replaced brittle shell scripts with AI agent skills and how to install them with npx skills.","md","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20AI%20Agent%20Skills%20Replace%20Nuxt%20App%20Scaffolding%20Scripts\u002FEN-How-AI-Agent-Skills-Replace-Nuxt-App-Scaffolding-Scripts.webp","Nuxt Scaffolding on Cloudflare: Scripts vs AI Skills - Comparing shell scripts and intelligent AI agent skills for scaffolding Nuxt applications.",{"schemaOrg":1041,"robots":1044,"sitemap":1045},[1042],{"@type":1043,"headline":366,"description":1036,"image":1038},"TechArticle","index, follow",{"lastmod":1035},{"title":1047,"description":1036,"ogTitle":366,"ogDescription":1036,"twitterTitle":366,"twitterDescription":1036},"Nuxt Scaffolding on Cloudflare: Scripts vs AI Skills",[1049,1050,1051,1052],"Nuxt","Cloudflare","AI Agent","Scaffolding",null,"NXF2Lnd-1xZXVg9jQtNTE4K5fB8GBw1eOmA1GHAhr6s",{"surround":1056,"related":3810},[1057,1869],{"id":1058,"title":414,"author":1053,"body":1059,"category":1852,"date":1854,"description":1855,"extension":1037,"image":1856,"imageAlt":1857,"isPublished":486,"meta":1858,"minRead":553,"navigation":486,"path":415,"seo":1863,"stem":416,"tags":1864,"updatedAt":1053,"__hash__":1868},"article\u002Fen\u002Farticle\u002Fuse-cloudflare-as-ai-memory.md",{"type":425,"value":1060,"toc":1834},[1061,1065,1068,1071,1075,1078,1092,1096,1103,1117,1120,1123,1164,1169,1252,1256,1282,1394,1405,1409,1414,1458,1482,1486,1491,1564,1569,1573,1607,1615,1653,1657,1689,1693,1701,1706,1736,1740,1780,1784,1787,1790,1793,1797,1831],[446,1062,1064],{"id":1063},"the-importance-of-persistent-ai-memory-for-agents","The Importance of Persistent AI Memory for Agents",[428,1066,1067],{},"As AI assistants become integrated into our daily lives, we frequently encounter the blank context issue. The decisions made last week are forgotten, requiring us to input the same tech stack details, and set the user preferences all over again.",[428,1069,1070],{},"Instead of starting from scratch every time, we need to build a memory system that evolves, continuously understands a user's decisions and eliminates the need to repeat context.",[446,1072,1074],{"id":1073},"self-hosted-vs-built-in-ai-memory-systems","Self-Hosted vs. Built-In AI Memory Systems",[428,1076,1077],{},"Many AI agents come with built-in memory, but we don't just use one agent for all purposes. We use Claude for architecting and designing a project; Kimi for coding; and ChatGPT for research. The context is not shared among these agents; it remains siloed per agent.",[428,1079,1080,1081,1086,1087,1091],{},"From a software engineering point of view, we don't trust black boxes. We need AI memory system that is observable, auditable, and under our control. The open sourced project, ",[633,1082,1085],{"href":1083,"rel":1084},"https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fsecond-brain-cloudflare\u002Ftree\u002Fmain",[664],"Second Brain",", forked from ",[633,1088,1089],{"href":1089,"rel":1090},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare",[664],", provides a persistent and self-hosted memory system with Model Context Protocol (MCP) support.  Any compatible AI agents such as Claude, ChatGPT, Kimi Code can share the same context.",[446,1093,1095],{"id":1094},"how-to-build-a-second-brain-ai-memory-on-cloudflare","How to Build a Second Brain AI Memory on Cloudflare",[428,1097,1098,1099,1102],{},"The Second Brain memory system is deployed on ",[441,1100,1101],{},"Cloudflare Workers",", which provides globally distributed, low-latency execution server infrastructure. This allows the memory recall and other operations to execute with minimal latency to the AI’s reasoning loop.",[428,1104,1105,1106,1109,1110,1113,1114,1116],{},"The ",[441,1107,1108],{},"Workers AI"," embedding model is used for generating the embeddings. These embeddings are stored in ",[441,1111,1112],{},"Cloudflare Vectorize",", which is a globally distributed vector database. The ",[441,1115,1112],{}," performs the cosine similarity search for semantically related memories.",[428,1118,1119],{},"Duplication detection and smart merging mechanisms are implemented in Second Brain. Content with less than 85% similarity is stored, otherwise it is blocked or marked as a duplicate candidate. Text exceeding 1,600 characters is split at sentence or line-break boundaries with 200-character overlap to prevent loss of context. Then each chunk is embedded as a vector which allows precise matching.",[428,1121,1122],{},"The following tools are exposed as MCP interfaces to be used in AI agents:",[582,1124,1125,1131,1137,1143,1149,1155,1161],{},[585,1126,1127,1130],{},[432,1128,1129],{},"remember",": Store ideas, decisions, preferences, and project context",[585,1132,1133,1136],{},[432,1134,1135],{},"append",": Add an update to an existing memory",[585,1138,1139,1142],{},[432,1140,1141],{},"update",": Replace an existing memory",[585,1144,1145,1148],{},[432,1146,1147],{},"recall",": Find memories by meaning rather than exact wording",[585,1150,1151,1154],{},[432,1152,1153],{},"list_recent",": Browse recently saved memories",[585,1156,1157,1160],{},[432,1158,1159],{},"forget",": Permanently delete a memory",[585,1162,1163],{},"`link\u002Fconnections``: Connect related memories (v2 graph feature)",[1165,1166,1168],"h3",{"id":1167},"setup-second-brain-on-cloudflare","Setup Second Brain on Cloudflare",[670,1170,1171,1189,1196,1203,1210,1217,1228,1235,1238,1245],{},[585,1172,1173,1174,1177,1178,1183,1184,1188],{},"Click on ",[432,1175,1176],{},"Deploy to Cloudflare"," at the ",[633,1179,1182],{"href":1180,"rel":1181},"https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fsecond-brain-cloudflare",[664],"Github repo"," page. [[",[966,1185],{"alt":1186,"src":1187},"GitHub page with the Deploy to Cloudflare button highlighted","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fdeploy-to-cloudflare-button.webp","]]",[585,1190,1191,1192],{},"Fill out the Cloudflare Worker form.\n",[966,1193],{"alt":1194,"src":1195},"Cloudflare Workers deployment configuration form","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-deployment-form.webp",[585,1197,1198,1199],{},"Enter '384' for Dimensions; select 'cosine' for Metric; and click the Deploy button.\n",[966,1200],{"alt":1201,"src":1202},"Cloudflare Vectorize database creation settings screen","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-vectorize-configuration.webp",[585,1204,1205,1206],{},"The following is the overview of the Second Brain in Cloudflare Worker\n",[966,1207],{"alt":1208,"src":1209},"Overview dashboard of the deployed Second Brain worker","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-second-brain-overview.webp",[585,1211,1212,1213],{},"Click on 'Settings', then click edit icon for 'AUTH_TOKEN' for creating a token\n",[966,1214],{"alt":1215,"src":1216},"Cloudflare Worker variable settings highlighting AUTH_TOKEN","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-auth-token-settings.webp",[585,1218,1219,1220,1224],{},"Click the 'Rotate' link for entering a new value           ",[966,1221],{"alt":1222,"src":1223},"AUTH_TOKEN variable modification and rotation screen","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-auth-token-rotate.webp",[966,1225],{"alt":1226,"src":1227},"Entering the generated random string into the AUTH_TOKEN value field","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-auth-token-value-input.webp",[585,1229,1230,1231,1234],{},"Run the command ",[432,1232,1233],{},"openssl rand -base64 32"," at macOS terminal to create a random value and paste it in the 'Value' input field.",[585,1236,1237],{},"Click the 'Deploy' button to update the new value of 'AUTH_TOKEN'.",[585,1239,1240,1241],{},"Open the Second Brain worker url on the web browser\n",[966,1242],{"alt":1243,"src":1244},"Second Brain Web UI login screen with Bearer Token input","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fsecond-brain-web-ui-login.webp",[585,1246,1247,1248,1251],{},"Enter the created 'AUTH_TOKEN' in the ",[432,1249,1250],{},"Bearer token"," input field and click 'Connect' button to login to the Web UI.",[1165,1253,1255],{"id":1254},"integrating-claude-desktop-via-mcp","Integrating Claude Desktop via MCP",[670,1257,1258,1265,1272],{},[585,1259,1260,1261],{},"Click on 'Customize' at Claude Desktop.\n",[966,1262],{"alt":1263,"src":1264},"Claude Desktop interface pointing to the Customize button","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-customize-button.webp",[585,1266,1267,1268],{},"Click on 'Developer' to manually edit the MCP Servers config file\n",[966,1269],{"alt":1270,"src":1271},"Claude Desktop Developer settings menu to access MCP config","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-developer-menu.webp",[585,1273,1274,1275,1278,1279],{},"Add the following code to the ",[432,1276,1277],{},"mcpServers"," section in",[432,1280,1281],{},"claude_desktop_config.json",[454,1283,1287],{"className":1284,"code":1285,"language":1286,"meta":423,"style":423},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","    \"second-brain\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"mcp-remote\",\n        \"https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp\",\n        \"--header\",\n        \"Authorization: Bearer \u003Cyour-token>\"\n      ]\n    }\n","json",[432,1288,1289,1305,1327,1341,1353,1364,1375,1384,1389],{"__ignoreMap":423},[462,1290,1291,1294,1297,1299,1302],{"class":464,"line":465},[462,1292,1293],{"class":503},"    \"",[462,1295,1296],{"class":479},"second-brain",[462,1298,511],{"class":503},[462,1300,730],{"class":1301},"sTEyZ",[462,1303,1304],{"class":503},"{\n",[462,1306,1307,1310,1314,1316,1318,1320,1322,1324],{"class":464,"line":472},[462,1308,1309],{"class":503},"      \"",[462,1311,1313],{"class":1312},"spNyl","command",[462,1315,511],{"class":503},[462,1317,940],{"class":503},[462,1319,504],{"class":503},[462,1321,494],{"class":479},[462,1323,511],{"class":503},[462,1325,1326],{"class":503},",\n",[462,1328,1329,1331,1334,1336,1338],{"class":464,"line":483},[462,1330,1309],{"class":503},[462,1332,1333],{"class":1312},"args",[462,1335,511],{"class":503},[462,1337,940],{"class":503},[462,1339,1340],{"class":503}," [\n",[462,1342,1343,1346,1349,1351],{"class":464,"line":490},[462,1344,1345],{"class":503},"        \"",[462,1347,1348],{"class":479},"mcp-remote",[462,1350,511],{"class":503},[462,1352,1326],{"class":503},[462,1354,1355,1357,1360,1362],{"class":464,"line":535},[462,1356,1345],{"class":503},[462,1358,1359],{"class":479},"https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp",[462,1361,511],{"class":503},[462,1363,1326],{"class":503},[462,1365,1366,1368,1371,1373],{"class":464,"line":540},[462,1367,1345],{"class":503},[462,1369,1370],{"class":479},"--header",[462,1372,511],{"class":503},[462,1374,1326],{"class":503},[462,1376,1377,1379,1382],{"class":464,"line":553},[462,1378,1345],{"class":503},[462,1380,1381],{"class":479},"Authorization: Bearer \u003Cyour-token>",[462,1383,550],{"class":503},[462,1385,1386],{"class":464,"line":558},[462,1387,1388],{"class":503},"      ]\n",[462,1390,1391],{"class":464,"line":570},[462,1392,1393],{"class":503},"    }\n",[428,1395,1396,1400,1401],{},[966,1397],{"alt":1398,"src":1399},"Claude Desktop MCP configuration JSON containing the Second Brain server","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-mcp-config-json.webp","\n4. Restart Claude Desktop and check the 'Local MCP servers'. The status says 'running'",[966,1402],{"alt":1403,"src":1404},"Claude Desktop displaying running status for the Second Brain MCP server","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-mcp-status-running.webp",[1165,1406,1408],{"id":1407},"integrating-claude-code-via-mcp","Integrating Claude Code via MCP",[582,1410,1411],{},[585,1412,1413],{},"Run the following command to add the MCP",[454,1415,1419],{"className":1416,"code":1417,"language":1418,"meta":423,"style":423},"language-shell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","claude mcp add --transport http second-brain https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp\n","shell",[432,1420,1421],{"__ignoreMap":423},[462,1422,1423,1426,1429,1431,1434,1437,1440,1443,1446,1449,1452,1455],{"class":464,"line":465},[462,1424,1425],{"class":493},"claude",[462,1427,1428],{"class":479}," mcp",[462,1430,955],{"class":479},[462,1432,1433],{"class":479}," --transport",[462,1435,1436],{"class":479}," http",[462,1438,1439],{"class":479}," second-brain",[462,1441,1442],{"class":479}," https:\u002F\u002F",[462,1444,1445],{"class":503},"\u003C",[462,1447,1448],{"class":479},"your-worker-ur",[462,1450,1451],{"class":1301},"l",[462,1453,1454],{"class":503},">",[462,1456,1457],{"class":479},"\u002Fmcp\n",[582,1459,1460,1466],{},[585,1461,1462,1463],{},"Claude Code detects that the endpoint requires OAuth and will open the login page at the web browser for entering ",[432,1464,1465],{},"AUTH_TOKEN",[585,1467,1468,1469,1472,1473,1476,1477,444],{},"Create the ",[432,1470,1471],{},"CLAUDE.md"," file in ",[432,1474,1475],{},"~\u002F.claude"," folder with the instructions from ",[633,1478,1481],{"href":1479,"rel":1480},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fblob\u002Fmain\u002FAI_Instructions\u002FCLAUDE_INSTRUCTIONS.md",[664],"CLAUDE_INSTRUCTIONS.md",[1165,1483,1485],{"id":1484},"integrating-gemini-cli-via-mcp","Integrating Gemini CLI via MCP",[670,1487,1488],{},[585,1489,1490],{},"Add the following MCP server settings to '.\u002F.gemini\u002Fsettings.json'",[454,1492,1494],{"className":1284,"code":1493,"language":1286,"meta":423,"style":423},"    \"second-brain\": {\n      \"httpUrl\": \"https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp\",\n      \"oauth\": {\n        \"enabled\": true\n      }\n    }\n",[432,1495,1496,1508,1527,1541,1555,1560],{"__ignoreMap":423},[462,1497,1498,1500,1502,1504,1506],{"class":464,"line":465},[462,1499,1293],{"class":503},[462,1501,1296],{"class":479},[462,1503,511],{"class":503},[462,1505,730],{"class":1301},[462,1507,1304],{"class":503},[462,1509,1510,1512,1515,1517,1519,1521,1523,1525],{"class":464,"line":472},[462,1511,1309],{"class":503},[462,1513,1514],{"class":1312},"httpUrl",[462,1516,511],{"class":503},[462,1518,940],{"class":503},[462,1520,504],{"class":503},[462,1522,1359],{"class":479},[462,1524,511],{"class":503},[462,1526,1326],{"class":503},[462,1528,1529,1531,1534,1536,1538],{"class":464,"line":483},[462,1530,1309],{"class":503},[462,1532,1533],{"class":1312},"oauth",[462,1535,511],{"class":503},[462,1537,940],{"class":503},[462,1539,1540],{"class":503}," {\n",[462,1542,1543,1545,1548,1550,1552],{"class":464,"line":490},[462,1544,1345],{"class":503},[462,1546,1547],{"class":493},"enabled",[462,1549,511],{"class":503},[462,1551,940],{"class":503},[462,1553,1554],{"class":503}," true\n",[462,1556,1557],{"class":464,"line":535},[462,1558,1559],{"class":503},"      }\n",[462,1561,1562],{"class":464,"line":540},[462,1563,1393],{"class":503},[670,1565,1566],{"start":472},[585,1567,1568],{},"Start the Gemini CLI",[1165,1570,1572],{"id":1571},"test-second-brain-in-ai-agents","Test Second Brain in AI Agents",[670,1574,1575,1586,1600],{},[585,1576,1577,1578,1581,1582],{},"Started with a simple brand palette settings in '",[441,1579,1580],{},"Claude Desktop","', the Second Brain is not called.\n",[966,1583],{"alt":1584,"src":1585},"First test in Claude Desktop without the Second Brain memory layer active","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-first-run-brand-palette.webp",[585,1587,1588,1589,1592,1593,1595,1596],{},"Tried with the keyword, 'remember', only ",[432,1590,1591],{},"memory_user-edits"," tools in '",[441,1594,1580],{},"' are used but not Second Brain.\n",[966,1597],{"alt":1598,"src":1599},"Claude Desktop falling back to local built-in user edits instead of Second Brain","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-remember-built-in-tool-fallback.webp",[585,1601,1602,1603,1606],{},"Tried the the following prompt in '",[441,1604,1605],{},"Claude Code","', Second Brain was called.",[454,1608,1613],{"className":1609,"code":1611,"language":1612},[1610],"language-text","Remember Our brand palette uses `#1a1a2e` as primary, `#16213e` as secondary, and `#e94560` as accent. Never use pure black.\"\n","text",[432,1614,1611],{"__ignoreMap":423},[428,1616,1617,1621,1622,1625,1629,1630,1633,1634,1636,1637,1641,1642,1645,1646,1629,1650],{},[966,1618],{"alt":1619,"src":1620},"Claude Code terminal window showing successful trigger of the Second Brain MCP","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-code-second-brain-mcp-called.webp","\n4. Verified the colour settings in the ",[441,1623,1624],{},"Second Brain at Cloudflare",[966,1626],{"alt":1627,"src":1628},"Verifying the saved brand color codes in the Second Brain database Web UI","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fsecond-brain-web-ui-color-verification.webp","\n- ",[990,1631,1632],{},"The reason Claude Code worked was because the CLAUDE_INSTRUCTIONS.md contains the 'Second Brain' keywords.","\n5. Included 'Second Brain' as keywords in '",[441,1635,1580],{},"',  need to be explicitly specified to store to and retrieve from the Second Brain memory layer.\n",[966,1638],{"alt":1639,"src":1640},"Triggering Second Brain in Claude Desktop by explicitly mentioning keywords","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-second-brain-explicit-trigger.webp","\n6. The keywords, 'Second Brain', need to be mentioned in the ",[441,1643,1644],{},"Gemini CLI"," to trigger the Second Brain MCP.\n",[966,1647],{"alt":1648,"src":1649},"Gemini CLI terminal window demonstrating successful Second Brain MCP calls","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fgemini-cli-second-brain-trigger.webp",[990,1651,1652],{},"Adding similar instructions to GEMINI.md like what has been done in CLAUDE_INSTRUCTIONS.md will trigger the Second Brain without mentioning the keywords.",[1165,1654,1656],{"id":1655},"web-browser-extensions","Web Browser Extensions",[582,1658,1659,1662],{},[585,1660,1661],{},"Extensions are available for Chrome, Firefox and Microsoft Edge web browsers.",[585,1663,1664,1665],{},"The extensions are for\n",[582,1666,1667,1673,1679],{},[585,1668,1669,1672],{},[441,1670,1671],{},"Capture the current page"," — saves the title and URL to the Second Brain",[585,1674,1675,1678],{},[441,1676,1677],{},"Capture highlighted text"," — select any text on a page before clicking capture; the excerpt is saved alongside the title and URL",[585,1680,1681,1684,1685,1688],{},[441,1682,1683],{},"Add a note"," — type context or ",[432,1686,1687],{},"#hashtags"," in the popup before saving; hashtags are automatically extracted as tags",[1165,1690,1692],{"id":1691},"syncing-personal-knowledge-with-the-obsidian-plugin","Syncing Personal Knowledge with the Obsidian Plugin",[582,1694,1695,1698],{},[585,1696,1697],{},"Obsidian plugin is available to sync the notes from the Obsidian Vault to Second Brain at Cloudflare.",[585,1699,1700],{},"Notes can be tagged for syncing to the Second Brain",[1702,1703,1705],"h4",{"id":1704},"install-obsidian-plugin","Install Obsidian Plugin",[670,1707,1708,1715,1722,1729],{},[585,1709,1710,1711],{},"Open Obsidian → Settings → Community Plugins\n",[966,1712],{"alt":1713,"src":1714},"Obsidian settings panel navigating to the Community Plugins section","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-settings-community-plugins.webp",[585,1716,1717,1718],{},"Click on 'Browse' button\n",[966,1719],{"alt":1720,"src":1721},"Obsidian community plugins search page showing the Browse button","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-community-plugins-browse.webp",[585,1723,1724,1725],{},"Search for 'Second Brain Sync'\n",[966,1726],{"alt":1727,"src":1728},"Searching for Second Brain Sync plugin in Obsidian marketplace","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-community-plugins-search-second-brain.webp",[585,1730,1731,1732],{},"Click 'Install' button then 'Enable' button\n",[966,1733],{"alt":1734,"src":1735},"Installing and enabling the Second Brain Sync plugin in Obsidian","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-install-and-enable.webp",[1702,1737,1739],{"id":1738},"configure-obsidian-plugin","Configure Obsidian Plugin",[670,1741,1742,1745,1752,1759,1766,1773],{},[585,1743,1744],{},"Open Obsidian → Settings → Second Brain Sync",[585,1746,1747,1748],{},"Enter the 'URL' and 'Auth token'\n",[966,1749],{"alt":1750,"src":1751},"Entering Worker URL and Auth Token in Obsidian plugin settings","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-configuration-credentials.webp",[585,1753,1754,1755],{},"Click 'Test' button to verify it is connected.\n",[966,1756],{"alt":1757,"src":1758},"Obsidian plugin connection test showing successful verification","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-connection-test-success.webp",[585,1760,1761,1762],{},"Configure the sync behaviours. Set the 'Sync tag' and enable 'Auto-sync on save'.\n",[966,1763],{"alt":1764,"src":1765},"Configuring Sync Tag and enabling Auto-sync on save in Obsidian","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-sync-behavior-settings.webp",[585,1767,1768,1769],{},"Create a note in Obsidian with the tag, 'second-brain', as it was configured as the 'Sync tag'.\n",[966,1770],{"alt":1771,"src":1772},"Creating a new Obsidian note tagged with second-brain for synchronization","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-note-with-sync-tag.webp",[585,1774,1775,1776],{},"The note has been saved and synced to the Second Brain deployed at Cloudflare.\n",[966,1777],{"alt":1778,"src":1779},"Verifying the successfully synchronized Obsidian note in Second Brain Web UI","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fsecond-brain-web-ui-synced-note-verification.webp",[446,1781,1783],{"id":1782},"conclusion","Conclusion",[428,1785,1786],{},"Second Brain provides an open-source solution to one of the most frustrating issues in AI: persistent memory. By combining it with Cloudflare infrastructure, it delivers a fully self-hosted memory layer that is globally distributed with low latency. The MCP tools built into Second Brain make this memory portable across all AI agents.",[428,1788,1789],{},"The Obsidian plugin extends the Second Brain into personal knowledge management. Notes in an Obsidian vault can be selectively synchronised to Second Brain, transforming raw notes into structured context that AI agents can semantically understand and retrieve.",[428,1791,1792],{},"By combining self-hosting, semantic search, and standards-based MCP integration; Second Brain proves to be more than just a memory layer but a practical foundation for building an AI ecosystem.",[446,1794,1796],{"id":1795},"reference","Reference:",[582,1798,1799,1805,1811,1818,1825],{},[585,1800,1801],{},[633,1802,1803],{"href":1803,"rel":1804},"https:\u002F\u002Fwww.thesecondbrain.dev\u002F",[664],[585,1806,1807],{},[633,1808,1809],{"href":1809,"rel":1810},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fwiki\u002FHow-It-Works",[664],[585,1812,1813],{},[633,1814,1817],{"href":1815,"rel":1816},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fwiki\u002FConnect-to-AI-Clients",[664],"Connect to AI Clients",[585,1819,1820],{},[633,1821,1824],{"href":1822,"rel":1823},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fwiki\u002FObsidian-Plugin",[664],"Second Brain Obsidian Plugin",[585,1826,1827],{},[633,1828,1829],{"href":1829,"rel":1830},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-obsidian-plugin",[664],[1023,1832,1833],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":423,"searchDepth":472,"depth":483,"links":1835},[1836,1837,1838,1850,1851],{"id":1063,"depth":472,"text":1064},{"id":1073,"depth":472,"text":1074},{"id":1094,"depth":472,"text":1095,"children":1839},[1840,1841,1842,1843,1844,1845,1846],{"id":1167,"depth":483,"text":1168},{"id":1254,"depth":483,"text":1255},{"id":1407,"depth":483,"text":1408},{"id":1484,"depth":483,"text":1485},{"id":1571,"depth":483,"text":1572},{"id":1655,"depth":483,"text":1656},{"id":1691,"depth":483,"text":1692,"children":1847},[1848,1849],{"id":1704,"depth":490,"text":1705},{"id":1738,"depth":490,"text":1739},{"id":1782,"depth":472,"text":1783},{"id":1795,"depth":472,"text":1796},[1853,1034],"cloudflare","2026-08-07","Learn how to build a persistent, self-hosted AI memory system on Cloudflare using Second Brain and MCP. Share context across Claude, Gemini, and Obsidian.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002FEN-Use-Cloudflare-as-AI-memory.webp","A personal self-hosted AI memory system deployed on Cloudflare Workers and Vectorize using the Model Context Protocol (MCP) and Obsidian sync.",{"schemaOrg":1859,"robots":1044,"sitemap":1862},[1860],{"@type":1043,"headline":1861,"description":1855},"Build a Self-Hosted AI Memory System with Cloudflare & MCP",{"lastmod":1854},{"title":1861,"description":1855,"ogTitle":414,"ogDescription":1855,"twitterTitle":414,"twitterDescription":1855},[1050,1865,1866,1085,1867],"MCP","AI Memory","Obsidian","i-n5KfCSdIReLHWXO0pss_aKBTXq5lNG61z0LAefVgk",{"id":1870,"title":378,"author":1053,"body":1871,"category":3788,"date":3790,"description":3791,"extension":1037,"image":3792,"imageAlt":3793,"isPublished":486,"meta":3794,"minRead":3802,"navigation":486,"path":379,"seo":3803,"stem":380,"tags":3804,"updatedAt":3808,"__hash__":3809},"article\u002Fen\u002Farticle\u002Fself-hosted-travel-planner-trek.md",{"type":425,"value":1872,"toc":3747},[1873,1876,1879,1882,1886,1890,2078,2082,2090,2110,2113,2117,2222,2233,2236,2241,2244,2256,2260,2264,2267,2270,2308,2312,2315,2347,2350,2392,2395,2400,2411,2415,2422,2426,2429,2524,2528,2534,2538,2545,2549,2552,2570,2580,2584,2587,2597,2601,2605,2613,2617,2621,2624,2628,2632,2635,2640,2643,2648,2654,2658,2662,2665,2669,2682,2687,2693,2698,2702,2705,2710,2715,2718,2725,2729,2732,2735,2745,2752,2757,2763,2768,2772,2779,2784,2787,2792,2796,2802,2806,2811,2815,2818,2821,2826,2831,2836,2840,2847,2852,2857,2862,2867,2871,2876,2881,2887,2891,2894,2898,2904,2909,2914,2920,2925,2930,2935,2948,2952,2957,2977,2982,2985,2989,2992,2997,3000,3047,3051,3058,3064,3069,3075,3080,3086,3091,3097,3100,3105,3112,3117,3123,3127,3133,3138,3143,3147,3151,3154,3158,3161,3168,3172,3179,3183,3195,3203,3207,3211,3221,3230,3235,3242,3247,3254,3258,3261,3413,3419,3423,3426,3431,3434,3440,3444,3451,3455,3458,3463,3470,3475,3479,3489,3556,3572,3575,3580,3584,3588,3599,3676,3686,3689,3693,3697,3700,3704,3707,3710,3719,3721,3744],[428,1874,1875],{},"The tedious part of travel planning is that flight booking PDFs, hotel confirmations, conversations with travel companions, and lists of places to visit are scattered in different locations. When it is time to work out total spending and split the bills, huge effort is needed to scroll through all that travel data.",[428,1877,1878],{},"TREK is an open-source travel planner that can be self-hosted, packing your itinerary, bookings, budget, and packing lists all into one place. The built-in MCP server enables AI agents (such as Claude Desktop) to directly manipulate travel data.",[428,1880,1881],{},"This guide will walk you through everything from deployment to fully managing a real trip from start to finish.",[1165,1883,1885],{"id":1884},"_1-how-to-deploy-trek-travel-planner-using-docker","1. How to Deploy TREK Travel Planner Using Docker",[1702,1887,1889],{"id":1888},"install-docker-on-the-ubuntu-vps","Install Docker on the Ubuntu VPS",[454,1891,1893],{"className":456,"code":1892,"language":458,"meta":423,"style":423},"# Add Docker's official GPG key and set up the Docker repository\ncurl -fsSL https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg | sudo gpg --dearmor -o \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n\n# Add the official Docker repository\necho \"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu $(lsb_release -cs) stable\" | sudo tee \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list > \u002Fdev\u002Fnull\n\n# Update package list\nsudo apt update\n\n# Install Docker Engine, Docker Community Edition, and containerd runtime\nsudo apt install docker-ce docker-ce-cli containerd.io -y\n\n# Verify docker is installed\ndocker --version\n\n# Starts automatically when your system boots\nsudo systemctl enable docker\n",[432,1894,1895,1900,1929,1933,1938,1981,1985,1990,2001,2005,2011,2033,2038,2044,2053,2058,2064],{"__ignoreMap":423},[462,1896,1897],{"class":464,"line":465},[462,1898,1899],{"class":468},"# Add Docker's official GPG key and set up the Docker repository\n",[462,1901,1902,1905,1908,1911,1914,1917,1920,1923,1926],{"class":464,"line":472},[462,1903,1904],{"class":493},"curl",[462,1906,1907],{"class":479}," -fsSL",[462,1909,1910],{"class":479}," https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg",[462,1912,1913],{"class":503}," |",[462,1915,1916],{"class":493}," sudo",[462,1918,1919],{"class":479}," gpg",[462,1921,1922],{"class":479}," --dearmor",[462,1924,1925],{"class":479}," -o",[462,1927,1928],{"class":479}," \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n",[462,1930,1931],{"class":464,"line":483},[462,1932,487],{"emptyLinePlaceholder":486},[462,1934,1935],{"class":464,"line":490},[462,1936,1937],{"class":468},"# Add the official Docker repository\n",[462,1939,1940,1943,1945,1948,1951,1954,1957,1960,1963,1965,1967,1969,1972,1975,1978],{"class":464,"line":535},[462,1941,1942],{"class":475},"echo",[462,1944,504],{"class":503},[462,1946,1947],{"class":479},"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu ",[462,1949,1950],{"class":503},"$(",[462,1952,1953],{"class":493},"lsb_release",[462,1955,1956],{"class":479}," -cs",[462,1958,1959],{"class":503},")",[462,1961,1962],{"class":479}," stable",[462,1964,511],{"class":503},[462,1966,1913],{"class":503},[462,1968,1916],{"class":493},[462,1970,1971],{"class":479}," tee",[462,1973,1974],{"class":479}," \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list",[462,1976,1977],{"class":503}," >",[462,1979,1980],{"class":479}," \u002Fdev\u002Fnull\n",[462,1982,1983],{"class":464,"line":540},[462,1984,487],{"emptyLinePlaceholder":486},[462,1986,1987],{"class":464,"line":553},[462,1988,1989],{"class":468},"# Update package list\n",[462,1991,1992,1995,1998],{"class":464,"line":558},[462,1993,1994],{"class":493},"sudo",[462,1996,1997],{"class":479}," apt",[462,1999,2000],{"class":479}," update\n",[462,2002,2003],{"class":464,"line":570},[462,2004,487],{"emptyLinePlaceholder":486},[462,2006,2008],{"class":464,"line":2007},10,[462,2009,2010],{"class":468},"# Install Docker Engine, Docker Community Edition, and containerd runtime\n",[462,2012,2014,2016,2018,2021,2024,2027,2030],{"class":464,"line":2013},11,[462,2015,1994],{"class":493},[462,2017,1997],{"class":479},[462,2019,2020],{"class":479}," install",[462,2022,2023],{"class":479}," docker-ce",[462,2025,2026],{"class":479}," docker-ce-cli",[462,2028,2029],{"class":479}," containerd.io",[462,2031,2032],{"class":479}," -y\n",[462,2034,2036],{"class":464,"line":2035},12,[462,2037,487],{"emptyLinePlaceholder":486},[462,2039,2041],{"class":464,"line":2040},13,[462,2042,2043],{"class":468},"# Verify docker is installed\n",[462,2045,2047,2050],{"class":464,"line":2046},14,[462,2048,2049],{"class":493},"docker",[462,2051,2052],{"class":479}," --version\n",[462,2054,2056],{"class":464,"line":2055},15,[462,2057,487],{"emptyLinePlaceholder":486},[462,2059,2061],{"class":464,"line":2060},16,[462,2062,2063],{"class":468},"# Starts automatically when your system boots\n",[462,2065,2067,2069,2072,2075],{"class":464,"line":2066},17,[462,2068,1994],{"class":493},[462,2070,2071],{"class":479}," systemctl",[462,2073,2074],{"class":479}," enable",[462,2076,2077],{"class":479}," docker\n",[1702,2079,2081],{"id":2080},"generate-the-encryption-key","Generate the encryption key",[428,2083,2084,2085,2089],{},"TREK uses a key to encrypt sensitive data. Use the following command or this ",[633,2086,2088],{"href":2087},"\u002Ftools\u002Fsecret-key-hex","online tool"," to generate the encryption key:",[454,2091,2093],{"className":456,"code":2092,"language":458,"meta":423,"style":423},"openssl rand -hex 32\n",[432,2094,2095],{"__ignoreMap":423},[462,2096,2097,2100,2103,2106],{"class":464,"line":465},[462,2098,2099],{"class":493},"openssl",[462,2101,2102],{"class":479}," rand",[462,2104,2105],{"class":479}," -hex",[462,2107,2109],{"class":2108},"sbssI"," 32\n",[428,2111,2112],{},"Save it somewhere safe; losing it means losing access to encrypted data.",[1702,2114,2116],{"id":2115},"start-the-container","Start the container",[454,2118,2120],{"className":456,"code":2119,"language":458,"meta":423,"style":423},"docker run -d \\\n  --name trek \\\n  -p 3000:3000 \\\n  -e ENCRYPTION_KEY=\"\u003Cgenerated_key>\" \\\n  -e APP_URL=\"https:\u002F\u002Ftrek.pafor.me\" \\\n  -v .\u002Fdata:\u002Fapp\u002Fdata \\\n  -v .\u002Fuploads:\u002Fapp\u002Fuploads \\\n  --restart unless-stopped \\\n  mauriceboe\u002Ftrek:latest\n",[432,2121,2122,2135,2145,2155,2172,2188,2198,2207,2217],{"__ignoreMap":423},[462,2123,2124,2126,2129,2132],{"class":464,"line":465},[462,2125,2049],{"class":493},[462,2127,2128],{"class":479}," run",[462,2130,2131],{"class":479}," -d",[462,2133,2134],{"class":1301}," \\\n",[462,2136,2137,2140,2143],{"class":464,"line":472},[462,2138,2139],{"class":479},"  --name",[462,2141,2142],{"class":479}," trek",[462,2144,2134],{"class":1301},[462,2146,2147,2150,2153],{"class":464,"line":483},[462,2148,2149],{"class":479},"  -p",[462,2151,2152],{"class":479}," 3000:3000",[462,2154,2134],{"class":1301},[462,2156,2157,2160,2163,2165,2168,2170],{"class":464,"line":490},[462,2158,2159],{"class":479},"  -e",[462,2161,2162],{"class":479}," ENCRYPTION_KEY=",[462,2164,511],{"class":503},[462,2166,2167],{"class":479},"\u003Cgenerated_key>",[462,2169,511],{"class":503},[462,2171,2134],{"class":1301},[462,2173,2174,2176,2179,2181,2184,2186],{"class":464,"line":535},[462,2175,2159],{"class":479},[462,2177,2178],{"class":479}," APP_URL=",[462,2180,511],{"class":503},[462,2182,2183],{"class":479},"https:\u002F\u002Ftrek.pafor.me",[462,2185,511],{"class":503},[462,2187,2134],{"class":1301},[462,2189,2190,2193,2196],{"class":464,"line":540},[462,2191,2192],{"class":479},"  -v",[462,2194,2195],{"class":479}," .\u002Fdata:\u002Fapp\u002Fdata",[462,2197,2134],{"class":1301},[462,2199,2200,2202,2205],{"class":464,"line":553},[462,2201,2192],{"class":479},[462,2203,2204],{"class":479}," .\u002Fuploads:\u002Fapp\u002Fuploads",[462,2206,2134],{"class":1301},[462,2208,2209,2212,2215],{"class":464,"line":558},[462,2210,2211],{"class":479},"  --restart",[462,2213,2214],{"class":479}," unless-stopped",[462,2216,2134],{"class":1301},[462,2218,2219],{"class":464,"line":570},[462,2220,2221],{"class":479},"  mauriceboe\u002Ftrek:latest\n",[582,2223,2224],{},[585,2225,2226,2232],{},[441,2227,2228,2231],{},[432,2229,2230],{},"APP_URL"," must be set correctly"," — the MCP server's OAuth discovery flow depends on it. Set it to your final public HTTPS address from the start.",[428,2234,2235],{},"The first run takes a while to pull the image:",[966,2237],{"src":2238,"alt":2239,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-docker-pull-image.webp","Docker pull and run logs for TREK","max-width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2242,2243],{},"Verify it's running:",[454,2245,2247],{"className":456,"code":2246,"language":458,"meta":423,"style":423},"docker ps\n",[432,2248,2249],{"__ignoreMap":423},[462,2250,2251,2253],{"class":464,"line":465},[462,2252,2049],{"class":493},[462,2254,2255],{"class":479}," ps\n",[966,2257],{"src":2258,"alt":2259,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-docker-ps-status.webp","Verifying running container status via docker ps",[1165,2261,2263],{"id":2262},"_2-setting-up-domain-routing-ssl-with-caddy-reverse-proxy","2. Setting Up Domain Routing & SSL with Caddy Reverse Proxy",[428,2265,2266],{},"HTTPS is required for passkeys, and OAuth for MCP. The domain name is hosted on Cloudflare which comes with free SSL certificate and DDoS protection.",[428,2268,2269],{},"Caddy is set up as the secure reverse server to point to point 3000. An example of Caddyfile as follow:",[454,2271,2273],{"className":1284,"code":2272,"language":1286,"meta":423,"style":423},"{$TREK_DOMAIN} {\n  encode zstd gzip\n  reverse_proxy host.docker.internal:3000\n}\n",[432,2274,2275,2288,2293,2303],{"__ignoreMap":423},[462,2276,2277,2280,2283,2286],{"class":464,"line":465},[462,2278,2279],{"class":503},"{",[462,2281,2282],{"class":1301},"$TREK_DOMAIN",[462,2284,2285],{"class":503},"}",[462,2287,1540],{"class":503},[462,2289,2290],{"class":464,"line":472},[462,2291,2292],{"class":1301},"  encode zstd gzip\n",[462,2294,2295,2298,2300],{"class":464,"line":483},[462,2296,2297],{"class":1301},"  reverse_proxy host.docker.internal",[462,2299,940],{"class":503},[462,2301,2302],{"class":2108},"3000\n",[462,2304,2305],{"class":464,"line":490},[462,2306,2307],{"class":503},"}\n",[1165,2309,2311],{"id":2310},"_3-initial-configuration-secure-admin-setup","3. Initial Configuration & Secure Admin Setup",[428,2313,2314],{},"There are two ways of creating the admin account:",[582,2316,2317,2328],{},[585,2318,2319,2327],{},[441,2320,2321,435,2324],{},[432,2322,2323],{},"ADMIN_EMAIL",[432,2325,2326],{},"ADMIN_PASSWORD"," are set as environment variables; those values are used directly.",[585,2329,2330,2331,2334,2335,2338,2339,2342,2343,2346],{},"TREK creates email ",[432,2332,2333],{},"admin@trek.local",", username ",[432,2336,2337],{},"admin",", and a ",[441,2340,2341],{},"randomly generated password printed to the container log",". Run ",[432,2344,2345],{},"docker logs trek"," to retrieve it.",[428,2348,2349],{},"If the password can't be found from the log, reset it:",[454,2351,2353],{"className":456,"code":2352,"language":458,"meta":423,"style":423},"docker exec -it -e RESET_ADMIN_EMAIL=admin@trek.local -e RESET_ADMIN_PASSWORD='YourNewPassword' trek node server\u002Freset-admin.js\n",[432,2354,2355],{"__ignoreMap":423},[462,2356,2357,2359,2362,2365,2368,2371,2373,2376,2379,2382,2384,2386,2389],{"class":464,"line":465},[462,2358,2049],{"class":493},[462,2360,2361],{"class":479}," exec",[462,2363,2364],{"class":479}," -it",[462,2366,2367],{"class":479}," -e",[462,2369,2370],{"class":479}," RESET_ADMIN_EMAIL=admin@trek.local",[462,2372,2367],{"class":479},[462,2374,2375],{"class":479}," RESET_ADMIN_PASSWORD=",[462,2377,2378],{"class":503},"'",[462,2380,2381],{"class":479},"YourNewPassword",[462,2383,2378],{"class":503},[462,2385,2142],{"class":479},[462,2387,2388],{"class":479}," node",[462,2390,2391],{"class":479}," server\u002Freset-admin.js\n",[428,2393,2394],{},"You will be prompted to change the password on first login.",[966,2396],{"src":2397,"alt":2398,"style":2399},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-initial-login-password-prompt.webp","Initial login and admin password reset prompt","max-width: 215px; width:100% height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2401,1173,2402,2405,2406],{},[441,2403,2404],{},"Admin"," and update the email:",[966,2407],{"src":2408,"alt":2409,"style":2410},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-admin-email-update-panel.webp","Setting up custom email in TREK admin settings","max-width: 700px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2412,2414],{"id":2413},"_31-backups","3.1 Backups",[428,2416,2417,2418],{},"Configure the automatic backups with a retention policy in the admin panel:\n",[966,2419],{"src":2420,"alt":2421,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-admin-backup-retention-policy.webp","Configuring automated backup schedules and retention rules",[1702,2423,2425],{"id":2424},"_32-store-uploaded-files-to-cloudflare-r2","3.2 Store Uploaded Files to Cloudflare R2",[428,2427,2428],{},"Storing uploaded files, photos, and backups in Cloudflare R2 keeps the VPS disk clean and light. TREK supports S3-compatible backends, and Cloudflare R2 fits this perfectly.",[670,2430,2431,2437,2450,2461,2472,2487,2498,2513],{},[585,2432,2433,2434,444],{},"Create an R2 bucket called ",[432,2435,2436],{},"trek",[585,2438,2439,2440,2443,2444,2445],{},"In the ",[441,2441,2442],{},"Account Details"," section, find your account ID:","\n  ",[966,2446],{"src":2447,"alt":2448,"style":2449},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fcloudflare-r2-account-details-id.webp","Locating Cloudflare account ID in portal","max-width: 325px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[585,2451,2452,2453,940,2444,2456],{},"Click ",[441,2454,2455],{},"Manage API Tokens",[966,2457],{"src":2458,"alt":2459,"style":2460},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fcloudflare-r2-manage-api-tokens-button.webp","Cloudflare portal Manage API Tokens screen","max-width: 282px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[585,2462,2452,2463,2466,2444,2467],{},[441,2464,2465],{},"Create Account API token"," with read\u002Fwrite permissions for the bucket:",[966,2468],{"src":2469,"alt":2470,"style":2471},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fcloudflare-r2-create-token-permissions.webp","Creating R2 access token with read and write permissions","max-width: 360px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[585,2473,2452,2474,2477,2478,2481,2444,2482],{},[441,2475,2476],{},"Storage"," on ",[441,2479,2480],{},"ADMINISTRATION"," panel:",[966,2483],{"src":2484,"alt":2485,"style":2486},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-administration-storage-menu.webp","Navigating to storage settings in TREK control panel","max-width: 539px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[585,2488,2452,2489,2492,2444,2493],{},[441,2490,2491],{},"Add Backend"," button and fill in the endpoint, bucket, and credentials:",[966,2494],{"src":2495,"alt":2496,"style":2497},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-add-storage-backend-credentials.webp","Configuring S3 compatible Cloudflare R2 storage backend","max-width: 445px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[585,2499,2452,2500,2503,2504,2507,2444,2508],{},[441,2501,2502],{},"Apply",", then the ",[441,2505,2506],{},"Test"," link button. You want to see \"Connection OK\":",[966,2509],{"src":2510,"alt":2511,"style":2512},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-test-storage-backend-connection-ok.webp","Successful storage connection test showing Connection OK","max-width: 677px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[585,2514,2515,2516,940,2444,2519],{},"Switch all storage categories to Cloudflare R2 and click ",[441,2517,2518],{},"Save changes",[966,2520],{"src":2521,"alt":2522,"style":2523},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-switch-storage-categories-r2.webp","Routing all file storage categories to Cloudflare R2","max-width: 653px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2525,2527],{"id":2526},"_33-passkey-login","3.3 Passkey Login",[428,2529,2530,2531,940],{},"TREK supports passkeys, two-factor authentication, and OIDC single sign-on. For passkeys, enter your domain name and allowed origins in settings, then click ",[441,2532,2533],{},"Save",[966,2535],{"src":2536,"alt":2537,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-passkey-allowed-origins-settings.webp","Registering allowed origins for secure Passkey authentication",[428,2539,2540,2541,2544],{},"Without the ",[441,2542,2543],{},"allowed origins"," configured, passkey registration will fail.",[1702,2546,2548],{"id":2547},"_34-google-maps-api-key","3.4 Google Maps API Key",[428,2550,2551],{},"A Google Maps key enriches place search with ratings, opening hours, and photos. TREK automatically falls back to OpenStreetMap with no key required, just without ratings and photos.",[428,2553,2554,2555,2560,2561,2564,2565],{},"Follow this ",[633,2556,2559],{"href":2557,"rel":2558},"https:\u002F\u002Fmapsplatform.google.com\u002Fmaps-demo-key\u002F",[664],"link"," and click ",[441,2562,2563],{},"Get demo key"," to request one:                                                  ",[966,2566],{"src":2567,"alt":2568,"style":2569},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fgoogle-maps-get-demo-api-key.webp","Requesting Google Maps Platform API key","max-width: 176px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2571,2572,2573,2575,2576],{},"Paste the key in settings and click ",[441,2574,2506],{}," to confirm the connection:\n",[966,2577],{"src":2578,"alt":2579,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-google-maps-key-test-connection.webp","Verifying Google Maps API key connectivity in settings",[1702,2581,2583],{"id":2582},"_35-ai-integration","3.5 AI Integration",[428,2585,2586],{},"The AI model is used to parse booking confirmation emails and PDFs into structured reservations.",[428,2588,2452,2589,2592,2593,2596],{},[441,2590,2591],{},"Addons"," in the left menu and enable ",[441,2594,2595],{},"AI Parsing",". Select \"OpenAI\" (or another compatible provider) and fill in the provider details:",[966,2598],{"src":2599,"alt":2600,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-addons-enable-ai-parsing-openai.webp","Enabling AI Parsing addon with OpenAI integration",[1702,2602,2604],{"id":2603},"_36-mcp-access","3.6 MCP Access",[428,2606,2607,2608,2610,2611,940],{},"Under ",[441,2609,2591],{},", enable ",[441,2612,1865],{},[966,2614],{"src":2615,"alt":2616,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-addons-enable-mcp.webp","Activating Model Context Protocol MCP server addon",[1702,2618,2620],{"id":2619},"_37-plugins","3.7 Plugins",[428,2622,2623],{},"The following plugins are recommended and worth activating:",[966,2625],{"src":2626,"alt":2627,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-recommended-addons-plugins-activation.webp","List of active recommended plugins and addons",[1702,2629,2631],{"id":2630},"_38-create-your-everyday-user","3.8 Create Your Everyday User",[428,2633,2634],{},"Plan trips as a normal user, not as an admin. Create a regular user and log in with it:",[966,2636],{"src":2637,"alt":2638,"style":2639},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-create-regular-user-form.webp","Creating a regular user account in TREK panel","max-width: 420px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2641,2642],{},"Once logged in, add a passkey or set up 2FA to harden the account:",[966,2644],{"src":2645,"alt":2646,"style":2647},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-user-security-passkey-2fa-setup.webp","Configuring user security settings with Passkeys and 2FA","max-width: 381px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2649,2452,2650,2653],{},[441,2651,2652],{},"+ Add a passkey",", enter the current password, and confirm:",[966,2655],{"src":2656,"alt":2657,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-add-passkey-confirm-password.webp","Confirming password to register new hardware Passkey",[1165,2659,2661],{"id":2660},"_4-testing-your-deployment-importing-historical-travel-data","4. Testing Your Deployment: Importing Historical Travel Data",[428,2663,2664],{},"A good way to learn TREK is to build up your travel history.",[1702,2666,2668],{"id":2667},"_41-create-the-trip","4.1 Create the trip",[428,2670,2452,2671,2674,2675,435,2678,2681],{},[441,2672,2673],{},"+ New Trip"," and set the ",[441,2676,2677],{},"Start Date",[441,2679,2680],{},"End Date"," to the past dates of the trip:",[966,2683],{"src":2684,"alt":2685,"style":2686},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-create-new-trip-details.webp","Creating a new trip with custom date ranges","max-width: 334px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2688,2689,2690,940],{},"Add a cover image (drag one in, or paste from the clipboard) and click ",[441,2691,2692],{},"Create New Trip",[966,2694],{"src":2695,"alt":2696,"style":2697},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-cover-image-upload.webp","Setting up high-quality trip cover image","max-width: 608px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2699,2701],{"id":2700},"_42-import-the-bookings","4.2 Import the bookings",[428,2703,2704],{},"Drop all the flight, train, and other transportation files in:",[966,2706],{"src":2707,"alt":2708,"style":2709},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-import-travel-booking-files.webp","Drag and drop area to import travel PDFs and bookings","max-width: 570px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2711],{"src":2712,"alt":2713,"style":2714},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-import-booking-pdf-processing-status.webp","Uploaded reservation processing window showing extraction","max-width: 377px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2716,2717],{},"With AI model enabled, booking confirmation PDFs are parsed and extracted into structured reservations.",[428,2719,2720,2721,2724],{},"Review the parsed result and click ",[441,2722,2723],{},"Add"," to commit the booking detail:",[966,2726],{"src":2727,"alt":2728,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-review-parsed-booking-details.webp","Reviewing structured booking details extracted by AI",[428,2730,2731],{},"If a booking only exists in an email, export the email as a PDF and dump it in — the same extraction pipeline applies.",[428,2733,2734],{},"The following screenshots show how bookings are displayed:",[428,2736,2737,2741],{},[966,2738],{"src":2739,"alt":2740,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-bookings-timeline-view.webp","Comprehensive timeline display of travel bookings",[966,2742],{"src":2743,"alt":2744,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-booking-confirmation-details.webp","Detailed view of a confirmed transport reservation",[428,2746,2747,2748,2751],{},"On the ",[441,2749,2750],{},"Plan"," page, all the accommodations will be displayed on the map:",[966,2753],{"src":2754,"alt":2755,"style":2756},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-plan-accommodations-map-display.webp","Interactive map plotting all hotel accommodations","max-width: 546px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2758,2452,2759,2762],{},[441,2760,2761],{},"Atlas"," on the top menu bar for a list (and map) of every country you've visited:",[966,2764],{"src":2765,"alt":2766,"style":2767},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-atlas-countries-visited-summary.webp","Travel history overview in the personal Atlas tracker","max-width: 407px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2769,2771],{"id":2770},"_43-add-travel-companions","4.3 Add travel companions",[428,2773,2774,2775,2778],{},"Click the ",[441,2776,2777],{},"Share"," button:",[966,2780],{"src":2781,"alt":2782,"style":2783},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-share-options-button.webp","Opening the trip sharing dialog in TREK","max-width: 224px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2785,2786],{},"At the bottom of the dialog, guests can be added:",[966,2788],{"src":2789,"alt":2790,"style":2791},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-add-companions-guests.webp","Adding custom traveling companions and guests","max-width: 635px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2793,2795],{"id":2794},"_44-record-the-expenses","4.4 Record the expenses",[428,2797,2452,2798,2801],{},[441,2799,2800],{},"Add expense"," to add costs other than bookings such as health insurance, local transport, SIM cards:",[966,2803],{"src":2804,"alt":2805,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-add-custom-expense-form.webp","Inputting detailed spending data in expense form",[966,2807],{"src":2808,"alt":2809,"style":2810},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-expenses-list-billing-split.webp","Split bill breakdown and cost tracking ledger","max-width: 526px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2812,2814],{"id":2813},"_45-trip-segments","4.5 Trip segments",[428,2816,2817],{},"This feature requires the Trip Segment plugin to be installed.",[428,2819,2820],{},"Long trips break down into segments nicely, with each leg displaying its own bookings, places, and costs:",[966,2822],{"src":2823,"alt":2824,"style":2825},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-segments-overview-display.webp","Breaking down a complex itinerary into travel segments","max-width: 465px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2827],{"src":2828,"alt":2829,"style":2830},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-segment-itinerary-details.webp","Active travel segment displaying places and schedules","max-width: 596px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2832],{"src":2833,"alt":2834,"style":2835},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-trip-segments-interactive-map.webp","Mapping out distinct trip legs on the timeline","max-width: 605px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,2837,2839],{"id":2838},"_46-create-a-journey-and-check-your-atlas","4.6 Create a journey and check your atlas",[428,2841,2842,2843,2846],{},"Group trips into a ",[441,2844,2845],{},"Journey"," and write stories to share the adventure with friends:",[966,2848],{"src":2849,"alt":2850,"style":2851},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-create-new-journey-group.webp","Consolidating multiple trips into a visual Journey","max-width: 441px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2853],{"src":2854,"alt":2855,"style":2856},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-journey-timeline-story-writing.webp","Drafting visual stories in the Journey panel","max-width: 443px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2858],{"src":2859,"alt":2860,"style":2861},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-journey-gallery-media-grid.webp","Media collection and gallery grid inside a Journey","max-width: 440px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2863],{"src":2864,"alt":2865,"style":2866},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-journey-public-share-link.webp","Generating public share links for collaborative Journeys","max-width: 532px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1165,2868,2870],{"id":2869},"_5-designing-custom-itineraries-and-packing-lists","5. Designing Custom Itineraries and Packing Lists",[428,2872,2452,2873,2875],{},[441,2874,2673],{},", enter a name, and set the dates:",[966,2877],{"src":2878,"alt":2879,"style":2880},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-planning-new-trip-setup.webp","Initial prompt dialog to create an undated trip","max-width: 432px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2882,2883,2886],{},[441,2884,2885],{},"If you haven't fixed the dates yet, leave both empty."," A \"number of days\" field appears (up to 365). Plan first, schedule later.",[1702,2888,2890],{"id":2889},"_51-adding-places","5.1 Adding places",[428,2892,2893],{},"This is the most time-consuming step of any trip planning, and TREK has a couple of ways of doing it:",[966,2895],{"src":2896,"alt":2897,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-add-places-methods-overview.webp","Multi-channel methods to add new places to itineraries",[428,2899,2900,2903],{},[441,2901,2902],{},"1. Right-click the map"," to create a place at that exact location — the address is reverse-geocoded automatically:",[966,2905],{"src":2906,"alt":2907,"style":2908},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-right-click-map-location.webp","Right-clicking the map interface to pinpoint locations","max-width: 632px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2910],{"src":2911,"alt":2912,"style":2913},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-right-click-reverse-geocode-address.webp","Automatic reverse-geocoding of selected map coords","max-width: 628px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2915,2916,2919],{},[441,2917,2918],{},"2. Click + Add Place\u002FActivity"," and search by name",[966,2921],{"src":2922,"alt":2923,"style":2924},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-search-place-by-name-input.webp","Searching for real-world places using text inputs","max-width: 642px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2926],{"src":2927,"alt":2928,"style":2929},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-select-place-search-results-list.webp","Displaying place search results with address overlays","max-width: 594px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,2931],{"src":2932,"alt":2933,"style":2934},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-place-details-rich-info-card.webp","Comprehensive place info card with reviews and ratings","max-width: 568px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2936,2937,2940,2941,700,2944,2947],{},[441,2938,2939],{},"3. Paste a Google Maps URL"," (",[432,2942,2943],{},"maps.app.goo.gl\u002F…",[432,2945,2946],{},"maps.google.com\u002F…",") into the search field. TREK parses out the name, address, and coordinates:",[966,2949],{"src":2950,"alt":2951,"style":2512},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-paste-google-maps-share-link.webp","Parsing locations directly from pasted Google Maps share links",[966,2953],{"src":2954,"alt":2955,"style":2956},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-google-maps-parsed-location.webp","Successful coordinate extraction from maps URL","max-width: 543px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2958,2959,2962,2963,2940,2966,435,2969,2972,2973,2976],{},[441,2960,2961],{},"4. Bulk import"," — the easiest of all. If you already maintain a \"want to go\" list on Google Maps, export it as ",[432,2964,2965],{},".gpx",[432,2967,2968],{},".kml",[432,2970,2971],{},".kmz"," also work) and click ",[441,2974,2975],{},"Import file"," on the right panel to pull everything in at once:",[966,2978],{"src":2979,"alt":2980,"style":2981},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-bulk-import-places-gpx-file.webp","Performing bulk place imports using GPX or KML files","max-width: 389px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2983,2984],{},"Add everything interesting first, regardless of whether it fits the schedule. Allocate places to days later.",[1702,2986,2988],{"id":2987},"_52-day-plans-and-notes","5.2 Day plans and notes",[428,2990,2991],{},"The Day Plan organises places into days, in order. It's a collapsible list per day, and everything is drag-and-drop:",[966,2993],{"src":2994,"alt":2995,"style":2996},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-day-plan-drag-drop-ordering.webp","Customizing daily routes with drag-and-drop actions","max-width: 496px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,2998,2999],{},"The details that make it useful:",[582,3001,3002,3012,3022,3032],{},[585,3003,3004,3007,3008],{},[441,3005,3006],{},"Transport between stops",": the bus icon at the top left of a day adds commuting transport (train, bus, flight legs within the day):\n",[966,3009],{"src":3010,"alt":3011,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-day-plan-commuting-transport-button.webp","Registering commuting transport between day segments",[585,3013,3014,3017,3018],{},[441,3015,3016],{},"Day notes",": the notes icon at the bottom left attaches icon-tagged notes — \"early start today\", \"this museum needs a reservation\":\n",[966,3019],{"src":3020,"alt":3021,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-day-plan-icon-tagged-notes-button.webp","Adding highly visible, icon-tagged custom notes to days",[585,3023,3024,3027,3028],{},[441,3025,3026],{},"Time slots",": drag a place from the right panel into a day, then assign it a time. Places with set times are auto connected on the map:\n",[966,3029],{"src":3030,"alt":3031,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-day-plan-timed-places-routing.webp","Auto-calculated transit routes between timed locations",[585,3033,3034,3035,3040,3041,435,3044,444],{},"Please refer to ",[633,3036,3039],{"href":3037,"rel":3038},"https:\u002F\u002Fgithub.com\u002Fliketrek\u002FTREK\u002Fwiki\u002FDay-Plans-and-Notes",[664],"Day Plans and Notes wiki page"," for ",[441,3042,3043],{},"Route optimisation",[441,3045,3046],{},"Weather",[1702,3048,3050],{"id":3049},"_53-collections-reusable-place-lists","5.3 Collections: reusable place lists",[428,3052,3053,3054,3057],{},"Collections allows the user to save a list of places outside of any trip. It can be shared with friends, and ready for the next trip. Places are ",[441,3055,3056],{},"copied"," into trips, so editing a trip entry never mutates your collection and vice versa.",[428,3059,2452,3060,3063],{},[441,3061,3062],{},"Collections"," in the top menu bar:",[966,3065],{"src":3066,"alt":3067,"style":3068},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-dashboard-view.webp","Accessing custom user collections for saved places","max-width: 495px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3070,2452,3071,3074],{},[441,3072,3073],{},"+ New list"," to create one:",[966,3076],{"src":3077,"alt":3078,"style":3079},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-create-new-list.webp","Creating custom lists in user collections","max-width: 269px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3081,2452,3082,3085],{},[441,3083,3084],{},"+ Add a place"," and fill in the details:",[966,3087],{"src":3088,"alt":3089,"style":3090},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-add-place-manually-form.webp","Manual form entry to populate custom collection lists","max-width: 271px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3092,3093,3096],{},[441,3094,3095],{},"Note:"," the search inside the \"Add a place\" dialog does not seem to work, so you will need to enter details manually.",[428,3098,3099],{},"If geo-coordinates of the places are available, the places show up on the map:",[966,3101],{"src":3102,"alt":3103,"style":3104},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-map-places-display.webp","Visualizing custom collection places on an interactive map","max-width: 592px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3106,3107,3108,3111],{},"To organise places with labels, click the ",[441,3109,3110],{},"tick-box"," icon:",[966,3113],{"src":3114,"alt":3115,"style":3116},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-select-places-tickbox.webp","Selection mode for bulk labeling of saved places","max-width: 662px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3118,3119,3120,940],{},"Select the places to group, then click ",[441,3121,3122],{},"Assign label",[966,3124],{"src":3125,"alt":3126,"style":2956},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-group-assign-label.webp","Assigning descriptive labels to selected collection spots",[428,3128,2452,3129,3132],{},[441,3130,3131],{},"Manage labels"," to create labels first:",[966,3134],{"src":3135,"alt":3136,"style":3137},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-manage-custom-labels.webp","Creation and management of custom labels","max-width: 411px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3139,3140,3141,940],{},"Select a label and click ",[441,3142,3122],{},[966,3144],{"src":3145,"alt":3146,"style":2767},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-collections-confirm-label-selection.webp","Applying custom labels to group places",[1702,3148,3150],{"id":3149},"_54-costs-and-budget","5.4 Costs and budget",[428,3152,3153],{},"We can add other expenses for the trip on the 'Costs' page.",[966,3155],{"src":3156,"alt":3157,"style":2996},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-costs-budget-overall-expenses-list.webp","Comprehensive expenses table and balance settling ledger",[428,3159,3160],{},"Payments made by travel companions can be added and split on the same page.",[428,3162,3163,3164,3167],{},"The settlement panel runs a greedy-matching algorithm to compute the ",[441,3165,3166],{},"minimum number of transfers"," for who owes whom, and how much.",[1165,3169,3171],{"id":3170},"_6-leveraging-model-context-protocol-mcp-for-ai-powered-travel-planning","6. Leveraging Model Context Protocol (MCP) for AI-Powered Travel Planning",[428,3173,3174,3175,3178],{},"TREK has a built-in ",[441,3176,3177],{},"MCP (Model Context Protocol) server",", which lets AI agents read and write your travel data directly — over 150 tools and 30 resources covering trips, places, budgets, packing, bookings, and collaboration.",[1702,3180,3182],{"id":3181},"_61-cloudflare-zero-trust","6.1 Cloudflare Zero Trust",[428,3184,3185,3186,3189,3190,444],{},"Because TREK is running behind a ",[633,3187,3188],{"href":363},"Cloudflare Zero Trust"," network, you will need to add the domain to the split tunnels inclusion list. Otherwise, you will have issues with OAuth authorisation. Please refer to this GitHub issue: ",[633,3191,3194],{"href":3192,"rel":3193},"https:\u002F\u002Fgithub.com\u002Fliketrek\u002FTREK\u002Fissues\u002F1463",[664],"github issue",[3196,3197],"article-card",{"description":3198,"image":3199,"image-alt":3200,"label":3201,"min-read":3202,"title":362,"to":363},"Learn how to securely expose and access your Hermes Agent globally using Cloudflare WARP and Zero Trust without opening inbound firewall ports.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002FEN-Exposing-Hermes-Agent-to-Private-Network-Using-Cloudflare-WARP.webp","Securely exposing Hermes Agent to a private network using Cloudflare Zero Trust and WARP tunnel","Related guide","8",[966,3204],{"src":3205,"alt":3206,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fcloudflare-zero-trust-split-tunnels-domain.webp","Adding custom domains to Cloudflare Warp Split Tunnels",[1702,3208,3210],{"id":3209},"_62-claude-desktop","6.2 Claude Desktop",[428,3212,2452,3213,3216,3217],{},[441,3214,3215],{},"+ New Client"," to create an AI agent client:\n",[966,3218],{"src":3219,"alt":3220,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-register-new-mcp-client.webp","Registering a new custom client token in settings",[428,3222,3223,3224,3226,3227,940],{},"Select the ",[441,3225,1580],{}," tab and click ",[441,3228,3229],{},"Register Client",[966,3231],{"src":3232,"alt":3233,"style":3234},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-mcp-claude-desktop-client-credentials.webp","Generating Claude Desktop client credentials","max-width: 354px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3236,3237,3238,3241],{},"A client ID and client secret pair is displayed. Copy them somewhere safe. Then click ",[441,3239,3240],{},"Client Configuration"," to show the MCP config:",[966,3243],{"src":3244,"alt":3245,"style":3246},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-mcp-client-configuration-block.webp","Retrieving pre-formatted MCP server configuration block","max-width: 508px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3248,3249,3250,3253],{},"In Claude Desktop, click ",[441,3251,3252],{},"Edit Config"," to open the local MCP servers configuration file:",[966,3255],{"src":3256,"alt":3257,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fclaude-desktop-mcp-config-json.webp","Editing Claude Desktop local MCP config json file",[428,3259,3260],{},"Paste the TREK config, replacing the placeholders with your credentials:",[454,3262,3264],{"className":1284,"code":3263,"language":1286,"meta":423,"style":423},"  \"mcpServers\": {\n    \"trek\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"mcp-remote\",\n        \"https:\u002F\u002Ftrek.pafor.me\u002Fmcp\",\n        \"--static-oauth-client-info\",\n        \"{\\\"client_id\\\": \\\"\u003Cyour_client_id>\\\", \\\"client_secret\\\": \\\"\u003Cyour_client_secret>\\\"}\"\n      ]\n    }\n  },\n",[432,3265,3266,3279,3291,3309,3321,3331,3342,3353,3398,3402,3406],{"__ignoreMap":423},[462,3267,3268,3271,3273,3275,3277],{"class":464,"line":465},[462,3269,3270],{"class":503},"  \"",[462,3272,1277],{"class":479},[462,3274,511],{"class":503},[462,3276,730],{"class":1301},[462,3278,1304],{"class":503},[462,3280,3281,3283,3285,3287,3289],{"class":464,"line":472},[462,3282,1293],{"class":503},[462,3284,2436],{"class":1312},[462,3286,511],{"class":503},[462,3288,940],{"class":503},[462,3290,1540],{"class":503},[462,3292,3293,3295,3297,3299,3301,3303,3305,3307],{"class":464,"line":483},[462,3294,1309],{"class":503},[462,3296,1313],{"class":493},[462,3298,511],{"class":503},[462,3300,940],{"class":503},[462,3302,504],{"class":503},[462,3304,494],{"class":479},[462,3306,511],{"class":503},[462,3308,1326],{"class":503},[462,3310,3311,3313,3315,3317,3319],{"class":464,"line":490},[462,3312,1309],{"class":503},[462,3314,1333],{"class":493},[462,3316,511],{"class":503},[462,3318,940],{"class":503},[462,3320,1340],{"class":503},[462,3322,3323,3325,3327,3329],{"class":464,"line":535},[462,3324,1345],{"class":503},[462,3326,1348],{"class":479},[462,3328,511],{"class":503},[462,3330,1326],{"class":503},[462,3332,3333,3335,3338,3340],{"class":464,"line":540},[462,3334,1345],{"class":503},[462,3336,3337],{"class":479},"https:\u002F\u002Ftrek.pafor.me\u002Fmcp",[462,3339,511],{"class":503},[462,3341,1326],{"class":503},[462,3343,3344,3346,3349,3351],{"class":464,"line":553},[462,3345,1345],{"class":503},[462,3347,3348],{"class":479},"--static-oauth-client-info",[462,3350,511],{"class":503},[462,3352,1326],{"class":503},[462,3354,3355,3357,3359,3362,3365,3367,3369,3371,3374,3376,3378,3380,3383,3385,3387,3389,3392,3394,3396],{"class":464,"line":558},[462,3356,1345],{"class":503},[462,3358,2279],{"class":479},[462,3360,3361],{"class":1301},"\\\"",[462,3363,3364],{"class":479},"client_id",[462,3366,3361],{"class":1301},[462,3368,730],{"class":479},[462,3370,3361],{"class":1301},[462,3372,3373],{"class":479},"\u003Cyour_client_id>",[462,3375,3361],{"class":1301},[462,3377,737],{"class":479},[462,3379,3361],{"class":1301},[462,3381,3382],{"class":479},"client_secret",[462,3384,3361],{"class":1301},[462,3386,730],{"class":479},[462,3388,3361],{"class":1301},[462,3390,3391],{"class":479},"\u003Cyour_client_secret>",[462,3393,3361],{"class":1301},[462,3395,2285],{"class":479},[462,3397,550],{"class":503},[462,3399,3400],{"class":464,"line":570},[462,3401,1388],{"class":503},[462,3403,3404],{"class":464,"line":2007},[462,3405,1393],{"class":503},[462,3407,3408,3411],{"class":464,"line":2013},[462,3409,3410],{"class":503},"  }",[462,3412,1326],{"class":1301},[428,3414,3415,3416,940],{},"Restart Claude Desktop, and the TREK server shows as connected under ",[441,3417,3418],{},"Local MCP servers",[966,3420],{"src":3421,"alt":3422,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fclaude-desktop-mcp-trek-server-connected.webp","Verifying active TREK connection status inside Claude UI",[428,3424,3425],{},"Now run a prompt:",[966,3427],{"src":3428,"alt":3429,"style":3430},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fclaude-desktop-mcp-natural-language-prompt.webp","Prompting Claude in natural language to manipulate travel data","max-width: 550px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3432,3433],{},"Let's add an expense in natural language:",[454,3435,3438],{"className":3436,"code":3437,"language":1612,"meta":423},[1610],"For the West Europe trip, the Grab from KLIA1 to the hotel cost RM115.90 on 26\u002F4\u002F2025. Please add it as an expense without split to the trip.\n",[432,3439,3437],{"__ignoreMap":423},[966,3441],{"src":3442,"alt":3443,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fclaude-desktop-mcp-add-expense-response.webp","Claude utilizing tools to automatically record an expense",[428,3445,3446,3447,3450],{},"Checking the ",[441,3448,3449],{},"Costs"," page, the expense is created with \"No one paid yet\", since no payer was mentioned:",[966,3452],{"src":3453,"alt":3454,"style":2410},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-costs-page-mcp-parsed-expense.webp","Confirming the newly parsed AI expense in the Costs view",[428,3456,3457],{},"Adding to the packing list works the same way:",[966,3459],{"src":3460,"alt":3461,"style":3462},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fclaude-desktop-mcp-add-packing-items.webp","Claude adding packing items using natural language prompts","max-width: 631px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3464,3465,3466,3469],{},"Refresh the ",[441,3467,3468],{},"Packing List"," page and the three items are there:",[966,3471],{"src":3472,"alt":3473,"style":3474},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Ftrek-packing-list-mcp-parsed-items.webp","Confirming newly parsed packing items on the Packing List page","max-width: 312px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[1702,3476,3478],{"id":3477},"_63-gemini-cli-dynamic-registration","6.3 Gemini CLI (dynamic registration)",[428,3480,3481,3482,3485,3486,940],{},"Gemini CLI supports ",[441,3483,3484],{},"dynamic registration",", that is no pre-created client needed. Add this to ",[432,3487,3488],{},".gemini\u002Fsettings.json",[454,3490,3492],{"className":1284,"code":3491,"language":1286,"meta":423,"style":423},"    \"trek\": {\n      \"httpUrl\": \"https:\u002F\u002Ftrek.pafor.me\u002Fmcp\",\n      \"oauth\": {\n        \"enabled\": true\n      }\n    }\n",[432,3493,3494,3506,3524,3536,3548,3552],{"__ignoreMap":423},[462,3495,3496,3498,3500,3502,3504],{"class":464,"line":465},[462,3497,1293],{"class":503},[462,3499,2436],{"class":479},[462,3501,511],{"class":503},[462,3503,730],{"class":1301},[462,3505,1304],{"class":503},[462,3507,3508,3510,3512,3514,3516,3518,3520,3522],{"class":464,"line":472},[462,3509,1309],{"class":503},[462,3511,1514],{"class":1312},[462,3513,511],{"class":503},[462,3515,940],{"class":503},[462,3517,504],{"class":503},[462,3519,3337],{"class":479},[462,3521,511],{"class":503},[462,3523,1326],{"class":503},[462,3525,3526,3528,3530,3532,3534],{"class":464,"line":483},[462,3527,1309],{"class":503},[462,3529,1533],{"class":1312},[462,3531,511],{"class":503},[462,3533,940],{"class":503},[462,3535,1540],{"class":503},[462,3537,3538,3540,3542,3544,3546],{"class":464,"line":490},[462,3539,1345],{"class":503},[462,3541,1547],{"class":493},[462,3543,511],{"class":503},[462,3545,940],{"class":503},[462,3547,1554],{"class":503},[462,3549,3550],{"class":464,"line":535},[462,3551,1559],{"class":503},[462,3553,3554],{"class":464,"line":540},[462,3555,1393],{"class":503},[428,3557,3558,3559,3562,3563,3566,3567],{},"Run ",[432,3560,3561],{},"gemini"," in the terminal and click ",[441,3564,3565],{},"Approve"," when the authorisation prompt appears:\n",[966,3568],{"src":3569,"alt":3570,"style":3571},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fmcp-client-oauth-authorization-prompt.webp","Approving OAuth access for the TREK MCP server","max-width: 488px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3573,3574],{},"Then start with a simple prompt:",[966,3576],{"src":3577,"alt":3578,"style":3579},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fgemini-cli-mcp-prompt-itinerary.webp","Prompting Gemini CLI to fetch travel itineraries","max-width: 415px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[966,3581],{"src":3582,"alt":3583,"style":2861},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fgemini-cli-mcp-display-itinerary.webp","Gemini CLI successfully displaying structured trip information",[1702,3585,3587],{"id":3586},"_64-kimi-cli-dynamic-registration","6.4 Kimi CLI (dynamic registration)",[428,3589,3590,3591,3594,3595,3598],{},"Same approach — add to ",[432,3592,3593],{},"mcp.json"," in the ",[432,3596,3597],{},"\u002FUsers\u002F\u003Cuser>\u002F.kimi\u002F"," folder:",[454,3600,3602],{"className":1284,"code":3601,"language":1286,"meta":423,"style":423},"    \"trek\": {\n      \"type\": \"http\",\n      \"url\": \"https:\u002F\u002Ftrek.pafor.me\u002Fmcp\",\n      \"auth\": \"oauth\"\n    }\n",[432,3603,3604,3616,3636,3655,3672],{"__ignoreMap":423},[462,3605,3606,3608,3610,3612,3614],{"class":464,"line":465},[462,3607,1293],{"class":503},[462,3609,2436],{"class":479},[462,3611,511],{"class":503},[462,3613,730],{"class":1301},[462,3615,1304],{"class":503},[462,3617,3618,3620,3623,3625,3627,3629,3632,3634],{"class":464,"line":472},[462,3619,1309],{"class":503},[462,3621,3622],{"class":1312},"type",[462,3624,511],{"class":503},[462,3626,940],{"class":503},[462,3628,504],{"class":503},[462,3630,3631],{"class":479},"http",[462,3633,511],{"class":503},[462,3635,1326],{"class":503},[462,3637,3638,3640,3643,3645,3647,3649,3651,3653],{"class":464,"line":483},[462,3639,1309],{"class":503},[462,3641,3642],{"class":1312},"url",[462,3644,511],{"class":503},[462,3646,940],{"class":503},[462,3648,504],{"class":503},[462,3650,3337],{"class":479},[462,3652,511],{"class":503},[462,3654,1326],{"class":503},[462,3656,3657,3659,3662,3664,3666,3668,3670],{"class":464,"line":490},[462,3658,1309],{"class":503},[462,3660,3661],{"class":1312},"auth",[462,3663,511],{"class":503},[462,3665,940],{"class":503},[462,3667,504],{"class":503},[462,3669,1533],{"class":479},[462,3671,550],{"class":503},[462,3673,3674],{"class":464,"line":535},[462,3675,1393],{"class":503},[428,3677,3558,3678,3562,3681,756,3683],{},[432,3679,3680],{},"kimi mcp auth trek",[441,3682,3565],{},[966,3684],{"src":3569,"alt":3570,"style":3685},"max-width: 453px; width: 100%; height: auto; border-radius: 8px; margin: 1.5rem auto; display: block;",[428,3687,3688],{},"Once authorised, the available tools are listed:",[966,3690],{"src":3691,"alt":3692,"style":2240},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002Fkimi-cli-mcp-authorized-tools-list.webp","Kimi CLI displaying available tools after successful authorization",[1165,3694,3696],{"id":3695},"_7-mobile-experience","7. Mobile Experience",[428,3698,3699],{},"TREK is a PWA (progressive web app) on mobile devices. A service worker caches map tiles and API data, so your itinerary remains readable offline. However, push notifications may experience some latency compared to a native app.",[1165,3701,3703],{"id":3702},"final-thoughts","Final Thoughts",[428,3705,3706],{},"Connecting AI agents through MCP saves a lot of the tedious work of entering flight and accommodation bookings. In addition, agents can suggest places of interest based on your travel dates and season. A single conversation with an AI agent can cover the entire pipeline, from research and itinerary building to budget tracking and packing.",[428,3708,3709],{},"There are some minor technical glitches. For instance, when importing bookings from PDFs, the currency defaults to the trip's base currency rather than the currency actually paid. Also, when creating a new list in Collections, any cover image added during creation disappears on save, though it can be manually added back when editing.",[428,3711,3712,3713,3718],{},"There is a slight technical barrier, as you need to host this on your own server. TREK is primarily designed for people who travel frequently and have high expectations of how they organise their travel data. We suggest trying the official demo at ",[633,3714,3717],{"href":3715,"rel":3716},"https:\u002F\u002Fdemo.liketrek.com\u002F",[664],"demo.liketrek.com"," before considering self-hosting.",[1165,3720,1796],{"id":1795},[582,3722,3723,3730,3737],{},[585,3724,3725],{},[633,3726,3729],{"href":3727,"rel":3728},"https:\u002F\u002Fgithub.com\u002Fliketrek\u002FTREK\u002Fwiki\u002FQuick-Start",[664],"TREK Quick Start",[585,3731,3732],{},[633,3733,3736],{"href":3734,"rel":3735},"https:\u002F\u002Fgithub.com\u002Fliketrek\u002FTREK\u002Fwiki\u002FTroubleshooting",[664],"TREK Troubleshooting",[585,3738,3739],{},[633,3740,3743],{"href":3741,"rel":3742},"https:\u002F\u002Fgithub.com\u002Fliketrek\u002FTREK\u002Fwiki\u002FMCP-Scopes",[664],"TREK MCP Scopes",[1023,3745,3746],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":423,"searchDepth":472,"depth":483,"links":3748},[3749,3754,3755,3765,3773,3779,3785,3786,3787],{"id":1884,"depth":483,"text":1885,"children":3750},[3751,3752,3753],{"id":1888,"depth":490,"text":1889},{"id":2080,"depth":490,"text":2081},{"id":2115,"depth":490,"text":2116},{"id":2262,"depth":483,"text":2263},{"id":2310,"depth":483,"text":2311,"children":3756},[3757,3758,3759,3760,3761,3762,3763,3764],{"id":2413,"depth":490,"text":2414},{"id":2424,"depth":490,"text":2425},{"id":2526,"depth":490,"text":2527},{"id":2547,"depth":490,"text":2548},{"id":2582,"depth":490,"text":2583},{"id":2603,"depth":490,"text":2604},{"id":2619,"depth":490,"text":2620},{"id":2630,"depth":490,"text":2631},{"id":2660,"depth":483,"text":2661,"children":3766},[3767,3768,3769,3770,3771,3772],{"id":2667,"depth":490,"text":2668},{"id":2700,"depth":490,"text":2701},{"id":2770,"depth":490,"text":2771},{"id":2794,"depth":490,"text":2795},{"id":2813,"depth":490,"text":2814},{"id":2838,"depth":490,"text":2839},{"id":2869,"depth":483,"text":2870,"children":3774},[3775,3776,3777,3778],{"id":2889,"depth":490,"text":2890},{"id":2987,"depth":490,"text":2988},{"id":3049,"depth":490,"text":3050},{"id":3149,"depth":490,"text":3150},{"id":3170,"depth":483,"text":3171,"children":3780},[3781,3782,3783,3784],{"id":3181,"depth":490,"text":3182},{"id":3209,"depth":490,"text":3210},{"id":3477,"depth":490,"text":3478},{"id":3586,"depth":490,"text":3587},{"id":3695,"depth":483,"text":3696},{"id":3702,"depth":483,"text":3703},{"id":1795,"depth":483,"text":1796},[3789,1034],"travel","2026-09-01","Learn how to deploy TREK using Docker, secure it via Cloudflare R2 and Caddy, and leverage AI agents with MCP for seamless travel planning.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf%20hosted%20travel%20planner%20TREK\u002FEN-Self-hosted-travel-planner-TREK.webp","A premium minimalist 3D illustration of the TREK self-hosted travel planner dashboard on a warm parchment background.",{"schemaOrg":3795,"robots":1044,"sitemap":3801},[3796,3798],{"@type":3797,"headline":378,"description":3791},"HowTo",{"@type":3799,"headline":3800,"description":3791},"Article","How to Self-Host TREK: The Ultimate AI Travel Planner",{"lastmod":3790},22,{"title":3800,"description":3791,"ogTitle":378,"ogDescription":3791,"twitterTitle":378,"twitterDescription":3791},[3805,3806,3807,1050,1865],"Docker","TREK","Caddy","2026-09-03","hV0BoKmT_W4ef-yv8Igqd32Dqqk7LsAlRAABPpfuoZ8",[3811,5977,5978],{"id":3812,"title":382,"author":423,"body":3813,"category":5944,"date":5946,"description":5947,"extension":1037,"image":5948,"imageAlt":5949,"isPublished":486,"meta":5950,"minRead":2060,"navigation":486,"path":383,"seo":5972,"stem":384,"tags":5974,"updatedAt":1053,"__hash__":5976},"article\u002Fen\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues.md",{"type":425,"value":3814,"toc":5914},[3815,3818,3824,3830,3834,3837,3875,3879,3885,3923,3927,3931,3945,3951,3953,3957,3961,3975,3981,4030,4056,4060,4068,4074,4078,4081,4264,4268,4312,4319,4326,4332,4381,4387,4415,4419,4423,4450,4478,4483,4525,4534,4814,4818,4863,4868,4875,4880,4884,4907,4910,4916,4919,4923,4931,4937,4940,4946,4953,4981,4987,4993,4996,5002,5006,5009,5012,5015,5021,5024,5030,5036,5042,5047,5051,5062,5069,5075,5078,5084,5088,5095,5101,5108,5112,5120,5183,5195,5249,5252,5321,5327,5343,5349,5353,5399,5405,5408,5414,5417,5423,5427,5443,5459,5465,5562,5565,5571,5582,5631,5637,5643,5655,5671,5674,5680,5684,5693,5715,5725,5823,5834,5840,5847,5853,5856,5862,5865,5871,5875,5878,5881,5911],[428,3816,3817],{},"Context fragmentation is a frustrating hurdle when working with multiple AI agents. With conversations scattered across different tools, you end up acting as a human router by copying conversations from Claude Code to paste into Gemini CLI, then copying from Gemini CLI to paste into Hermes Agent. This friction increases when human colleagues are on the same team.",[428,3819,3820],{},[966,3821],{"alt":3822,"src":3823},"The user interface of the Buzz collaborative workspace showing chat channels and active AI agents","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-workspace-interface.webp",[428,3825,3826,3829],{},[441,3827,3828],{},"Buzz",", an open-source collaboration workspace, brings human teams and AI agents together into a single, unified environment. Here, human colleagues and AI agents share the same task and project history, seamlessly handing work off to one another.",[446,3831,3833],{"id":3832},"what-is-blocks-buzz-the-collaborative-ai-agent-workspace","What is Block's Buzz? The Collaborative AI Agent Workspace",[428,3835,3836],{},"Buzz is an open-source collaboration workspace from Block (Jack Dorsey's company) where humans and AI agents share the same channels and projects. It offers the following key features:",[582,3838,3839,3845,3851,3857,3863,3869],{},[585,3840,3841,3844],{},[441,3842,3843],{},"Shared context:"," Channels are where humans and agents collaborate with one another. All conversational and project history is contained within the channel.",[585,3846,3847,3850],{},[441,3848,3849],{},"Agent-to-agent communication:"," Agents can communicate with each other, even across different machines. An agent can @-mention another agent to hand off work or cross-check code.",[585,3852,3853,3856],{},[441,3854,3855],{},"Mention-driven activation:"," Agents only act when @-mentioned, otherwise staying quiet. When mentioned, an agent reads the relevant context in the channel and start working.",[585,3858,3859,3862],{},[441,3860,3861],{},"Unified identity system:"," Humans and agents use the same identity system, authenticated via cryptographic keys.",[585,3864,3865,3868],{},[441,3866,3867],{},"Delegated commands:"," You can grant human colleagues permission to command your agents, allowing the entire team to brief and leverage each other's digital helpers.",[585,3870,3871,3874],{},[441,3872,3873],{},"Self-hosted servers:"," Because you host the server, your data remains fully under your control. You choose who joins and define your own operational rules.",[446,3876,3878],{"id":3877},"the-cryptographic-nostr-powered-architecture-of-buzz","The Cryptographic, Nostr-Powered Architecture of Buzz",[428,3880,3881],{},[966,3882],{"alt":3883,"src":3884},"Cryptographic, Nostr-powered architectural diagram of the Buzz collaboration workspace","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-nostr-cryptographic-architecture.webp",[582,3886,3887,3893,3899,3905,3911,3917],{},[585,3888,3889,3892],{},[441,3890,3891],{},"The Nostr relay acts as the server:"," Messages, workflows, repositories, and other events are cryptographically signed, verified, and stored on a Nostr relay server. The Nostr protocol natively supports communication over WebSockets and REST APIs.",[585,3894,3895,3898],{},[441,3896,3897],{},"Unified cryptographic identity:"," Both humans and agents authenticate using their own cryptographic keys. This identity remains client-side and is never stored on the server.",[585,3900,3901,3904],{},[441,3902,3903],{},"First-class agent membership:"," Every agent possesses its own identity, channel memberships, and audit trail. Agents connect to the workspace using the Agent Communication Protocol (ACP).",[585,3906,3907,3910],{},[441,3908,3909],{},"Decentralised Git repositories:"," Code repositories are stored on S3 compatible object storage, while tasks, pull requests, and code reviews are tracked within the Nostr event log. Consequently, a Buzz Git repository is hosted on the Nostr relay rather than GitHub.",[585,3912,3913,3916],{},[441,3914,3915],{},"The Buzz app is a Nostr client:"," Buzz is separate from the Nostr relay; it is a desktop\u002Fmobile client application that connects to the relay's URL.",[585,3918,3919,3922],{},[441,3920,3921],{},"Infrastructure stack:"," A PostgreSQL database handles event storage and full-text search, Redis manages pub\u002Fsub messaging, and S3 compatible MinIO is used for media storage.",[446,3924,3926],{"id":3925},"how-to-self-host-blocks-buzz-relay-on-a-linux-vps","How to Self-Host Block's Buzz Relay on a Linux VPS",[1165,3928,3930],{"id":3929},"_0-prerequisites","0. Prerequisites",[582,3932,3933,3936,3939,3942],{},[585,3934,3935],{},"A Linux VPS",[585,3937,3938],{},"A domain pointing at your server",[585,3940,3941],{},"Docker and the Docker Compose plugin",[585,3943,3944],{},"Cloudflare account (free tier)",[428,3946,3947,3948,3950],{},"In this guide, we will run the Nostr relay on an Ubuntu VPS behind a ",[633,3949,3188],{"href":363}," private network. The stack is four services in Docker Compose, relay, PostgreSQL, Redis and MinIO.",[3196,3952],{"description":3198,"image":3199,"image-alt":3200,"label":3201,"min-read":3202,"title":362,"to":363},[1165,3954,3956],{"id":3955},"_1-cloudflare-dns-and-api-token","1. Cloudflare DNS and API Token",[1702,3958,3960],{"id":3959},"create-a-cloudflare-api-token","Create a Cloudflare API Token",[670,3962,3963,3970],{},[585,3964,3965,3966,3969],{},"Click on the top right ",[441,3967,3968],{},"Profile"," from the user icon dropdown menu.",[585,3971,1173,3972,444],{},[441,3973,3974],{},"API Tokens",[428,3976,3977],{},[966,3978],{"alt":3979,"src":3980},"Cloudflare user profile page showing the API Tokens creation menu","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fcloudflare-profile-api-tokens.webp",[670,3982,3983,3988,3995,4015,4020,4024,4027],{"start":483},[585,3984,2452,3985,444],{},[441,3986,3987],{},"Create Token",[585,3989,3990,3991,3994],{},"Use the ",[441,3992,3993],{},"Edit zone DNS"," template.",[585,3996,3997,3998],{},"Configure the template as follows:\n",[582,3999,4000,4006],{},[585,4001,4002,4005],{},[441,4003,4004],{},"Permissions",": Zone — DNS — Edit",[585,4007,4008,4011,4012],{},[441,4009,4010],{},"Zone Resources",": Include — Specific zone — ",[432,4013,4014],{},"example.com",[585,4016,2452,4017,444],{},[441,4018,4019],{},"Continue to summary",[585,4021,2452,4022,444],{},[441,4023,3987],{},[585,4025,4026],{},"Copy the generated token as it won't be shown when the page is closed.",[585,4028,4029],{},"Test the generated token in your terminal to ensure it works:",[454,4031,4033],{"className":456,"code":4032,"language":458,"meta":423,"style":423},"curl \"https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4\u002Fuser\u002Ftokens\u002Fverify\" -H \"Authorization: Bearer YOUR_TOKEN_HERE\"\n",[432,4034,4035],{"__ignoreMap":423},[462,4036,4037,4039,4041,4044,4046,4049,4051,4054],{"class":464,"line":465},[462,4038,1904],{"class":493},[462,4040,504],{"class":503},[462,4042,4043],{"class":479},"https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4\u002Fuser\u002Ftokens\u002Fverify",[462,4045,511],{"class":503},[462,4047,4048],{"class":479}," -H",[462,4050,504],{"class":503},[462,4052,4053],{"class":479},"Authorization: Bearer YOUR_TOKEN_HERE",[462,4055,550],{"class":503},[1702,4057,4059],{"id":4058},"dns-records","DNS Records",[582,4061,4062],{},[585,4063,4064,4065,444],{},"Create an A record and set it to ",[441,4066,4067],{},"DNS only",[428,4069,4070],{},[966,4071],{"alt":4072,"src":4073},"Configuring a DNS A record for the Buzz domain in Cloudflare dashboard with proxy status set to DNS only","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fcloudflare-dns-a-record-configuration.webp",[1165,4075,4077],{"id":4076},"_2-install-docker-on-ubuntu","2. Install Docker on Ubuntu",[428,4079,4080],{},"Run the following commands to install Docker on Ubuntu:",[454,4082,4084],{"className":456,"code":4083,"language":458,"meta":423,"style":423},"# Add Docker's official GPG key and set up the Docker repository\ncurl -fsSL https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg | sudo gpg --dearmor -o \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n\n# Add the official Docker repository\necho \"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu $(lsb_release -cs) stable\" | sudo tee \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list > \u002Fdev\u002Fnull\n\n# Update package list\nsudo apt update\n\n# Install Docker Engine, Docker Community Edition, and containerd runtime\nsudo apt install docker-ce docker-ce-cli containerd.io -y\n\n# Start automatically when the system boots\nsudo systemctl enable docker\n\n# Verify docker is installed\ndocker --version\n\nsudo apt install -y docker-compose-plugin\n\n# Verify the compose plugin is installed\ndocker compose version\n\n",[432,4085,4086,4090,4110,4114,4118,4150,4154,4158,4166,4170,4174,4190,4194,4199,4209,4213,4217,4223,4228,4243,4248,4254],{"__ignoreMap":423},[462,4087,4088],{"class":464,"line":465},[462,4089,1899],{"class":468},[462,4091,4092,4094,4096,4098,4100,4102,4104,4106,4108],{"class":464,"line":472},[462,4093,1904],{"class":493},[462,4095,1907],{"class":479},[462,4097,1910],{"class":479},[462,4099,1913],{"class":503},[462,4101,1916],{"class":493},[462,4103,1919],{"class":479},[462,4105,1922],{"class":479},[462,4107,1925],{"class":479},[462,4109,1928],{"class":479},[462,4111,4112],{"class":464,"line":483},[462,4113,487],{"emptyLinePlaceholder":486},[462,4115,4116],{"class":464,"line":490},[462,4117,1937],{"class":468},[462,4119,4120,4122,4124,4126,4128,4130,4132,4134,4136,4138,4140,4142,4144,4146,4148],{"class":464,"line":535},[462,4121,1942],{"class":475},[462,4123,504],{"class":503},[462,4125,1947],{"class":479},[462,4127,1950],{"class":503},[462,4129,1953],{"class":493},[462,4131,1956],{"class":479},[462,4133,1959],{"class":503},[462,4135,1962],{"class":479},[462,4137,511],{"class":503},[462,4139,1913],{"class":503},[462,4141,1916],{"class":493},[462,4143,1971],{"class":479},[462,4145,1974],{"class":479},[462,4147,1977],{"class":503},[462,4149,1980],{"class":479},[462,4151,4152],{"class":464,"line":540},[462,4153,487],{"emptyLinePlaceholder":486},[462,4155,4156],{"class":464,"line":553},[462,4157,1989],{"class":468},[462,4159,4160,4162,4164],{"class":464,"line":558},[462,4161,1994],{"class":493},[462,4163,1997],{"class":479},[462,4165,2000],{"class":479},[462,4167,4168],{"class":464,"line":570},[462,4169,487],{"emptyLinePlaceholder":486},[462,4171,4172],{"class":464,"line":2007},[462,4173,2010],{"class":468},[462,4175,4176,4178,4180,4182,4184,4186,4188],{"class":464,"line":2013},[462,4177,1994],{"class":493},[462,4179,1997],{"class":479},[462,4181,2020],{"class":479},[462,4183,2023],{"class":479},[462,4185,2026],{"class":479},[462,4187,2029],{"class":479},[462,4189,2032],{"class":479},[462,4191,4192],{"class":464,"line":2035},[462,4193,487],{"emptyLinePlaceholder":486},[462,4195,4196],{"class":464,"line":2040},[462,4197,4198],{"class":468},"# Start automatically when the system boots\n",[462,4200,4201,4203,4205,4207],{"class":464,"line":2046},[462,4202,1994],{"class":493},[462,4204,2071],{"class":479},[462,4206,2074],{"class":479},[462,4208,2077],{"class":479},[462,4210,4211],{"class":464,"line":2055},[462,4212,487],{"emptyLinePlaceholder":486},[462,4214,4215],{"class":464,"line":2060},[462,4216,2043],{"class":468},[462,4218,4219,4221],{"class":464,"line":2066},[462,4220,2049],{"class":493},[462,4222,2052],{"class":479},[462,4224,4226],{"class":464,"line":4225},18,[462,4227,487],{"emptyLinePlaceholder":486},[462,4229,4231,4233,4235,4237,4240],{"class":464,"line":4230},19,[462,4232,1994],{"class":493},[462,4234,1997],{"class":479},[462,4236,2020],{"class":479},[462,4238,4239],{"class":479}," -y",[462,4241,4242],{"class":479}," docker-compose-plugin\n",[462,4244,4246],{"class":464,"line":4245},20,[462,4247,487],{"emptyLinePlaceholder":486},[462,4249,4251],{"class":464,"line":4250},21,[462,4252,4253],{"class":468},"# Verify the compose plugin is installed\n",[462,4255,4256,4258,4261],{"class":464,"line":3802},[462,4257,2049],{"class":493},[462,4259,4260],{"class":479}," compose",[462,4262,4263],{"class":479}," version\n",[1165,4265,4267],{"id":4266},"_3-clone-and-configure","3. Clone and configure",[454,4269,4271],{"className":456,"code":4270,"language":458,"meta":423,"style":423},"git clone https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz.git\n\ncd buzz\u002Fdeploy\u002Fcompose\ncp .env.example .env\nnano .env\n",[432,4272,4273,4284,4288,4295,4305],{"__ignoreMap":423},[462,4274,4275,4278,4281],{"class":464,"line":465},[462,4276,4277],{"class":493},"git",[462,4279,4280],{"class":479}," clone",[462,4282,4283],{"class":479}," https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz.git\n",[462,4285,4286],{"class":464,"line":472},[462,4287,487],{"emptyLinePlaceholder":486},[462,4289,4290,4292],{"class":464,"line":483},[462,4291,543],{"class":475},[462,4293,4294],{"class":479}," buzz\u002Fdeploy\u002Fcompose\n",[462,4296,4297,4299,4302],{"class":464,"line":490},[462,4298,561],{"class":493},[462,4300,4301],{"class":479}," .env.example",[462,4303,4304],{"class":479}," .env\n",[462,4306,4307,4310],{"class":464,"line":535},[462,4308,4309],{"class":493},"nano",[462,4311,4304],{"class":479},[428,4313,4314,4315,4318],{},"Edit ",[432,4316,4317],{},".env"," in groups:",[582,4320,4321],{},[585,4322,4323],{},[441,4324,4325],{},"Domain:",[454,4327,4330],{"className":4328,"code":4329,"language":1612},[1610],"BUZZ_DOMAIN=buzz.pafor.me\nRELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\nBUZZ_PAIRING_RELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\u002Fpair\nBUZZ_MEDIA_BASE_URL=https:\u002F\u002Fbuzz.pafor.me\u002Fmedia\nBUZZ_MEDIA_SERVER_DOMAIN=buzz.pafor.me\nBUZZ_CORS_ORIGINS=https:\u002F\u002Fbuzz.pafor.me\n",[432,4331,4329],{"__ignoreMap":423},[582,4333,4334,4344],{},[585,4335,4336,4339,4340,4343],{},[441,4337,4338],{},"Owner key:"," ",[432,4341,4342],{},"RELAY_OWNER_PUBKEY"," requires your 64-character hex public key. Generate an identity in the desktop app first ('Create a new identity key' → copy your public ID, which is in npub format), then convert it to hex.",[585,4345,4346,4349],{},[441,4347,4348],{},"Secrets:",[582,4350,4351,4361,4375],{},[585,4352,4353,4354,4356,4357,4360],{},"Generate secrets using this ",[633,4355,2088],{"href":2087}," or with ",[432,4358,4359],{},"openssl rand -hex 32"," (run it seven times)",[585,4362,4363,4364,4367,4368,737,4371,4374],{},"Replace every ",[432,4365,4366],{},"CHANGE_ME"," placeholder: ",[432,4369,4370],{},"BUZZ_RELAY_PRIVATE_KEY",[432,4372,4373],{},"BUZZ_GIT_HOOK_HMAC_SECRET",", the Postgres\u002FRedis\u002FTypesense passwords, and the S3 access\u002Fsecret keys.",[585,4376,4377,4378,444],{},"Leftover placeholders are the most common cause of container restart loops; verify yours with ",[432,4379,4380],{},"grep CHANGE_ME .env",[454,4382,4385],{"className":4383,"code":4384,"language":1612},[1610],"    BUZZ_RELAY_PRIVATE_KEY=CHANGE_ME_64_HEX_PRIVATE_KEY\n    BUZZ_GIT_HOOK_HMAC_SECRET=CHANGE_ME_RANDOM_64_HEX\n    POSTGRES_PASSWORD=CHANGE_ME_RANDOM_PASSWORD\n    REDIS_PASSWORD=CHANGE_ME_RANDOM_PASSWORD\n    TYPESENSE_API_KEY=CHANGE_ME_RANDOM_API_KEY\n    BUZZ_S3_ACCESS_KEY=CHANGE_ME_RANDOM_ACCESS_KEY\n    BUZZ_S3_SECRET_KEY=CHANGE_ME_RANDOM_SECRET_KEY\n",[432,4386,4384],{"__ignoreMap":423},[582,4388,4389],{},[585,4390,4391,4394],{},[441,4392,4393],{},"Others:",[582,4395,4396,4403],{},[585,4397,4398,4399,4402],{},"Add ",[432,4400,4401],{},"CLOUDFLARE_API_TOKEN"," as an environment variable and assign the API token generated earlier. This is required for Caddy.",[585,4404,4405,4406,737,4408,4411,4412,444],{},"Buzz ships with open defaults — anyone who knows your relay URL can authenticate and join. Set ",[432,4407,4342],{},[432,4409,4410],{},"BUZZ_REQUIRE_RELAY_MEMBERSHIP=true",", and ",[432,4413,4414],{},"BUZZ_REQUIRE_AUTH_TOKEN=true",[1165,4416,4418],{"id":4417},"_4-enable-https-with-caddy","4. Enable HTTPS with Caddy",[1702,4420,4422],{"id":4421},"build-a-custom-caddy-image-with-the-cloudflare-dns-module","Build a Custom Caddy Image with the Cloudflare DNS Module",[582,4424,4425,4436,4447],{},[585,4426,4427,4428,4431,4432,4435],{},"We set up DNS-01 with Cloudflare for Caddy. DNS-01 works by having the plugin write a TXT record ",[432,4429,4430],{},"_acme-challenge.buzz.pafor.me"," to the ",[441,4433,4434],{},"public DNS",";",[585,4437,4438,4439,4442,4443,4446],{},"Let's Encrypt then looks the record up from the public internet to verify domain control. This means ",[432,4440,4441],{},"pafor.me"," must be a public zone in your Cloudflare account — not just a private hostname that only exists in Zero Trust \u002F WARP private DNS. If ",[432,4444,4445],{},"buzz.pafor.me"," is only resolved privately and there is no public zone, DNS-01 will fail, requiring a different approach.",[585,4448,4449],{},"Add the following to the Caddyfile:",[454,4451,4455],{"className":4452,"code":4453,"language":4454,"meta":423,"style":423},"language-yml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}\n}\n","yml",[432,4456,4457,4461,4474],{"__ignoreMap":423},[462,4458,4459],{"class":464,"line":465},[462,4460,1304],{"class":503},[462,4462,4463,4466,4469,4472],{"class":464,"line":472},[462,4464,4465],{"class":479},"  acme_dns cloudflare",[462,4467,4468],{"class":503}," {",[462,4470,4471],{"class":479},"env.CLOUDFLARE_API_TOKEN",[462,4473,2307],{"class":503},[462,4475,4476],{"class":464,"line":483},[462,4477,2307],{"class":503},[582,4479,4480],{},[585,4481,4482],{},"Create a Dockerfile.caddy with the following content, which is required by compose.caddy.yml:",[454,4484,4486],{"className":4452,"code":4485,"language":4454,"meta":423,"style":423},"FROM caddy:2-builder AS builder\n\nRUN xcaddy build \\\n    --with github.com\u002Fcaddy-dns\u002Fcloudflare\n\nFROM caddy:2-alpine\n\nCOPY --from=builder \u002Fusr\u002Fbin\u002Fcaddy \u002Fusr\u002Fbin\u002Fcaddy\n",[432,4487,4488,4493,4497,4502,4507,4511,4516,4520],{"__ignoreMap":423},[462,4489,4490],{"class":464,"line":465},[462,4491,4492],{"class":479},"FROM caddy:2-builder AS builder\n",[462,4494,4495],{"class":464,"line":472},[462,4496,487],{"emptyLinePlaceholder":486},[462,4498,4499],{"class":464,"line":483},[462,4500,4501],{"class":479},"RUN xcaddy build \\\n",[462,4503,4504],{"class":464,"line":490},[462,4505,4506],{"class":479},"    --with github.com\u002Fcaddy-dns\u002Fcloudflare\n",[462,4508,4509],{"class":464,"line":535},[462,4510,487],{"emptyLinePlaceholder":486},[462,4512,4513],{"class":464,"line":540},[462,4514,4515],{"class":479},"FROM caddy:2-alpine\n",[462,4517,4518],{"class":464,"line":553},[462,4519,487],{"emptyLinePlaceholder":486},[462,4521,4522],{"class":464,"line":558},[462,4523,4524],{"class":479},"COPY --from=builder \u002Fusr\u002Fbin\u002Fcaddy \u002Fusr\u002Fbin\u002Fcaddy\n",[582,4526,4527],{},[585,4528,4529,4530,4533],{},"Modify ",[432,4531,4532],{},"compose.caddy.yml"," to use the image with the Cloudflare module and pass the Cloudflare API token:",[454,4535,4537],{"className":4452,"code":4536,"language":4454,"meta":423,"style":423},"services:\n  relay:\n    ports: !reset []\n\n  caddy:\n    build:\n      context: .\n      dockerfile: Dockerfile.caddy\n    image: buzz-caddy:cloudflare\n    depends_on:\n      relay:\n        condition: service_healthy\n    environment:\n      BUZZ_DOMAIN: ${BUZZ_DOMAIN:?set BUZZ_DOMAIN}\n      CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}\n    ports:\n      - \"${CADDY_HTTP_PORT:-80}:80\"\n      - \"${CADDY_HTTPS_PORT:-443}:443\"\n    volumes:\n      - .\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile:ro\n      - buzz-caddy-data:\u002Fdata\n      - buzz-caddy-config:\u002Fconfig\n    restart: unless-stopped\n    networks:\n      - buzz-net\n\nvolumes:\n  buzz-caddy-data:\n    labels:\n      com.buzz.volume: caddy-data\n  buzz-caddy-config:\n    labels:\n      com.buzz.volume: caddy-config\n",[432,4538,4539,4547,4554,4567,4571,4578,4585,4594,4604,4614,4621,4628,4638,4645,4655,4665,4671,4683,4694,4701,4708,4715,4722,4733,4741,4749,4754,4762,4770,4778,4789,4797,4804],{"__ignoreMap":423},[462,4540,4541,4545],{"class":464,"line":465},[462,4542,4544],{"class":4543},"swJcz","services",[462,4546,756],{"class":503},[462,4548,4549,4552],{"class":464,"line":472},[462,4550,4551],{"class":4543},"  relay",[462,4553,756],{"class":503},[462,4555,4556,4559,4561,4564],{"class":464,"line":483},[462,4557,4558],{"class":4543},"    ports",[462,4560,940],{"class":503},[462,4562,4563],{"class":1312}," !reset",[462,4565,4566],{"class":503}," []\n",[462,4568,4569],{"class":464,"line":490},[462,4570,487],{"emptyLinePlaceholder":486},[462,4572,4573,4576],{"class":464,"line":535},[462,4574,4575],{"class":4543},"  caddy",[462,4577,756],{"class":503},[462,4579,4580,4583],{"class":464,"line":540},[462,4581,4582],{"class":4543},"    build",[462,4584,756],{"class":503},[462,4586,4587,4590,4592],{"class":464,"line":553},[462,4588,4589],{"class":4543},"      context",[462,4591,940],{"class":503},[462,4593,567],{"class":2108},[462,4595,4596,4599,4601],{"class":464,"line":558},[462,4597,4598],{"class":4543},"      dockerfile",[462,4600,940],{"class":503},[462,4602,4603],{"class":479}," Dockerfile.caddy\n",[462,4605,4606,4609,4611],{"class":464,"line":570},[462,4607,4608],{"class":4543},"    image",[462,4610,940],{"class":503},[462,4612,4613],{"class":479}," buzz-caddy:cloudflare\n",[462,4615,4616,4619],{"class":464,"line":2007},[462,4617,4618],{"class":4543},"    depends_on",[462,4620,756],{"class":503},[462,4622,4623,4626],{"class":464,"line":2013},[462,4624,4625],{"class":4543},"      relay",[462,4627,756],{"class":503},[462,4629,4630,4633,4635],{"class":464,"line":2035},[462,4631,4632],{"class":4543},"        condition",[462,4634,940],{"class":503},[462,4636,4637],{"class":479}," service_healthy\n",[462,4639,4640,4643],{"class":464,"line":2040},[462,4641,4642],{"class":4543},"    environment",[462,4644,756],{"class":503},[462,4646,4647,4650,4652],{"class":464,"line":2046},[462,4648,4649],{"class":4543},"      BUZZ_DOMAIN",[462,4651,940],{"class":503},[462,4653,4654],{"class":479}," ${BUZZ_DOMAIN:?set BUZZ_DOMAIN}\n",[462,4656,4657,4660,4662],{"class":464,"line":2055},[462,4658,4659],{"class":4543},"      CLOUDFLARE_API_TOKEN",[462,4661,940],{"class":503},[462,4663,4664],{"class":479}," ${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}\n",[462,4666,4667,4669],{"class":464,"line":2060},[462,4668,4558],{"class":4543},[462,4670,756],{"class":503},[462,4672,4673,4676,4678,4681],{"class":464,"line":2066},[462,4674,4675],{"class":503},"      -",[462,4677,504],{"class":503},[462,4679,4680],{"class":479},"${CADDY_HTTP_PORT:-80}:80",[462,4682,550],{"class":503},[462,4684,4685,4687,4689,4692],{"class":464,"line":4225},[462,4686,4675],{"class":503},[462,4688,504],{"class":503},[462,4690,4691],{"class":479},"${CADDY_HTTPS_PORT:-443}:443",[462,4693,550],{"class":503},[462,4695,4696,4699],{"class":464,"line":4230},[462,4697,4698],{"class":4543},"    volumes",[462,4700,756],{"class":503},[462,4702,4703,4705],{"class":464,"line":4245},[462,4704,4675],{"class":503},[462,4706,4707],{"class":479}," .\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile:ro\n",[462,4709,4710,4712],{"class":464,"line":4250},[462,4711,4675],{"class":503},[462,4713,4714],{"class":479}," buzz-caddy-data:\u002Fdata\n",[462,4716,4717,4719],{"class":464,"line":3802},[462,4718,4675],{"class":503},[462,4720,4721],{"class":479}," buzz-caddy-config:\u002Fconfig\n",[462,4723,4725,4728,4730],{"class":464,"line":4724},23,[462,4726,4727],{"class":4543},"    restart",[462,4729,940],{"class":503},[462,4731,4732],{"class":479}," unless-stopped\n",[462,4734,4736,4739],{"class":464,"line":4735},24,[462,4737,4738],{"class":4543},"    networks",[462,4740,756],{"class":503},[462,4742,4744,4746],{"class":464,"line":4743},25,[462,4745,4675],{"class":503},[462,4747,4748],{"class":479}," buzz-net\n",[462,4750,4752],{"class":464,"line":4751},26,[462,4753,487],{"emptyLinePlaceholder":486},[462,4755,4757,4760],{"class":464,"line":4756},27,[462,4758,4759],{"class":4543},"volumes",[462,4761,756],{"class":503},[462,4763,4765,4768],{"class":464,"line":4764},28,[462,4766,4767],{"class":4543},"  buzz-caddy-data",[462,4769,756],{"class":503},[462,4771,4773,4776],{"class":464,"line":4772},29,[462,4774,4775],{"class":4543},"    labels",[462,4777,756],{"class":503},[462,4779,4781,4784,4786],{"class":464,"line":4780},30,[462,4782,4783],{"class":4543},"      com.buzz.volume",[462,4785,940],{"class":503},[462,4787,4788],{"class":479}," caddy-data\n",[462,4790,4792,4795],{"class":464,"line":4791},31,[462,4793,4794],{"class":4543},"  buzz-caddy-config",[462,4796,756],{"class":503},[462,4798,4800,4802],{"class":464,"line":4799},32,[462,4801,4775],{"class":4543},[462,4803,756],{"class":503},[462,4805,4807,4809,4811],{"class":464,"line":4806},33,[462,4808,4783],{"class":4543},[462,4810,940],{"class":503},[462,4812,4813],{"class":479}," caddy-config\n",[1702,4815,4817],{"id":4816},"start-the-docker-containers","Start the Docker containers",[454,4819,4821],{"className":456,"code":4820,"language":458,"meta":423,"style":423},"docker compose -f compose.yml -f compose.caddy.yml up -d\n\n#Check the Docker status\ndocker compose ps\n",[432,4822,4823,4846,4850,4855],{"__ignoreMap":423},[462,4824,4825,4827,4829,4832,4835,4837,4840,4843],{"class":464,"line":465},[462,4826,2049],{"class":493},[462,4828,4260],{"class":479},[462,4830,4831],{"class":479}," -f",[462,4833,4834],{"class":479}," compose.yml",[462,4836,4831],{"class":479},[462,4838,4839],{"class":479}," compose.caddy.yml",[462,4841,4842],{"class":479}," up",[462,4844,4845],{"class":479}," -d\n",[462,4847,4848],{"class":464,"line":472},[462,4849,487],{"emptyLinePlaceholder":486},[462,4851,4852],{"class":464,"line":483},[462,4853,4854],{"class":468},"#Check the Docker status\n",[462,4856,4857,4859,4861],{"class":464,"line":490},[462,4858,2049],{"class":493},[462,4860,4260],{"class":479},[462,4862,2255],{"class":479},[966,4864],{"src":4865,"alt":4866,"style":4867},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fdocker-compose-ps-status-terminal.webp","Terminal window displaying running containers for Buzz services via docker compose ps","max-width: 700px; width: 100%; height: auto;",[428,4869,4870,4871,4874],{},"Open your web browser and navigate to ",[432,4872,4873],{},"http:\u002F\u002Fbuzz.pafor.me"," to verify that the relay is running.",[966,4876],{"src":4877,"alt":4878,"style":4879},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-relay-running-browser-verification.webp","Browser verification showing successful response from self-hosted Block's Buzz relay","max-width: 500px; width: 100%; height: auto;",[1165,4881,4883],{"id":4882},"step-5-back-up-from-day-one","Step 5: Back up from day one",[454,4885,4887],{"className":456,"code":4886,"language":458,"meta":423,"style":423},"mkdir -p \u002Fbuzz_backups\ncrontab -e\n",[432,4888,4889,4900],{"__ignoreMap":423},[462,4890,4891,4894,4897],{"class":464,"line":465},[462,4892,4893],{"class":493},"mkdir",[462,4895,4896],{"class":479}," -p",[462,4898,4899],{"class":479}," \u002Fbuzz_backups\n",[462,4901,4902,4905],{"class":464,"line":472},[462,4903,4904],{"class":493},"crontab",[462,4906,480],{"class":479},[428,4908,4909],{},"Add a nightly database dump cron job:",[454,4911,4914],{"className":4912,"code":4913,"language":1612},[1610],"0 3 * * * cd \u002Fhome\u002F\u003Cuser>\u002Fbuzz\u002Fdeploy\u002Fcompose && docker compose exec -T postgres pg_dump -U buzz buzz > \u002Fbuzz_backups\u002Fbuzz-$(date +\\%Y\\%m\\%d).sql\n",[432,4915,4913],{"__ignoreMap":423},[428,4917,4918],{},"Note: Treat BUZZ_RELAY_PRIVATE_KEY as permanent. Events signed by it will fail verification if the key changes; a restored database paired with a fresh key is not treated as the same relay.",[446,4920,4922],{"id":4921},"setting-up-the-buzz-desktop-client-and-nostr-identities","Setting Up the Buzz Desktop Client and Nostr Identities",[428,4924,4925,4926,4930],{},"Download the Buzz desktop app from ",[633,4927,4928],{"href":4928,"rel":4929},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Freleases",[664]," and start it. Fill in the profile details until you reach the \"Join or create a community\" page.",[428,4932,4933],{},[966,4934],{"alt":4935,"src":4936},"Buzz Desktop Client initial setup screen for joining or creating a community","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-setup-community.webp",[428,4938,4939],{},"Click \"Join a community\" and copy your public key.",[428,4941,4942],{},[966,4943],{"alt":4944,"src":4945},"Buzz client display showing public key identity before joining community","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-join-community-public-key.webp",[428,4947,4948,4949,4952],{},"Run the following command on the ",[441,4950,4951],{},"VPS"," to add yourself as the first member:",[454,4954,4956],{"className":456,"code":4955,"language":458,"meta":423,"style":423},"docker compose exec relay buzz-admin add-member --pubkey npub1yourkeyhere\n",[432,4957,4958],{"__ignoreMap":423},[462,4959,4960,4962,4964,4966,4969,4972,4975,4978],{"class":464,"line":465},[462,4961,2049],{"class":493},[462,4963,4260],{"class":479},[462,4965,2361],{"class":479},[462,4967,4968],{"class":479}," relay",[462,4970,4971],{"class":479}," buzz-admin",[462,4973,4974],{"class":479}," add-member",[462,4976,4977],{"class":479}," --pubkey",[462,4979,4980],{"class":479}," npub1yourkeyhere\n",[428,4982,4398,4983,4986],{},[432,4984,4985],{},"wss:\u002F\u002Fbuzz.pafor.me"," as the community URL and click \"Next\".",[428,4988,4989],{},[966,4990],{"alt":4991,"src":4992},"Entering the self-hosted community relay URL in the Buzz desktop app","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-input-community-url.webp",[428,4994,4995],{},"Enter a name and click the Next button.",[428,4997,4998],{},[966,4999],{"alt":5000,"src":5001},"Profile configuration screen in Buzz app to enter display name","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-profile-name-input.webp",[1165,5003,5005],{"id":5004},"channels-and-agents","Channels and Agents",[428,5007,5008],{},"Channels are task groups or project groups. Create a channel per task or project and pull the humans and agents in.",[428,5010,5011],{},"Everything within a channel is shared automatically, eliminating the need to brief each member individually. Every agent can be mentioned using @ and reads the relevant messages. Also, agents can @ each other.",[428,5013,5014],{},"Let's send a DM to a preconfigured agent",[428,5016,5017],{},[966,5018],{"alt":5019,"src":5020},"Sending direct message to an AI agent in the Buzz collaborative desktop client","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-dm-agent.webp",[428,5022,5023],{},"Let's create a channel and add some agents to it",[428,5025,5026],{},[966,5027],{"alt":5028,"src":5029},"Creating a new task or project channel inside the Buzz desktop app","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-create-channel-dialog.webp",[428,5031,5032],{},[966,5033],{"alt":5034,"src":5035},"Adding human members and AI agents to the newly created channel","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-add-agents-to-channel.webp",[428,5037,5038],{},[966,5039],{"alt":5040,"src":5041},"Active channel view displaying consolidated chat history and project tasks","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-channel-view.webp",[966,5043],{"src":5044,"alt":5045,"style":5046},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-channel-active-agents.webp","Detail view of active AI agents integrated into the collaborative project channel","max-width: 367px; width: 100%; height: auto;",[1165,5048,5050],{"id":5049},"enable-agent-runtimes","Enable Agent Runtimes",[428,5052,5053,5054,5057,5058,5061],{},"Preset runtimes rely on auto-discovery detecting launcher binaries (e.g. ",[432,5055,5056],{},"hermes-acp",") in standard directories like ",[432,5059,5060],{},"~\u002F.local\u002Fbin",". If a tool was installed in a non-standard location, Buzz cannot resolve it.",[428,5063,5064,5065,5068],{},"For Kimi Code, the agent ID is kimi, and Buzz looks for its binary at ",[432,5066,5067],{},"~\u002F.local\u002Fbin\u002Fkimi",". A symbolic link does the job:",[454,5070,5073],{"className":5071,"code":5072,"language":1612},[1610],"ln -s kimi-cli \u002FUsers\u002F\u003Cuser>\u002F.local\u002Fbin\u002Fkimi\n",[432,5074,5072],{"__ignoreMap":423},[428,5076,5077],{},"Kimi Code now appears under Agent runtimes.",[428,5079,5080],{},[966,5081],{"alt":5082,"src":5083},"Buzz application settings displaying configured AI Agent runtimes including Kimi","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-agent-runtimes-list.webp",[1165,5085,5087],{"id":5086},"projects-and-repositories","Projects and Repositories",[428,5089,5090,5091,5094],{},"Enable the '",[441,5092,5093],{},"Projects","' feature in Settings → Experiments first:",[428,5096,5097],{},[966,5098],{"alt":5099,"src":5100},"Enabling experimental Projects feature in the Buzz desktop settings tab","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-experiments-projects.webp",[428,5102,5103,5104,5107],{},"Currently, a project must be created using the ",[432,5105,5106],{},"buzz-cli"," (though direct project creation from the UI is planned for a future release).",[1702,5109,5111],{"id":5110},"install-buzz-cli","Install buzz-cli",[428,5113,5114,5115,5117,5118,940],{},"Run the following commands to install ",[432,5116,5106],{}," on the ",[441,5119,4951],{},[454,5121,5123],{"className":456,"code":5122,"language":458,"meta":423,"style":423},"sudo apt install cargo\ncd ~\u002Fbuzz\ncargo install --path crates\u002Fbuzz-cli\necho 'export PATH=\"$HOME\u002F.cargo\u002Fbin:$PATH\"' >> ~\u002F.bashrc && source ~\u002F.bashrc\n",[432,5124,5125,5136,5143,5156],{"__ignoreMap":423},[462,5126,5127,5129,5131,5133],{"class":464,"line":465},[462,5128,1994],{"class":493},[462,5130,1997],{"class":479},[462,5132,2020],{"class":479},[462,5134,5135],{"class":479}," cargo\n",[462,5137,5138,5140],{"class":464,"line":472},[462,5139,543],{"class":475},[462,5141,5142],{"class":479}," ~\u002Fbuzz\n",[462,5144,5145,5148,5150,5153],{"class":464,"line":483},[462,5146,5147],{"class":493},"cargo",[462,5149,2020],{"class":479},[462,5151,5152],{"class":479}," --path",[462,5154,5155],{"class":479}," crates\u002Fbuzz-cli\n",[462,5157,5158,5160,5163,5166,5168,5171,5174,5177,5180],{"class":464,"line":490},[462,5159,1942],{"class":475},[462,5161,5162],{"class":503}," '",[462,5164,5165],{"class":479},"export PATH=\"$HOME\u002F.cargo\u002Fbin:$PATH\"",[462,5167,2378],{"class":503},[462,5169,5170],{"class":503}," >>",[462,5172,5173],{"class":479}," ~\u002F.bashrc",[462,5175,5176],{"class":503}," &&",[462,5178,5179],{"class":475}," source",[462,5181,5182],{"class":479}," ~\u002F.bashrc\n",[428,5184,5185,5186,700,5189,5191,5192,5194],{},"Generate a pair of private and public keys using the ",[633,5187,2088],{"href":5188},"\u002Ftools\u002Fnostr-key-generator",[432,5190,5106],{},". This pair is the identity of the ",[432,5193,5106],{}," in Nostr relay.",[454,5196,5198],{"className":456,"code":5197,"language":458,"meta":423,"style":423},"docker run --rm --entrypoint \u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-admin ghcr.io\u002Fblock\u002Fbuzz:main generate-key\n\n# Use the generated Public Key\ndocker compose exec relay buzz-admin add-member --pubkey generated_Public_key\n",[432,5199,5200,5221,5225,5230],{"__ignoreMap":423},[462,5201,5202,5204,5206,5209,5212,5215,5218],{"class":464,"line":465},[462,5203,2049],{"class":493},[462,5205,2128],{"class":479},[462,5207,5208],{"class":479}," --rm",[462,5210,5211],{"class":479}," --entrypoint",[462,5213,5214],{"class":479}," \u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-admin",[462,5216,5217],{"class":479}," ghcr.io\u002Fblock\u002Fbuzz:main",[462,5219,5220],{"class":479}," generate-key\n",[462,5222,5223],{"class":464,"line":472},[462,5224,487],{"emptyLinePlaceholder":486},[462,5226,5227],{"class":464,"line":483},[462,5228,5229],{"class":468},"# Use the generated Public Key\n",[462,5231,5232,5234,5236,5238,5240,5242,5244,5246],{"class":464,"line":490},[462,5233,2049],{"class":493},[462,5235,4260],{"class":479},[462,5237,2361],{"class":479},[462,5239,4968],{"class":479},[462,5241,4971],{"class":479},[462,5243,4974],{"class":479},[462,5245,4977],{"class":479},[462,5247,5248],{"class":479}," generated_Public_key\n",[428,5250,5251],{},"Configure the CLI:",[454,5253,5255],{"className":456,"code":5254,"language":458,"meta":423,"style":423},"# Copy the Secret key as the BUZZ_PRIVATE_KEY\necho 'export BUZZ_PRIVATE_KEY=\"nsec1...\"'  >> \u002Fhome\u002F\u003Cuser>\u002F.bashrc\n\necho 'export BUZZ_RELAY_URL=\"wss:\u002F\u002Fbuzz.pafor.me\"'  >> \u002Fhome\u002F\u003Cuser>\u002F.bashrc\n",[432,5256,5257,5262,5292,5296],{"__ignoreMap":423},[462,5258,5259],{"class":464,"line":465},[462,5260,5261],{"class":468},"# Copy the Secret key as the BUZZ_PRIVATE_KEY\n",[462,5263,5264,5266,5268,5271,5273,5276,5279,5281,5284,5287,5289],{"class":464,"line":472},[462,5265,1942],{"class":475},[462,5267,5162],{"class":503},[462,5269,5270],{"class":479},"export BUZZ_PRIVATE_KEY=\"nsec1...\"",[462,5272,2378],{"class":503},[462,5274,5275],{"class":503},"  >>",[462,5277,5278],{"class":479}," \u002Fhome\u002F",[462,5280,1445],{"class":503},[462,5282,5283],{"class":479},"use",[462,5285,5286],{"class":1301},"r",[462,5288,1454],{"class":503},[462,5290,5291],{"class":479},"\u002F.bashrc\n",[462,5293,5294],{"class":464,"line":483},[462,5295,487],{"emptyLinePlaceholder":486},[462,5297,5298,5300,5302,5305,5307,5309,5311,5313,5315,5317,5319],{"class":464,"line":490},[462,5299,1942],{"class":475},[462,5301,5162],{"class":503},[462,5303,5304],{"class":479},"export BUZZ_RELAY_URL=\"wss:\u002F\u002Fbuzz.pafor.me\"",[462,5306,2378],{"class":503},[462,5308,5275],{"class":503},[462,5310,5278],{"class":479},[462,5312,1445],{"class":503},[462,5314,5283],{"class":479},[462,5316,5286],{"class":1301},[462,5318,1454],{"class":503},[462,5320,5291],{"class":479},[428,5322,5323,5324,5326],{},"Run the following command to verify ",[432,5325,5106],{}," is configured properly:",[454,5328,5330],{"className":456,"code":5329,"language":458,"meta":423,"style":423},"buzz channels list\n",[432,5331,5332],{"__ignoreMap":423},[462,5333,5334,5337,5340],{"class":464,"line":465},[462,5335,5336],{"class":493},"buzz",[462,5338,5339],{"class":479}," channels",[462,5341,5342],{"class":479}," list\n",[428,5344,5345],{},[966,5346],{"alt":5347,"src":5348},"Terminal command execution verifying buzz-cli configuration by listing active channels","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-cli-channels-list-terminal.webp",[1702,5350,5352],{"id":5351},"create-a-project-with-buzz-cli","Create a Project with buzz-cli",[454,5354,5356],{"className":456,"code":5355,"language":458,"meta":423,"style":423},"# --channel refers to the UUID of the channel\nbuzz repos create --id TestKOA --name 'Display Name' --channel \"bd92b3d1-8fac-441c-a9ac-2b2f3aac5c5b\"\n",[432,5357,5358,5363],{"__ignoreMap":423},[462,5359,5360],{"class":464,"line":465},[462,5361,5362],{"class":468},"# --channel refers to the UUID of the channel\n",[462,5364,5365,5367,5370,5373,5376,5379,5382,5384,5387,5389,5392,5394,5397],{"class":464,"line":472},[462,5366,5336],{"class":493},[462,5368,5369],{"class":479}," repos",[462,5371,5372],{"class":479}," create",[462,5374,5375],{"class":479}," --id",[462,5377,5378],{"class":479}," TestKOA",[462,5380,5381],{"class":479}," --name",[462,5383,5162],{"class":503},[462,5385,5386],{"class":479},"Display Name",[462,5388,2378],{"class":503},[462,5390,5391],{"class":479}," --channel",[462,5393,504],{"class":503},[462,5395,5396],{"class":479},"bd92b3d1-8fac-441c-a9ac-2b2f3aac5c5b",[462,5398,550],{"class":503},[428,5400,5401,5402,5404],{},"A project can only be removed by its owner. Because the \"Display Name\" project was created by the ",[432,5403,5106],{},", which lacks a removal command, it cannot be deleted this way.",[428,5406,5407],{},"Check back the Buzz desktop app to verify the project is created.",[428,5409,5410],{},[966,5411],{"alt":5412,"src":5413},"Buzz desktop application projects view confirming successful project creation","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-project-view.webp",[428,5415,5416],{},"Once a project is available in Projects, more projects can be added using the \"+\" button at the top right corner.",[428,5418,5419],{},[966,5420],{"alt":5421,"src":5422},"Adding new developer projects using the plus icon in Buzz desktop client","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-add-project-button.webp",[1702,5424,5426],{"id":5425},"check-in-existing-git-repositories","Check In Existing Git Repositories",[428,5428,5429,5430,5433,5434,5437,5438,940],{},"Install ",[432,5431,5432],{},"git-credential-nostr"," on the machine where git repositories are. It requires ",[441,5435,5436],{},"git 2.46+"," and the Rust toolchain. Refer to this ",[633,5439,5442],{"href":5440,"rel":5441},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Ftree\u002Fmain\u002Fcrates\u002Fgit-credential-nostr",[664],"Readme",[454,5444,5446],{"className":456,"code":5445,"language":458,"meta":423,"style":423},"cargo install --path crates\u002Fgit-credential-nostr\n",[432,5447,5448],{"__ignoreMap":423},[462,5449,5450,5452,5454,5456],{"class":464,"line":465},[462,5451,5147],{"class":493},[462,5453,2020],{"class":479},[462,5455,5152],{"class":479},[462,5457,5458],{"class":479}," crates\u002Fgit-credential-nostr\n",[428,5460,5461,5462,5464],{},"Set up ",[432,5463,5432],{}," for Buzz relay authorisation:",[454,5466,5468],{"className":456,"code":5467,"language":458,"meta":423,"style":423},"# 1. Register the helper and enable per-path credentials.\ngit config --global credential.helper nostr\ngit config --global credential.useHttpPath true\n\n# 2. Store your nsec in a key file (must be 0600). Replace \"nsec1...\" with your private key\nmkdir -p ~\u002F.nostr\necho \"nsec1...\" > ~\u002F.nostr\u002Fkey && chmod 600 ~\u002F.nostr\u002Fkey\ngit config --global nostr.keyfile ~\u002F.nostr\u002Fkey\n",[432,5469,5470,5475,5491,5504,5508,5513,5522,5549],{"__ignoreMap":423},[462,5471,5472],{"class":464,"line":465},[462,5473,5474],{"class":468},"# 1. Register the helper and enable per-path credentials.\n",[462,5476,5477,5479,5482,5485,5488],{"class":464,"line":472},[462,5478,4277],{"class":493},[462,5480,5481],{"class":479}," config",[462,5483,5484],{"class":479}," --global",[462,5486,5487],{"class":479}," credential.helper",[462,5489,5490],{"class":479}," nostr\n",[462,5492,5493,5495,5497,5499,5502],{"class":464,"line":483},[462,5494,4277],{"class":493},[462,5496,5481],{"class":479},[462,5498,5484],{"class":479},[462,5500,5501],{"class":479}," credential.useHttpPath",[462,5503,1554],{"class":503},[462,5505,5506],{"class":464,"line":490},[462,5507,487],{"emptyLinePlaceholder":486},[462,5509,5510],{"class":464,"line":535},[462,5511,5512],{"class":468},"# 2. Store your nsec in a key file (must be 0600). Replace \"nsec1...\" with your private key\n",[462,5514,5515,5517,5519],{"class":464,"line":540},[462,5516,4893],{"class":493},[462,5518,4896],{"class":479},[462,5520,5521],{"class":479}," ~\u002F.nostr\n",[462,5523,5524,5526,5528,5531,5533,5535,5538,5540,5543,5546],{"class":464,"line":553},[462,5525,1942],{"class":475},[462,5527,504],{"class":503},[462,5529,5530],{"class":479},"nsec1...",[462,5532,511],{"class":503},[462,5534,1977],{"class":503},[462,5536,5537],{"class":479}," ~\u002F.nostr\u002Fkey",[462,5539,5176],{"class":503},[462,5541,5542],{"class":493}," chmod",[462,5544,5545],{"class":2108}," 600",[462,5547,5548],{"class":479}," ~\u002F.nostr\u002Fkey\n",[462,5550,5551,5553,5555,5557,5560],{"class":464,"line":558},[462,5552,4277],{"class":493},[462,5554,5481],{"class":479},[462,5556,5484],{"class":479},[462,5558,5559],{"class":479}," nostr.keyfile",[462,5561,5548],{"class":479},[428,5563,5564],{},"Create a repo on the Buzz relay:",[454,5566,5569],{"className":5567,"code":5568,"language":1612},[1610],"buzz repos create --id koa-email-routing --name \"KOA Email Routing\" --clone \"https:\u002F\u002Fbuzz.pafor.me\u002Fgit\u002F\u003Cpub_key>\u002Fkoa-email-routing\" --nostr-relay \"wss:\u002F\u002Fbuzz.pafor.me\"\n",[432,5570,5568],{"__ignoreMap":423},[428,5572,5573,5574,5577,5578,5581],{},"On your first ",[432,5575,5576],{},"git push",", you will encounter a ",[432,5579,5580],{},"remote: missing Authorization header"," error. To resolve this, you need to bind the repository ID to a Buzz channel, as channel membership dictates Git write permissions (ACLs):",[454,5583,5585],{"className":456,"code":5584,"language":458,"meta":423,"style":423},"buzz repos bind --id koa-email-routing --channel \u003CCHANNEL_UUID>\n\n# push the code again\ngit push\n",[432,5586,5587,5615,5619,5624],{"__ignoreMap":423},[462,5588,5589,5591,5593,5596,5598,5601,5603,5606,5609,5612],{"class":464,"line":465},[462,5590,5336],{"class":493},[462,5592,5369],{"class":479},[462,5594,5595],{"class":479}," bind",[462,5597,5375],{"class":479},[462,5599,5600],{"class":479}," koa-email-routing",[462,5602,5391],{"class":479},[462,5604,5605],{"class":503}," \u003C",[462,5607,5608],{"class":479},"CHANNEL_UUI",[462,5610,5611],{"class":1301},"D",[462,5613,5614],{"class":503},">\n",[462,5616,5617],{"class":464,"line":472},[462,5618,487],{"emptyLinePlaceholder":486},[462,5620,5621],{"class":464,"line":483},[462,5622,5623],{"class":468},"# push the code again\n",[462,5625,5626,5628],{"class":464,"line":490},[462,5627,4277],{"class":493},[462,5629,5630],{"class":479}," push\n",[428,5632,5633,5634,5636],{},"Checking the project in the Buzz desktop app shows the following, because the app needs ",[441,5635,5436],{}," — launching the app directly may pick up an older version of Git:",[428,5638,5639],{},[966,5640],{"alt":5641,"src":5642},"Buzz client rendering Git loading error due to outdated local Git version below 2.46","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-git-version-error.webp",[428,5644,5645,5646,5649,5650,444],{},"Export the PATH via ",[432,5647,5648],{},"launchctl setenv PATH \"\u002Fopt\u002Fhomebrew\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin:\u002Fusr\u002Fsbin:\u002Fsbin\""," in the shell profile and launch the Buzz app from the shell. Refer to this ",[633,5651,5654],{"href":5652,"rel":5653},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Fissues\u002F5348",[664],"issue",[454,5656,5658],{"className":456,"code":5657,"language":458,"meta":423,"style":423},"open -a Buzz\n",[432,5659,5660],{"__ignoreMap":423},[462,5661,5662,5665,5668],{"class":464,"line":465},[462,5663,5664],{"class":493},"open",[462,5666,5667],{"class":479}," -a",[462,5669,5670],{"class":479}," Buzz\n",[428,5672,5673],{},"Check back the Projects in the Buzz app, the repository details are now loaded.",[428,5675,5676],{},[966,5677],{"alt":5678,"src":5679},"Buzz desktop interface with successfully loaded Git repository details and commit logs","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-repository-details-loaded.webp",[446,5681,5683],{"id":5682},"syncing-ai-agents-with-the-buzz-mobile-app-via-qr-code","Syncing AI Agents with the Buzz Mobile App via QR Code",[428,5685,5686,5687,5690,5691,444],{},"The Buzz mobile app pairing only accepts the HTTPS protocol and the ",[432,5688,5689],{},"buzz-pair-relay"," is not started by default on ",[441,5692,4951],{},[454,5694,5696],{"className":456,"code":5695,"language":458,"meta":423,"style":423},"cd ~\u002Fbuzz\ncargo install --path crates\u002Fbuzz-pair-relay\n",[432,5697,5698,5704],{"__ignoreMap":423},[462,5699,5700,5702],{"class":464,"line":465},[462,5701,543],{"class":475},[462,5703,5142],{"class":479},[462,5705,5706,5708,5710,5712],{"class":464,"line":472},[462,5707,5147],{"class":493},[462,5709,2020],{"class":479},[462,5711,5152],{"class":479},[462,5713,5714],{"class":479}," crates\u002Fbuzz-pair-relay\n",[428,5716,5717,5718,5721,5722,5724],{},"Add the following to ",[432,5719,5720],{},"compose.yml"," to start the ",[432,5723,5689],{}," service:",[454,5726,5728],{"className":4452,"code":5727,"language":4454,"meta":423,"style":423},"  pair:\n    image: ${BUZZ_IMAGE:-ghcr.io\u002Fblock\u002Fbuzz:main}\n    entrypoint: [\"\u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-pair-relay\"]\n    environment:\n      BUZZ_PAIR_RELAY_BIND_ADDR: 0.0.0.0:5000\n    ports:\n      - \"${BUZZ_PAIR_RELAY_PORT:-5000}:5000\"\n    restart: unless-stopped\n    networks:\n      [buzz-net]\n",[432,5729,5730,5737,5746,5766,5772,5782,5788,5799,5807,5813],{"__ignoreMap":423},[462,5731,5732,5735],{"class":464,"line":465},[462,5733,5734],{"class":4543},"  pair",[462,5736,756],{"class":503},[462,5738,5739,5741,5743],{"class":464,"line":472},[462,5740,4608],{"class":4543},[462,5742,940],{"class":503},[462,5744,5745],{"class":479}," ${BUZZ_IMAGE:-ghcr.io\u002Fblock\u002Fbuzz:main}\n",[462,5747,5748,5751,5753,5756,5758,5761,5763],{"class":464,"line":483},[462,5749,5750],{"class":4543},"    entrypoint",[462,5752,940],{"class":503},[462,5754,5755],{"class":503}," [",[462,5757,511],{"class":503},[462,5759,5760],{"class":479},"\u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-pair-relay",[462,5762,511],{"class":503},[462,5764,5765],{"class":503},"]\n",[462,5767,5768,5770],{"class":464,"line":490},[462,5769,4642],{"class":4543},[462,5771,756],{"class":503},[462,5773,5774,5777,5779],{"class":464,"line":535},[462,5775,5776],{"class":4543},"      BUZZ_PAIR_RELAY_BIND_ADDR",[462,5778,940],{"class":503},[462,5780,5781],{"class":479}," 0.0.0.0:5000\n",[462,5783,5784,5786],{"class":464,"line":540},[462,5785,4558],{"class":4543},[462,5787,756],{"class":503},[462,5789,5790,5792,5794,5797],{"class":464,"line":553},[462,5791,4675],{"class":503},[462,5793,504],{"class":503},[462,5795,5796],{"class":479},"${BUZZ_PAIR_RELAY_PORT:-5000}:5000",[462,5798,550],{"class":503},[462,5800,5801,5803,5805],{"class":464,"line":558},[462,5802,4727],{"class":4543},[462,5804,940],{"class":503},[462,5806,4732],{"class":479},[462,5808,5809,5811],{"class":464,"line":570},[462,5810,4738],{"class":4543},[462,5812,756],{"class":503},[462,5814,5815,5818,5821],{"class":464,"line":2007},[462,5816,5817],{"class":503},"      [",[462,5819,5820],{"class":479},"buzz-net",[462,5822,5765],{"class":503},[428,5824,4398,5825,435,5828,4431,5831,5833],{},[432,5826,5827],{},"BUZZ_PAIRING_RELAY_URL",[432,5829,5830],{},"BUZZ_PAIR_RELAY_PORT",[432,5832,4317],{}," file:",[454,5835,5838],{"className":5836,"code":5837,"language":1612},[1610],"BUZZ_PAIRING_RELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\u002Fpair\nBUZZ_PAIR_RELAY_PORT=5000\n",[432,5839,5837],{"__ignoreMap":423},[428,5841,5842,5843,5846],{},"Head to the '",[441,5844,5845],{},"Mobile","' in the Buzz desktop Settings:",[428,5848,5849],{},[966,5850],{"alt":5851,"src":5852},"Settings dialog in Buzz app showing the Mobile devices configuration tab","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-mobile-tab.webp",[428,5854,5855],{},"Click \"Start pairing\" — a QR code is generated; scan this QR code with the Buzz app on the mobile device. It will be paired after you click \"Code Match\".",[428,5857,5858],{},[966,5859],{"alt":5860,"src":5861},"Generating secure pairing QR code in desktop client for Buzz mobile synchronization","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-pairing-qr-code.webp",[428,5863,5864],{},"The agents on the Buzz mobile app are available only if they are running on the Buzz desktop app. The desktop machine has to be running for the agents to work.",[428,5866,5867],{},[966,5868],{"alt":5869,"src":5870},"Buzz mobile application interface showcasing synced active AI companion agents","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-mobile-app-active-agents.webp",[446,5872,5874],{"id":5873},"final-thought","Final Thought",[428,5876,5877],{},"While Buzz is still too early for large scale production environments with several bugs and UI limitations, it is an exciting experience for small teams and solo developers. It offers a preview of what a collaborative, AI-first workspace truly feels like.",[446,5879,5880],{"id":1795},"Reference",[582,5882,5883,5890,5897,5904],{},[585,5884,5885],{},[633,5886,5889],{"href":5887,"rel":5888},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz",[664],"Buzz releases",[585,5891,5892],{},[633,5893,5896],{"href":5894,"rel":5895},"https:\u002F\u002Fblock.xyz\u002Finside\u002Fintroducing-buzz-where-humans-and-agents-work-together",[664],"Introducing Buzz",[585,5898,5899],{},[633,5900,5903],{"href":5901,"rel":5902},"https:\u002F\u002Fwww.hostinger.com\u002Ftutorials\u002Fwhat-is-buzz",[664],"What is buzz",[585,5905,5906],{},[633,5907,5910],{"href":5908,"rel":5909},"https:\u002F\u002Fmiget.com\u002Fblog\u002Fhow-to-self-host-buzz",[664],"How to self-host Buzz (Miget)",[1023,5912,5913],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":423,"searchDepth":472,"depth":483,"links":5915},[5916,5917,5918,5932,5941,5942,5943],{"id":3832,"depth":472,"text":3833},{"id":3877,"depth":472,"text":3878},{"id":3925,"depth":472,"text":3926,"children":5919},[5920,5921,5925,5926,5927,5931],{"id":3929,"depth":483,"text":3930},{"id":3955,"depth":483,"text":3956,"children":5922},[5923,5924],{"id":3959,"depth":490,"text":3960},{"id":4058,"depth":490,"text":4059},{"id":4076,"depth":483,"text":4077},{"id":4266,"depth":483,"text":4267},{"id":4417,"depth":483,"text":4418,"children":5928},[5929,5930],{"id":4421,"depth":490,"text":4422},{"id":4816,"depth":490,"text":4817},{"id":4882,"depth":483,"text":4883},{"id":4921,"depth":472,"text":4922,"children":5933},[5934,5935,5936],{"id":5004,"depth":483,"text":5005},{"id":5049,"depth":483,"text":5050},{"id":5086,"depth":483,"text":5087,"children":5937},[5938,5939,5940],{"id":5110,"depth":490,"text":5111},{"id":5351,"depth":490,"text":5352},{"id":5425,"depth":490,"text":5426},{"id":5682,"depth":472,"text":5683},{"id":5873,"depth":472,"text":5874},{"id":1795,"depth":472,"text":5880},[5945,1034,5336],"collaboration","2026-09-08","Learn how to self-host Block's Buzz on a Linux VPS behind Cloudflare DNS. Run a secure, Nostr-powered workspace where humans and AI agents collaborate.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002FEN-Self-Hosting-Buzz-As-The-Workspace-Where-AI-Agents-Become-Colleagues.webp","A premium 16:9 technology card with deep blue and orange accents illustrating how to self-host Block's Buzz relay on an Ubuntu VPS, featuring a clean glassmorphic panel with centered typography.",{"schemaOrg":5951,"robots":1044,"sitemap":5971},[5952,5953],{"@type":1043,"headline":382,"description":5947,"image":5948},{"@type":3797,"name":382,"description":5947,"image":5948,"step":5954},[5955,5959,5962,5965,5968],{"@type":5956,"name":5957,"text":5958},"HowToStep","Phase 1: Cloudflare Setup","Create a Cloudflare API Token and configure DNS settings.",{"@type":5956,"name":5960,"text":5961},"Phase 2: Install Docker","Set up and install Docker Engine on Ubuntu VPS.",{"@type":5956,"name":5963,"text":5964},"Phase 3: Clone and Configure","Clone the repository and configure compose variables.",{"@type":5956,"name":5966,"text":5967},"Phase 4: Caddy Integration","Build custom Caddy with Cloudflare DNS challenge module.",{"@type":5956,"name":5969,"text":5970},"Phase 5: Automated Backup","Configure a cron job to automatically back up PostgreSQL.",{"lastmod":3808},{"title":5973,"description":5947,"ogTitle":382,"ogDescription":5947,"twitterTitle":382,"twitterDescription":5947},"How to Self-Host Block's Buzz Relay on Ubuntu VPS",[5975,3805,3828,3807,1050],"Nostr","ir8b59r6ypIp92KOOIJHFgPU_UhHH0zic0M1up4soME",{"id":1870,"title":378,"author":1053,"body":1871,"category":3788,"date":3790,"description":3791,"extension":1037,"image":3792,"imageAlt":3793,"isPublished":486,"meta":3794,"minRead":3802,"navigation":486,"path":379,"seo":3803,"stem":380,"tags":3804,"updatedAt":3808,"__hash__":3809},{"id":1058,"title":414,"author":1053,"body":1059,"category":1852,"date":1854,"description":1855,"extension":1037,"image":1856,"imageAlt":1857,"isPublished":486,"meta":1858,"minRead":553,"navigation":486,"path":415,"seo":1863,"stem":416,"tags":1864,"updatedAt":1053,"__hash__":1868},1792489980112]