koborin-ai
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
No AI report is available for this listing yet.
๐ชด 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
nozomi-koborinai/koborin-ai. - 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