feat: bootstrap design kit and vaporwave demo baseline
This commit is contained in:
12
kit/scaffolds/go-nethttp-web/Makefile
Normal file
12
kit/scaffolds/go-nethttp-web/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
run:
|
||||
go run ./cmd/demo-server
|
||||
|
||||
build:
|
||||
go build ./cmd/demo-server
|
||||
|
||||
test:
|
||||
go test ./...
|
||||
|
||||
fmt:
|
||||
gofmt -w $$(find . -name '*.go' -type f)
|
||||
|
||||
10
kit/scaffolds/go-nethttp-web/README.md
Normal file
10
kit/scaffolds/go-nethttp-web/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Go net/http Web Skeleton
|
||||
|
||||
Minimal starter skeleton for a Go web app using:
|
||||
|
||||
- `net/http`
|
||||
- `html/template`
|
||||
- embedded templates and static assets
|
||||
|
||||
This scaffold is intended as a starting point that host repositories can adapt.
|
||||
|
||||
23
kit/scaffolds/go-nethttp-web/internal/web/handlers.go.tmpl
Normal file
23
kit/scaffolds/go-nethttp-web/internal/web/handlers.go.tmpl
Normal file
@@ -0,0 +1,23 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type IndexViewData struct {
|
||||
Title string
|
||||
}
|
||||
|
||||
func (s *Server) handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
_ = s.render(w, "base.html", IndexViewData{Title: "Home"})
|
||||
}
|
||||
|
||||
func (s *Server) handleHealthz(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("ok"))
|
||||
}
|
||||
|
||||
37
kit/scaffolds/go-nethttp-web/internal/web/server.go.tmpl
Normal file
37
kit/scaffolds/go-nethttp-web/internal/web/server.go.tmpl
Normal file
@@ -0,0 +1,37 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
||||
appweb "{{ .module_path }}/web"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
mux *http.ServeMux
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
func NewServer() (*Server, error) {
|
||||
tmpl, err := parseTemplates()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := &Server{
|
||||
mux: http.NewServeMux(),
|
||||
tmpl: tmpl,
|
||||
}
|
||||
s.registerRoutes()
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Server) Handler() http.Handler { return s.mux }
|
||||
|
||||
func (s *Server) registerRoutes() {
|
||||
s.mux.HandleFunc("/", s.handleIndex)
|
||||
s.mux.HandleFunc("/healthz", s.handleHealthz)
|
||||
staticFS, _ := fs.Sub(appweb.Assets, "static")
|
||||
s.mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))
|
||||
}
|
||||
|
||||
27
kit/scaffolds/go-nethttp-web/internal/web/templates.go.tmpl
Normal file
27
kit/scaffolds/go-nethttp-web/internal/web/templates.go.tmpl
Normal file
@@ -0,0 +1,27 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
appweb "{{ .module_path }}/web"
|
||||
)
|
||||
|
||||
func parseTemplates() (*template.Template, error) {
|
||||
t, err := template.ParseFS(appweb.Assets, "templates/*.html")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse templates: %w", err)
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (s *Server) render(w http.ResponseWriter, name string, data any) error {
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
if err := s.tmpl.ExecuteTemplate(w, name, data); err != nil {
|
||||
http.Error(w, "template error", http.StatusInternalServerError)
|
||||
return fmt.Errorf("render %s: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
9
kit/scaffolds/go-nethttp-web/web/embed.go
Normal file
9
kit/scaffolds/go-nethttp-web/web/embed.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package web
|
||||
|
||||
import "embed"
|
||||
|
||||
// Assets contains templates and static files.
|
||||
//
|
||||
//go:embed templates/* static/*
|
||||
var Assets embed.FS
|
||||
|
||||
46
kit/scaffolds/go-nethttp-web/web/static/css/app.css
Normal file
46
kit/scaffolds/go-nethttp-web/web/static/css/app.css
Normal file
@@ -0,0 +1,46 @@
|
||||
:root {
|
||||
--bg: #e6e8ee;
|
||||
--ink: #1f2023;
|
||||
--muted: #5d646f;
|
||||
--card: linear-gradient(180deg, rgba(252,252,253,0.99), rgba(240, 244, 249, 0.97) 44%, rgba(228, 238, 248, 0.96) 78%, rgba(221, 234, 248, 0.96));
|
||||
--line: #b9cbe0;
|
||||
--accent: linear-gradient(180deg, #85b8ef 0%, #93c6fb 26%, #abd8ff 55%, #c7e8ff 82%, #def2ff 100%);
|
||||
--accent-line: #88a4d4;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Lucida Grande", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
background:
|
||||
radial-gradient(760px 360px at 14% 6%, rgba(255,255,255,0.82), transparent 72%),
|
||||
radial-gradient(760px 360px at 88% 8%, rgba(154, 203, 247, 0.16), transparent 74%),
|
||||
repeating-linear-gradient(to bottom, rgba(255,255,255,0.05) 0 1px, rgba(170,182,198,0.03) 1px 3px),
|
||||
linear-gradient(#eef1f6, #dde2ea);
|
||||
color: var(--ink);
|
||||
}
|
||||
.shell {
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 16px 48px;
|
||||
}
|
||||
.hero { margin-bottom: 16px; }
|
||||
.eyebrow {
|
||||
margin: 0;
|
||||
color: #5f6772;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: 12px;
|
||||
}
|
||||
h1 { margin: 6px 0 0; font-size: 32px; }
|
||||
.card {
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255,255,255,0.70), rgba(255,255,255,0.18) 28%, rgba(255,255,255,0.0) 29%),
|
||||
repeating-linear-gradient(to bottom, rgba(255,255,255,0.26) 0 1px, rgba(188,205,223,0.10) 1px 3px),
|
||||
var(--card);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 14px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 10px 20px rgba(78, 107, 139, 0.09), inset 0 1px 0 rgba(255,255,255,0.96);
|
||||
}
|
||||
code { background: #eef3fb; padding: 1px 5px; border-radius: 6px; }
|
||||
2
kit/scaffolds/go-nethttp-web/web/static/js/app.js
Normal file
2
kit/scaffolds/go-nethttp-web/web/static/js/app.js
Normal file
@@ -0,0 +1,2 @@
|
||||
document.documentElement.classList.add("js");
|
||||
|
||||
22
kit/scaffolds/go-nethttp-web/web/templates/base.html
Normal file
22
kit/scaffolds/go-nethttp-web/web/templates/base.html
Normal file
@@ -0,0 +1,22 @@
|
||||
{{ define "base.html" }}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ .Title }}</title>
|
||||
<link rel="stylesheet" href="/static/css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
<main class="shell">
|
||||
<header class="hero">
|
||||
<p class="eyebrow">Go Web Scaffold</p>
|
||||
<h1>{{ .Title }}</h1>
|
||||
</header>
|
||||
{{ template "content" . }}
|
||||
</main>
|
||||
<script src="/static/js/app.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
|
||||
11
kit/scaffolds/go-nethttp-web/web/templates/index.html
Normal file
11
kit/scaffolds/go-nethttp-web/web/templates/index.html
Normal file
@@ -0,0 +1,11 @@
|
||||
{{ define "content" }}
|
||||
<section class="card">
|
||||
<p>Minimal net/http + html/template scaffold.</p>
|
||||
<ul>
|
||||
<li><code>GET /</code> page</li>
|
||||
<li><code>GET /healthz</code> healthcheck</li>
|
||||
<li><code>/static/*</code> embedded assets</li>
|
||||
</ul>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
Reference in New Issue
Block a user