This commit is contained in:
anthdm
2024-04-24 19:52:05 +02:00
commit af9c83cbd0
31 changed files with 1515 additions and 0 deletions

33
.air.toml Normal file
View File

@@ -0,0 +1,33 @@
root = "."
tmp_dir = "tmp"
[build]
bin = "./tmp/main"
cmd = "go build -tags dev -o ./tmp/main ."
delay = 20
exclude_dir = ["assets", "tmp", "vendor"]
exclude_file = []
exclude_regex = [".*_templ.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "templ", "html"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
stop_on_error = true
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
time = false
[misc]
clean_on_exit = false

1
.env Normal file
View File

@@ -0,0 +1 @@
LISTEN_ADDR=":4000"

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
bin

9
Makefile Normal file
View File

@@ -0,0 +1,9 @@
run: build
@./bin/app
build:
@go build -o bin/app .
css:
tailwindcss -i views/css/app.css -o public/styles.css --watch

0
README.md Normal file
View File

BIN
bin/app Executable file

Binary file not shown.

9
go.mod Normal file
View File

@@ -0,0 +1,9 @@
module gothstarter
go 1.22.0
require (
github.com/a-h/templ v0.2.663 // indirect
github.com/go-chi/chi/v5 v5.0.12 // indirect
github.com/joho/godotenv v1.5.1 // indirect
)

6
go.sum Normal file
View File

@@ -0,0 +1,6 @@
github.com/a-h/templ v0.2.663 h1:aa0WMm27InkYHGjimcM7us6hJ6BLhg98ZbfaiDPyjHE=
github.com/a-h/templ v0.2.663/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=

10
handlers/auth.go Normal file
View File

@@ -0,0 +1,10 @@
package handlers
import (
"gothstarter/views/auth"
"net/http"
)
func HandleLoginIndex(w http.ResponseWriter, r *http.Request) error {
return Render(w, r, auth.Login())
}

10
handlers/home.go Normal file
View File

@@ -0,0 +1,10 @@
package handlers
import (
"gothstarter/views/home"
"net/http"
)
func HandleHome(w http.ResponseWriter, r *http.Request) error {
return Render(w, r, home.Index())
}

22
handlers/shared.go Normal file
View File

@@ -0,0 +1,22 @@
package handlers
import (
"log/slog"
"net/http"
"github.com/a-h/templ"
)
type HTTPHandler func(w http.ResponseWriter, r *http.Request) error
func Make(h HTTPHandler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := h(w, r); err != nil {
slog.Error("HTTP handler error", "err", err, "path", r.URL.Path)
}
}
}
func Render(w http.ResponseWriter, r *http.Request, c templ.Component) error {
return c.Render(r.Context(), w)
}

27
main.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import (
"gothstarter/handlers"
"log"
"log/slog"
"net/http"
"os"
"github.com/go-chi/chi/v5"
"github.com/joho/godotenv"
)
func main() {
if err := godotenv.Load(); err != nil {
log.Fatal(err)
}
router := chi.NewMux()
router.Handle("/*", public())
router.Get("/", handlers.Make(handlers.HandleHome))
router.Get("/login", handlers.Make(handlers.HandleLoginIndex))
listenAddr := os.Getenv("LISTEN_ADDR")
slog.Info("HTTP server started", "listenAddr", listenAddr)
http.ListenAndServe(listenAddr, router)
}

1103
public/styles.css Normal file

File diff suppressed because it is too large Load Diff

16
static_dev.go Normal file
View File

@@ -0,0 +1,16 @@
//+build dev
//go:build dev
// +build dev
package main
import (
"fmt"
"net/http"
"os"
)
func public() http.Handler {
fmt.Println("building static files for development")
return http.StripPrefix("/public/", http.FileServerFS(os.DirFS("public")))
}

16
static_prod.go Normal file
View File

@@ -0,0 +1,16 @@
//go:build !dev
// +build !dev
package main
import (
"embed"
"net/http"
)
//go:embed public
var publicFS embed.FS
func public() http.Handler {
return http.FileServerFS(publicFS)
}

6
tailwind.config.js Normal file
View File

@@ -0,0 +1,6 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [ "./**/*.html", "./**/*.templ", "./**/*.go", ],
safelist: [],
}

1
tmp/build-errors.log Normal file
View File

@@ -0,0 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
tmp/main Executable file

Binary file not shown.

5
views/auth/login.templ Normal file
View File

@@ -0,0 +1,5 @@
package auth
templ Login() {
<div>on the login page</div>
}

35
views/auth/login_templ.go Normal file
View File

@@ -0,0 +1,35 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.596
package auth
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
func Login() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}

View File

@@ -0,0 +1 @@
<div>on the login page</div>

View File

@@ -0,0 +1,19 @@
package components
templ Navigation() {
<div class="border-b border-gray-800 py-2">
<div class="container mx-auto">
<div class="flex justify-between">
<div class>GOTHSTARTER</div>
<div class="flex space-x-12">
<div class="space-x-3 flex text-blue-500"></div>
<div>
<button type="button" class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900 focus:shadow-outline focus:outline-none">
login
</button>
</div>
</div>
</div>
</div>
</div>
}

View File

@@ -0,0 +1,35 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.596
package components
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
func Navigation() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}

View File

@@ -0,0 +1 @@
<div class=\"border-b border-gray-800 py-2\"><div class=\"container mx-auto\"><div class=\"flex justify-between\"><div class>GOTHSTARTER</div><div class=\"flex space-x-12\"><div class=\"space-x-3 flex text-blue-500\"></div><div><button type=\"button\" class=\"inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900 focus:shadow-outline focus:outline-none\">login</button></div></div></div></div></div>

3
views/css/app.css Normal file
View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

11
views/home/index.templ Normal file
View File

@@ -0,0 +1,11 @@
package home
import (
"gothstarter/views/layouts"
)
templ Index() {
@layouts.Base() {
<div class="flex flex-col items-center"></div>
}
}

54
views/home/index_templ.go Normal file
View File

@@ -0,0 +1,54 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.596
package home
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
import (
"gothstarter/views/layouts"
)
func Index() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = io.Copy(templ_7745c5c3_W, templ_7745c5c3_Buffer)
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layouts.Base().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}

View File

@@ -0,0 +1 @@
<div class=\"flex flex-col items-center\"></div>

26
views/layouts/base.templ Normal file
View File

@@ -0,0 +1,26 @@
package layouts
import (
"gothstarter/views/components"
)
templ Base() {
<!DOCTYPE html>
<html lang="en">
<head>
<title>GOTHSTARTER</title>
<link rel="icon" type="image/x-icon" href="/public/favicon.ico"/>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="/public/styles.css"/>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/alpinejs" defer></script>
<script src="https://unpkg.com/htmx.org@1.9.9" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/js/all.min.js"></script>
</head>
<body class="antialiased">
@components.Navigation()
{ children... }
</body>
</html>
}

View File

@@ -0,0 +1,51 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.596
package layouts
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import "context"
import "io"
import "bytes"
import (
"gothstarter/views/components"
)
func Base() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
if !templ_7745c5c3_IsBuffer {
templ_7745c5c3_Buffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = components.Navigation().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if !templ_7745c5c3_IsBuffer {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
}
return templ_7745c5c3_Err
})
}

View File

@@ -0,0 +1,2 @@
<!doctype html><html lang=\"en\"><head><title>GOTHSTARTER</title><link rel=\"icon\" type=\"image/x-icon\" href=\"/public/favicon.ico\"><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><link rel=\"stylesheet\" href=\"/public/styles.css\"><script src=\"https://code.jquery.com/jquery-3.7.1.min.js\" integrity=\"sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=\" crossorigin=\"anonymous\"></script><script src=\"https://unpkg.com/alpinejs\" defer></script><script src=\"https://unpkg.com/htmx.org@1.9.9\" defer></script><script src=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/js/all.min.js\"></script></head><body class=\"antialiased\">
</body></html>