site
Health Warn
- License รขโฌโ License: MIT
- Description รขโฌโ Repository has a description
- Active repo รขโฌโ Last push 0 days ago
- Low visibility รขโฌโ Only 9 GitHub stars
Code Pass
- Code scan รขโฌโ Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions รขโฌโ No dangerous permissions requested
This project is a monorepo template for building and deploying a personal homepage and digital garden. It uses Astro for the frontend and Pulumi (Go) to automate the entire Google Cloud Platform (GCP) infrastructure, including Cloud Run, HTTPS load balancing, and CI/CD pipelines.
Security Assessment
Overall risk: Low. The repository serves static content and contains Infrastructure as Code (IaC) rather than executable agent logic. A light code scan of 12 files found no dangerous patterns, hardcoded secrets, or requests for dangerous local permissions. Because it is an infrastructure template, the network requests and deployments are entirely standard for GCP (Cloud Run, Artifact Registry) and rely on secure GitHub Actions Workload Identity Federation rather than static credentials.
Quality Assessment
The project is of high technical quality and is actively maintained, with its last push occurring today. It operates under the highly permissive and standard MIT license. The primary concern is its low community visibility; with only 9 GitHub stars, it has not been broadly vetted by a large audience yet. However, the detailed architecture documentation and clear infrastructure boundaries suggest a mature and professional project setup.
Verdict
Safe to use, provided you review the Pulumi configuration to ensure the provisioned GCP resources align with your own cloud budget and security constraints.
๐ชด A repository for building personal homepages and technical garden on GCP
koborin.ai

Technical garden for exploring AI, cloud architecture, and continuous learning.
Astro ( ) runs on Cloud Run behind a global HTTPS load balancer, and the entire stack (app + infra) lives in this monorepo with Pulumi (Go).
Architecture
Dev/Prod share the same HTTPS load balancer and Artifact Registry; only Cloud Run scaling/access policies differ.
---
title: "Google Cloud Project"
---
flowchart LR
subgraph PULUMI_STATE["Pulumi Backend State - GCS"]
STATE_SHARED["shared"]
STATE_DEV["dev"]
STATE_PROD["prod"]
end
subgraph SHARED["Shared Resources"]
APIS["APIs"]
ARTIFACT["Artifact Registry"]
WIF["Workload Identity<br/>Pool/Provider"]
end
subgraph DNS["Cloudflare DNS (manual)"]
DEV_DOMAIN["dev.koborin.ai<br/>A record"]
PROD_DOMAIN["koborin.ai<br/>A record"]
end
subgraph LB["Unified HTTPS LB - shared"]
STATIC_IP["Static IP<br/>PREMIUM tier"]
SSL_CERT["Managed SSL Cert<br/>multi-domain"]
URL_MAP["URL Map<br/>host routing"]
HTTPS_PROXY["HTTPS Proxy"]
end
subgraph DEV_BACKEND["Dev Backend"]
DEV_IAP["IAP<br/>+ X-Robots-Tag"]
DEV_NEG["Serverless NEG"]
DEV_CR["Cloud Run<br/>koborin-ai-web-dev (Astro)<br/>(LB-only ingress)"]
end
subgraph PROD_BACKEND["Prod Backend"]
PROD_NEG["Serverless NEG"]
PROD_CR["Cloud Run<br/>koborin-ai-web-prod (Astro)<br/>(LB-only ingress)"]
end
subgraph CICD["GitHub Actions"]
GH_WIF["Workload Identity<br/>Federation"]
PULUMI_SA["Pulumi SA"]
end
STATE_SHARED -.-> SHARED
STATE_SHARED -.-> LB
STATE_DEV -.-> DEV_BACKEND
STATE_PROD -.-> PROD_BACKEND
ARTIFACT -.->|"Container Image"| DEV_CR
ARTIFACT -.->|"Container Image"| PROD_CR
DEV_DOMAIN --> STATIC_IP
PROD_DOMAIN --> STATIC_IP
STATIC_IP --> SSL_CERT
SSL_CERT --> HTTPS_PROXY
HTTPS_PROXY --> URL_MAP
URL_MAP -->|"dev host"| DEV_IAP
URL_MAP -->|"prod host"| PROD_NEG
DEV_IAP --> DEV_NEG
DEV_NEG --> DEV_CR
PROD_NEG --> PROD_CR
GH_WIF -.->|"Authenticate"| WIF
WIF -.->|"Impersonate"| PULUMI_SA
PULUMI_SA -.->|"Preview/Up"| PULUMI_STATE
style PULUMI_STATE fill:#E8E8E8,color:#000,stroke:#666,stroke-width:2px
style STATE_SHARED fill:#F5F5F5,color:#000
style STATE_DEV fill:#F5F5F5,color:#000
style STATE_PROD fill:#F5F5F5,color:#000
style APIS fill:#9E9E9E,color:#fff
style ARTIFACT fill:#9E9E9E,color:#fff
style WIF fill:#9E9E9E,color:#fff
style STATIC_IP fill:#00B6AC,color:#fff
style SSL_CERT fill:#00B6AC,color:#fff
style URL_MAP fill:#00B6AC,color:#fff
style HTTPS_PROXY fill:#00B6AC,color:#fff
style DEV_IAP fill:#F76560,color:#fff
style DEV_CR fill:#4A90E2,color:#fff
style PROD_CR fill:#4A90E2,color:#fff
style GH_WIF fill:#FFB74D,color:#000
style PULUMI_SA fill:#FFB74D,color:#000
DNS is hosted in Cloudflare. Pulumi does not manage DNS records; add/update
koborin.ai/dev.koborin.aiA records manually whenever the load balancer IP changes.
Environment matrix
| Layer | Dev (dev.koborin.ai) |
Prod (koborin.ai) |
|---|---|---|
| Runtime | Cloud Run (koborin-ai-web-dev) |
Cloud Run (koborin-ai-web-prod) |
| Access | IAP allow list + X-Robots-Tag: noindex |
Public (no IAP) |
| Ingress | INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER |
INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER |
| Scaling | Min: 0, Max: 1 | Min: 0, Max: 10 |
| Env Vars | NODE_ENV=development, NEXT_PUBLIC_ENV=dev |
NODE_ENV=production, NEXT_PUBLIC_ENV=prod |
| Content | Same MDX content (no env-specific filtering) | Same MDX content (no env-specific filtering) |
| Analytics | GA4 (debug view) + optional server events | GA4 + server events + Cloud Monitoring |
CI/CD
Infrastructure and application deploys are each handled by dedicated GitHub Actions workflows using Workload Identity Federation.
flowchart LR
subgraph GitHub Actions
planInfra[plan-infra.yml]
releaseInfra[release-infra.yml]
appCI[app-ci.yml]
appRelease[app-release.yml]
end
subgraph Cloud Build
buildApp[Docker Build\n+ Artifact Registry]
end
subgraph Pulumi
sharedStack[Shared Stack]
envStacks[Dev/Prod Stacks]
end
planInfra --> sharedStack
releaseInfra --> sharedStack
releaseInfra --> envStacks
appCI -->|PR validation| GitHub
appRelease --> buildApp --> envStacks
| Workflow | Trigger | Purpose | Notes |
|---|---|---|---|
plan-infra.yml |
PRs touching infra | Pulumi preview for shared/dev/prod stacks | No apply; reviewers inspect preview output |
release-infra.yml |
infra-v* tags or manual dispatch |
Applies shared/dev/prod stacks via Pulumi | Workload Identity SA has infra IAM roles |
app-ci.yml |
PRs touching app/ or content/ |
Runs Astro lint/typecheck/test/build | Blocks merges that break the app |
app-release.yml |
Merge to main or app-v* tags |
One job builds + pushes Docker image (tag = ${GITHUB_SHA}-${GITHUB_RUN_ID}) and applies Pulumi to update Cloud Run |
Cloud Build runs asynchronously; Pulumi consumes the new image URI |
plugin-ci.yml |
PRs touching plugins/ or .claude-plugin/ |
Validates plugin structure, JSON schemas, marketplace consistency | Blocks merges with invalid plugin packages |
Tech Stack
- Frontend: Astro with Starlight (documentation theme), TypeScript, Tailwind CSS.
- Content Management: MDX stored under
app/src/content/docs/within git. Frontmatter is validated via Zod schemas (from Starlight) to keep metadata type-safe. Drafts can be marked withdraft: truein frontmatter. - Analytics & o11y:
- Google Analytics 4 for baseline PV/engagement.
- Optional custom
/api/trackendpoint writing to Cloud Logging โ BigQuery for privacy-friendly metrics. - Cloud Monitoring dashboards + alert policies (via Pulumi) for Cloud Run metrics.
- Infrastructure: Pulumi (Go) targeting Google Cloud.
- CI/CD: GitHub Actions with Workload Identity.
plan-infra.yml/release-infra.ymldrive infra,app-ci.yml/app-release.ymlhandle the Astro app. - Testing: Vitest for app tests, TypeScript compilation for infra, Playwright for future E2E if needed.
- LLM Context: Machine-readable
llms.txtfiles for AI assistants. Auto-generated at build time.
LLM Context Files (llms.txt)
The site provides structured context files for LLMs at https://koborin.ai/llms.txt.
| File | Content |
|---|---|
/llms.txt |
Index with links to all variants |
/llms-full.txt |
All English articles (full Markdown) |
/llms-ja-full.txt |
All Japanese articles (full Markdown) |
/llms-tech.txt |
English tech articles only |
/llms-ja-tech.txt |
Japanese tech articles only |
/llms-life.txt |
English life articles only |
/llms-ja-life.txt |
Japanese life articles only |
These files are auto-generated at build time from Content Collections. Articles with draft: true are excluded. No runtime overhead.
Repository Layout (planned)
.
โโโ .gcloudignore # Excludes files from Cloud Build upload
โโโ app/ # Astro + Starlight application (Static, nginx)
โ โโโ cloudbuild.yaml # Cloud Build config for Docker build
โ โโโ src/
โ โ โโโ assets/ # Images organized by category
โ โ โ โโโ _shared/ # Common assets (header logo)
โ โ โ โโโ tech/ # Tech article images
โ โ โ โโโ life/ # Life article images
โ โ โ โโโ about-me/ # About me article images
โ โ โโโ content/
โ โ โ โโโ docs/ # MDX documentation pages (Starlight)
โ โ โ โโโ config.ts # Content Collections schema
โ โ โโโ utils/
โ โ โ โโโ llms.ts # Shared logic for llms.txt generation
โ โ โโโ pages/ # Astro endpoints (llms.txt, RSS feeds)
โ โ โโโ styles/
โ โ โโโ custom.css # Custom CSS overrides (logo sizing, etc.)
โ โโโ public/
โ โ โโโ favicon.png # Browser tab icon
โ โ โโโ robots.txt
โ โโโ nginx/
โ โ โโโ nginx.conf # nginx configuration for static serving
โ โโโ Dockerfile # Multi-stage build (node โ nginx:alpine)
โ โโโ astro.config.mjs # Starlight integration config
โโโ docs/ # Architecture notes, contact-flow specs, etc.
โโโ infra/ # Pulumi Go stacks (shared/dev/prod)
โ โโโ main.go # Entry point
โ โโโ config.go # Configuration helpers
โ โโโ stacks/ # Stack definitions
โ โ โโโ shared.go # Shared resources (LB, APIs, WIF)
โ โ โโโ dev.go # Dev Cloud Run
โ โ โโโ prod.go # Prod Cloud Run
โ โโโ Pulumi.yaml # Project configuration
โ โโโ go.mod # Go module dependencies
โ โโโ go.sum # Go dependency checksums
โโโ .claude-plugin/ # Plugin marketplace manifest
โ โโโ marketplace.json # Registry of published plugins
โโโ plugins/ # Published Claude Code plugins
โ โโโ agent-team-fullstack/ # Agent Team orchestration plugin
โ โโโ mermaid-diagram/ # Mermaid diagram workflow plugin
โโโ .github/workflows/ # CI pipelines (plan/apply, app deploy, plugin validation)
โโโ README.md # This file
โโโ AGENTS.md # English operations guide for collaborators
Brand Assets
| Asset | Location | Usage | Notes |
|---|---|---|---|
| Favicon | app/public/favicon.png |
Browser tab icon | PNG format, transparent background recommended |
| Header Logo | app/src/assets/_shared/koborin-ai-header.webp |
Site header (replaces title text) | Horizontal layout, optimized for dark backgrounds |
| Hero Image | app/public/og/koborin-ai-hero.png |
Landing page hero section | 16:9 aspect ratio recommended |
Logo sizing is customized via app/src/styles/custom.css (.site-title img selector).
Image Optimization (Automatic)
For performance, images are automatically converted to WebP format. Authors can use PNG/JPEG normally - optimization happens during build/deploy.
| Image Type | Location | What You Do | What Happens Automatically |
|---|---|---|---|
| OG images | app/public/og/ |
Place PNG/JPEG, reference as .png |
CI converts to WebP, nginx serves WebP |
| Blog images | app/src/assets/{category}/{article}/ |
Place PNG/JPEG in article folder | Astro optimizes to WebP |
Example workflow for OG images:
- Place image:
app/public/og/my-article.png - Frontmatter:
ogImage: /og/my-article.png - Article display:

That's it! The CI pipeline (app/scripts/optimize-og-images.sh) generates WebP versions, and nginx automatically serves them.
Workflow Overview
- Infra changes: edit Pulumi Go stacks โ
go build ./... && go vet ./...โ open PR โ GitHub Actions runs preview โ reviewer approves โ merge triggers apply on the right environment. - App changes: edit Astro/MDX โ
npm run lint && npm run test && npm run typecheck && npm run check-images && npm run buildโ PR triggersapp-ci.ymlโ merge tomain(or tagapp-v*) triggersapp-release.ymlwhich builds the container, pushes to Artifact Registry, and feeds the new image to Pulumi. - Content-only updates: modify MDX under
app/src/content/docs/, update frontmatter (title,description), runnpm run lint, open PR. Mark drafts withdraft: truein frontmatter to exclude from production builds.
Adding New Content
To add a new article or page:
Create MDX file under
app/src/content/docs/(or subdirectory for categories):# Single page app/src/content/docs/my-article.mdx # Categorized page app/src/content/docs/blog/my-post.mdxAdd frontmatter with required fields:
--- title: My Article Title description: Brief description of the article publishedAt: 2025-01-02 ---publishedAt: Set the publish date manually (YYYY-MM-DD format).- Updated date is automatically extracted from Git history at build time.
Update sidebar in
app/src/sidebar.ts:export const sidebar = [ // ... existing items { label: "Blog", items: [ { label: "My Post", slug: "blog/my-post" }, ], }, ];Build and test locally before pushing.
Release Strategy
- Infra applies use
infra-v*tags to triggerrelease-infra.yml. Tag the repo after merging infra PRs even if app work is still ongoing; this ensures the latest load balancer/stateful resources are deployed before app images roll out. - App deploys use
app-v*tags to driveapp-release.yml. Tagging after a successfulmainmerge guarantees that the latest container image is built and the Cloud Run service is updated via Pulumi. - GitHub release notes are generated via
.github/release.yml. Label each PR withapp,infra,pulumi,feature,bug, ordocso the notes stay segmented by domain; apply theignorelabel to omit a PR entirely.
Local Setup (once the app repo is initialized)
# Node.js >= 20, npm 10 recommended
npm install
# Run Astro dev server (app directory)
npm run dev --prefix app
# Build infrastructure (infra directory)
cd infra && go build ./...
Infrastructure Dev Notes
- Pulumi stacks are located in
infra/stacks/. - GCP provider version is managed via
github.com/pulumi/pulumi-gcp/sdkGo module. - Each stack uses a GCS backend with automatic state management per stack name.
Shared Stack
- API enablement: Run, Compute, IAM, Artifact Registry, IAP, Monitoring, Logging, Certificate Manager.
- Artifact Registry: Container images repository (
koborin-ai-web). - Global static IP: PREMIUM tier for HTTPS load balancer.
- Managed SSL Certificate: Multi-domain (
koborin.ai,dev.koborin.ai). - HTTPS Load Balancer:
- Serverless NEGs (dev/prod) referencing Cloud Run services by name.
- Backend Services:
- Dev: IAP enabled +
X-Robots-Tag: noindex, nofollowheader. - Prod: No IAP, logging enabled.
- Dev: IAP enabled +
- URL Map (host-based routing).
- Target HTTPS Proxy.
- Global Forwarding Rule.
- Workload Identity Federation:
- Pool:
github-actions-pool. - Provider:
actions-firebase-provider(OIDC issuer:https://token.actions.githubusercontent.com). - Service Account:
github-actions-service@{project}.iam.gserviceaccount.com. - IAM binding: Subject-based binding for repository
koborin-ai/site. - Project IAM roles (Artifact Registry, Run, Compute, IAM, etc.) granted to the Pulumi SA.
- Pool:
- DNS: Records live in Cloudflare and are managed manually (A records point to the LB IP).
Dev Stack
- Cloud Run Service:
koborin-ai-web-dev.- Ingress:
INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER(LB-only access). - Execution Environment: Gen2.
- Environment Variables:
NODE_ENV=development(runtime mode).NEXT_PUBLIC_ENV=dev(client-side environment identifier).
- Scaling: Min 0, Max 1.
- Ingress:
Prod Stack
- Cloud Run Service:
koborin-ai-web-prod.- Ingress:
INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER(LB-only access). - Execution Environment: Gen2.
- Environment Variables:
NODE_ENV=production(runtime mode).NEXT_PUBLIC_ENV=prod(client-side environment identifier).
- Scaling: Min 0, Max 10.
- Ingress:
Contact & Analytics Design (planned)
- Contact form will post to
/api/contact(Astro API Route) with:- Payload validation (Zod), reCAPTCHA enforcement, structured logging to Cloud Logging.
- Notification via SendGrid or Gmail API (configured via Secret Manager).
/api/trackendpoint will receive custom events and forward to Cloud Logging/BigQuery.- GA4 integration via gtag.js (prod only, injected at build time via
PUBLIC_GA_MEASUREMENT_ID).
Environment Variables
| Variable | Purpose | Where to Set |
|---|---|---|
GA_MEASUREMENT_ID |
GA4 Measurement ID (e.g., G-XXXXXXXXXX) |
GitHub Secrets |
The workflow creates a .env file with PUBLIC_GA_MEASUREMENT_ID only for prod builds. Dev builds do not include GA4 tracking.
Documentation
README.md: quickstart + architectural highlights (this file).AGENTS.md: contribution workflow, review checklist, release rules, IaC philosophy.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found