go-embedded-spa
Skill18 starsChanged 7 months agoMITView on GitHub
This skill provides guidance for implementing Go Embedded SPA architecture - embedding React/Vue/TSX frontend static resources into Go binary using go:embed directive. Use this skill when building self-contained single-binary applications, implementing SPA with Go backend, setting up cross-platform deployable full-stack projects, or configuring static file serving with Go standard library net/http.
In this repository28 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- brainstormingSkill
- dispatching-parallel-agentsSkill
- executing-plansSkill
- find-skillsSkill
- finishing-a-development-branchSkill
- golang-cli-cobra-viperSkill
- golang-testingSkill
- receiving-code-reviewSkill
- requesting-code-reviewSkill
- skill-creatorSkill
- skills-xSkill
- subagent-driven-developmentSkill
- systematic-debuggingSkill
- test-driven-developmentSkill
- using-superpowersSkill
- verification-before-completionSkill
- writing-plansSkill
- writing-skillsSkill
- baidu-speech-to-textSkill
- feishu-notifySkill
- go-i18nSkill
- go-pocketbase-integrationSkill
- minimal-ui-designSkill
- shadowrocket-claude-routingSkill
- skills-xSkill
- tui-designSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 48
Create site/embed.go to declare embed directive.
- Very specific: line 51
Use //go:embed all:dist to embed all files including hidden files
- Very specific: line 52
Use fs.Sub() to remove dist/ prefix
- Very specific: line 56
Create pkg/siteserver/siteserver.go.
- Very specific: line 60
Create http.FileServer from embed.FS
- Distinctive: line 96
Recommended: Start both backend and frontend with one command:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Go Embedded SPA
Overview
Go Embedded SPA is a technique that embeds frontend SPA (Single Page Application) static resources (React/Vue/TSX) into Go binary files using Go 1.16+ embed package, achieving single-binary full-stack deployment.
Core Benefits
| Benefit | Description |
| 🎯 Single File Deploy | One binary contains both frontend and backend, no nginx needed |
| 🌍 Cross-Platform | GOOS/GOARCH easily compiles for Linux/Mac/Windows |
| 📦 Zero Dependencies | Target machine needs no Node.js/npm, uses Go standard library only |
| 🚀 Container Friendly | Dockerfile only needs COPY + ENTRYPOINT |
| 🔒 Resource Security | Static resources compiled into binary, tamper-proof |
| ⚡ Fast Startup | No disk I/O for loading static files |
Project Structure
project/
├── go.mod
├── Makefile
├── site/ # Frontend project
│ ├── embed.go # Go embed directive
│ ├── src/ # React/Vue source
│ ├── dist/ # Build output (embedded)
│ ├── package.json
│ ├── vite.config.ts
│ └── index.html
├── pkg/
│ └── siteserver/ # Static file server
│ └── siteserver.go
└── cmd/
└── app/
└── main.goImplementation Steps
Step 1: Create embed.go
Create site/embed.go to declare embed directive. See references/embed.md for complete code.
Key points:
- Use
//go:embed all:distto embed all files including hidden files - Use
fs.Sub()to removedist/prefix
Step 2: Create Static File Server
Create pkg/siteserver/siteserver.go. See references/siteserver.md for complete implementation using Go standard net/http.
Core logic:
- Pre-load
index.htmlfor SPA fallback - Create
http.FileServerfrom embed.FS - Detect static resources by file extension
- Return
index.htmlfor SPA routes (no file extension)
Step 3: Application Integration
package main
import (
"log"
"net/http"
"your-project/pkg/siteserver"
"your-project/site"
)
func main() {
mux := http.NewServeMux()
// 1. Register API routes FIRST
mux.HandleFunc("/apis/v1/health", healthHandler)
mux.HandleFunc("/apis/v1/data", dataHandler)
// 2. Wrap with static file server (as fallback)
handler := siteserver.WrapHandler(mux, site.DistDirFS)
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", handler))
}Order is critical: API routes must be registered before static file server.
Step 4: Development
Recommended: Start both backend and frontend with one command:
make dev
# Backend: http://localhost:8080 (Go)
# Frontend: http://localhost:5173 (Vite with hot reload)
# API Proxy: /api/* -> localhost:8080Press Ctrl+C to stop both servers.
Step 5: Build for Production
Build order: frontend first, then backend
make build # Build both (frontend + backend)
# Or separately:
make build-web # npm run build → site/dist/
make build-backend # go build (embeds dist/)Step 6: Cross-Platform Build
make build-linux # Linux amd64
make build-linux-arm64 # Linux arm64
make build-macos # macOS Intel
make build-macos-arm64 # macOS Apple Silicon
make build-windows # Windows amd64
make build-all # All platformsRequest Handling Flow
Browser Request
│
▼
┌─────────────────────────────────────┐
│ http.ServeMux Route Matching │
│ ├── /apis/* → API Handler │
│ └── Others → Static Handler │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Static Handler │
│ ├── Has extension → serve file │
│ └── No extension → return index.html│
└─────────────────────────────────────┘Caching Strategy
| Path | Cache-Control | Reason |
/assets/* | max-age=31536000, immutable | Files have hash in name |
/index.html | no-cache | Entry must be fresh |
Container Deployment
Minimal Dockerfile:
FROM scratch
COPY app /app
ENTRYPOINT ["/app"]Troubleshooting
- Empty dist error → Run
make build-webbeforemake build-backend - Static files 404 → Check
//go:embed all:distpath relative to embed.go - API not matching → Register API routes BEFORE wrapping with siteserver
- SPA routes 404 → Verify handler returns index.html for non-file paths
References
go-dependencies.md- Go module dependencies (standard library only)embed.md- Complete embed.go implementationsiteserver.md- Static file server using Go standard net/httpvite-config.md- Vite configuration for development proxymakefile.md- Complete Makefile with cross-platform build
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

