Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions skills/create-go-api/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: create-go-api
description: Creates a new Go API project (net/http) by copying the go/api template files and installs custom AI rules.
inputs:
- id: workspace_name
name: Workspace Name
type: string
description: The name of the folder for the new project
---

## When to Use This Skill

Use this skill when the user wants to create a minimal Go HTTP API project (stdlib `net/http`) from the Go API template (`go/api`) and run it locally with Go installed.

## Instructions

1. **Read Setup Instructions**
Review the [setup instructions](resources/setup_instructions.md) to understand how to initialize the project and install prerequisites.

*Action:* Read `resources/setup_instructions.md`.

2. **Execute Setup**
Follow the steps outlined in `resources/setup_instructions.md` to:
- Ensure Go is installed (Go 1.20+).
- Create the workspace folder (using the `workspace_name` input).
- Copy template files from `go/api` into the new workspace.
- Create the `.agents/rules/go-api.md` file using the content from `resources/ai_rules.md`.
- Ensure the `.agents/rules/` directory exists.

3. **Final Verification**
Check that:
- `main.go` exists in the new project
- `go.mod` exists in the new project
- `README.md` exists in the new project
- `.agents/rules/go-api.md` exists
77 changes: 77 additions & 0 deletions skills/create-go-api/resources/ai_rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Gemini AI Rules for Go API Projects

## 1. Persona & Expertise

You are an expert backend developer specializing in Go (Golang) and HTTP APIs. You understand:
- Idiomatic Go (packages, interfaces, error handling)
- `net/http` server patterns (handlers, middleware-style wrappers)
- Context propagation (`context.Context`) for cancellation/timeouts
- JSON APIs (encoding/decoding, validation, status codes)
- Logging and observability basics
- Secure handling of environment variables and secrets

## 2. Project Context

This project is a minimal Go backend API service (stdlib `net/http`) based on:
https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-go-service

It is intended to be used as a Firebase Studio (formerly Project IDX) template/workspace and also runnable locally if the user has Go installed.

Default assumptions:
- Single entrypoint: `main.go`
- Go module defined in `go.mod`
- Server listens on `PORT` env var (defaults to `3000`)
- Optional greeting uses `NAME` env var (defaults to `World`)

## 3. Development Environment

This project is configured to run in a pre-built developer environment provided by Firebase Studio, where the environment is typically defined in Nix (`idx-template.nix` / `dev.nix`).

When providing instructions:
- Assume the Firebase Studio environment may already provide Go.
- Locally, the user must have Go installed (Go 1.20+ required by this template).
- Running the app is usually done via:
- `go run main.go`
- The service is typically available at:
- `http://localhost:3000`

## 4. Coding Standards & Best Practices

### General Go
- Prefer idiomatic Go: small functions, clear naming, minimal magic.
- Run `gofmt` on any Go code you generate.
- Avoid introducing new dependencies unless necessary.
- If adding dependencies, explain why and instruct to run:
- `go get <module>`
- and/or `go mod tidy`

### HTTP / API Behavior
- Use correct status codes:
- 200 OK for success
- 201 Created for creates (when applicable)
- 400 Bad Request for validation errors
- 401 Unauthorized / 403 Forbidden for auth-related failures
- 404 Not Found for unknown routes/resources
- 500 Internal Server Error for unexpected failures
- Avoid panics in request paths. Return safe errors and log details server-side.
- Prefer explicit request validation and clear error messages.

### Context & Timeouts
- Use `r.Context()` and propagate it to downstream calls.
- For outbound calls (DB/HTTP), use timeouts (e.g., `context.WithTimeout`).

### Secrets & Environment Variables
- Never hardcode secrets (tokens, keys, credentials).
- Use environment variables for configuration.
- Avoid logging secrets.

## 5. Interaction Guidelines

- Provide clear, actionable steps.
- When generating code, provide complete file contents (especially for `main.go`).
- If the request is ambiguous, ask for clarification about:
- Routes/endpoints required
- JSON vs plain-text responses
- Authentication requirements
- Data store (if any)
- Keep instructions compatible with both Firebase Studio (Nix-based environment) and local setups.
84 changes: 84 additions & 0 deletions skills/create-go-api/resources/setup_instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Go API Workspace Setup Instructions

Follow these steps to initialize the workspace.

## 1. Install prerequisites (Go)

This skill requires:
- Go (1.20+)

### 1.1 Verify
Run:
- `go version`

If it works and the version is **1.20+**, go to **Step 2**.

### 1.2 Install automatically from official Go downloads (recommended)
Run ONE of the following depending on your OS:

#### Windows (PowerShell)
Run:
- `powershell -ExecutionPolicy Bypass -File "scripts/install_go_official.ps1"`

Then restart terminal / Antigravity session and verify:
- `go version`

#### macOS / Linux (bash)
Run:
- `bash "scripts/install_go_official.sh"`

Then restart shell and verify:
- `go version`

---

## 2. Create the project (copy template files)

Set workspace name:
- `WS_NAME="<workspace_name>"`

From the repo root (or any directory), create the folder:

```bash
mkdir -p "$WS_NAME"
```
- Copy the Go API template files into the workspace:

# Copy from this repo’s go/api template into the new workspace
cp -R "<skill_root>/../../go/api/." "$WS_NAME/"

Then enter the workspace:

cd "$WS_NAME"

## 3. Configure Agents Rules

Create: .agents/rules/go-api.md inside the new workspace directory.

Copy the content from: resources/ai_rules.md

Commands:

mkdir -p .agents/rules
# then create .agents/rules/go-api.md and paste contents from resources/ai_rules.md

## 4. Run server
go run main.go

The server runs on:

http://localhost:3000 (default)

Optional env vars:

PORT to change port

NAME to change greeting

Verify:

curl http://localhost:3000/

Expected response contains:

Hello World!
123 changes: 123 additions & 0 deletions skills/create-go-api/scripts/install_go_official.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Installs the latest stable Go from official go.dev downloads (user-local install).
# - Detects CPU architecture
# - Fetches latest stable from https://go.dev/dl/?mode=json
# - Downloads the official ZIP
# - Extracts to %LOCALAPPDATA%\Programs\go\current
# - Adds %LOCALAPPDATA%\Programs\go\current\bin to user PATH (no admin required)
# - Prompts to restart terminal / Antigravity

$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest

$MinGoVersion = if ($env:MIN_GO_VERSION) { $env:MIN_GO_VERSION } else { "1.20.0" }

function Get-GoVersion {
try {
$out = & go version 2>$null
# "go version go1.22.5 windows/amd64"
$tok = $out.Split(" ")[2]
return $tok.Replace("go","") # "1.22.5"
} catch {
return $null
}
}

function Version-ToInt([string]$v) {
# "1.22.5" -> comparable int
$m = [regex]::Match($v, '^(\d+)\.(\d+)(?:\.(\d+))?$')
if (-not $m.Success) { return 0 }
$a = [int]$m.Groups[1].Value
$b = [int]$m.Groups[2].Value
$c = if ($m.Groups[3].Success) { [int]$m.Groups[3].Value } else { 0 }
return ($a * 1000000) + ($b * 1000) + $c
}

function Get-LatestStableGoVersionTag {
$data = Invoke-RestMethod -Uri "https://go.dev/dl/?mode=json"
$stable = $data | Where-Object { $_.stable -eq $true } | Select-Object -First 1
if (-not $stable -or -not $stable.version) {
throw "Could not determine latest stable Go version from https://go.dev/dl/?mode=json"
}
return $stable.version # e.g., "go1.22.5"
}

function Get-WindowsArchSuffix {
$arch = $env:PROCESSOR_ARCHITECTURE
switch ($arch) {
"AMD64" { return "windows-amd64" }
"ARM64" { return "windows-arm64" }
default { throw "Unsupported Windows architecture: $arch" }
}
}

# If Go already installed and >= MinGoVersion, do nothing.
$existing = Get-GoVersion
if ($existing) {
if ((Version-ToInt $existing) -ge (Version-ToInt $MinGoVersion)) {
Write-Host "Go is already installed (go$existing). No action needed."
exit 0
}
Write-Host "Go detected (go$existing) but < $MinGoVersion; proceeding to install latest stable."
}

$versionTag = Get-LatestStableGoVersionTag # "go1.22.5"
$platform = Get-WindowsArchSuffix # "windows-amd64"
$zipName = "$versionTag.$platform.zip" # "go1.22.5.windows-amd64.zip"
$zipUrl = "https://go.dev/dl/$zipName"

$installBase = Join-Path $env:LOCALAPPDATA "Programs\go"
$installDir = Join-Path $installBase "current"
$goBin = Join-Path $installDir "bin"

New-Item -ItemType Directory -Force -Path $installBase | Out-Null

$tmpDir = Join-Path $env:TEMP ("go-install-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Force -Path $tmpDir | Out-Null

$zipPath = Join-Path $tmpDir $zipName
$extractDir = Join-Path $tmpDir "extract"
New-Item -ItemType Directory -Force -Path $extractDir | Out-Null

try {
Write-Host "Downloading $zipUrl"
Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath

Write-Host "Extracting ZIP"
Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force

$extractedGoRoot = Join-Path $extractDir "go"
if (-not (Test-Path $extractedGoRoot)) {
throw "Extraction failed; expected folder not found: $extractedGoRoot"
}

# Install into ...\Programs\go\current (replace if exists)
if (Test-Path $installDir) {
Remove-Item -Recurse -Force $installDir
}
Move-Item -Path $extractedGoRoot -Destination $installDir

# Add to user PATH if not present
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if (-not $userPath) { $userPath = "" }

$already = $userPath.Split(";") | Where-Object { $_.Trim() -ieq $goBin }
if (-not $already) {
$newUserPath = ($goBin + ";" + $userPath).TrimEnd(";")
[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
Write-Host "Added Go to user PATH: $goBin"
} else {
Write-Host "Go bin path already present in user PATH."
}

# Also update current session PATH
$env:Path = $goBin + ";" + $env:Path

Write-Host "Installed Go ($versionTag) into $installDir"
Write-Host "Verify:"
& go version

Write-Host ""
Write-Host "Restart your terminal / Antigravity session so PATH updates fully."
} finally {
if (Test-Path $tmpDir) { Remove-Item -Recurse -Force $tmpDir }
}
Loading