mirror of
https://github.com/kevin-DL/gothstarter.git
synced 2026-01-11 01:54:32 +00:00
initial
This commit is contained in:
33
.air.toml
Normal file
33
.air.toml
Normal 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
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.env
|
||||
bin
|
||||
9
Makefile
Normal file
9
Makefile
Normal 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
|
||||
9
go.mod
Normal file
9
go.mod
Normal 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
6
go.sum
Normal 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
10
handlers/auth.go
Normal 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
10
handlers/home.go
Normal 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
22
handlers/shared.go
Normal 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
27
main.go
Normal 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
1103
public/styles.css
Normal file
File diff suppressed because it is too large
Load Diff
16
static_dev.go
Normal file
16
static_dev.go
Normal 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
16
static_prod.go
Normal 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
6
tailwind.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [ "./**/*.html", "./**/*.templ", "./**/*.go", ],
|
||||
safelist: [],
|
||||
}
|
||||
|
||||
1
tmp/build-errors.log
Normal file
1
tmp/build-errors.log
Normal 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
|
||||
5
views/auth/login.templ
Normal file
5
views/auth/login.templ
Normal file
@@ -0,0 +1,5 @@
|
||||
package auth
|
||||
|
||||
templ Login() {
|
||||
<div>on the login page</div>
|
||||
}
|
||||
35
views/auth/login_templ.go
Normal file
35
views/auth/login_templ.go
Normal 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
|
||||
})
|
||||
}
|
||||
1
views/auth/login_templ.txt
Normal file
1
views/auth/login_templ.txt
Normal file
@@ -0,0 +1 @@
|
||||
<div>on the login page</div>
|
||||
19
views/components/navigation.templ
Normal file
19
views/components/navigation.templ
Normal 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>
|
||||
}
|
||||
35
views/components/navigation_templ.go
Normal file
35
views/components/navigation_templ.go
Normal 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
|
||||
})
|
||||
}
|
||||
1
views/components/navigation_templ.txt
Normal file
1
views/components/navigation_templ.txt
Normal 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
3
views/css/app.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
11
views/home/index.templ
Normal file
11
views/home/index.templ
Normal 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
54
views/home/index_templ.go
Normal 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
|
||||
})
|
||||
}
|
||||
1
views/home/index_templ.txt
Normal file
1
views/home/index_templ.txt
Normal file
@@ -0,0 +1 @@
|
||||
<div class=\"flex flex-col items-center\"></div>
|
||||
26
views/layouts/base.templ
Normal file
26
views/layouts/base.templ
Normal 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>
|
||||
}
|
||||
51
views/layouts/base_templ.go
Normal file
51
views/layouts/base_templ.go
Normal 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
|
||||
})
|
||||
}
|
||||
2
views/layouts/base_templ.txt
Normal file
2
views/layouts/base_templ.txt
Normal 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>
|
||||
Reference in New Issue
Block a user