diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c849add
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+live/templ:
+ templ generate --watch --proxy="http://localhost:8080" --cmd="go run ./cmd" --open-browser=false -v
+
+live/sync_assets:
+ go run github.com/air-verse/air@v1.61.7 \
+ --build.cmd "templ generate --notify-proxy" \
+ --build.bin "true" \
+ --build.delay "100" \
+ --build.exclude_dir "" \
+ --build.include_dir "web/static" \
+ --build.include_ext "js,css"
+
+live:
+ make -j2 live/templ live/sync_assets
diff --git a/cmd/main.go b/cmd/main.go
new file mode 100644
index 0000000..8da5d7b
--- /dev/null
+++ b/cmd/main.go
@@ -0,0 +1,39 @@
+package main
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/dominicf2001/comfychan/web/views"
+ "github.com/dominicf2001/comfychan/web/views/boards"
+)
+
+var dev = true
+
+func disableCacheInDevMode(next http.Handler) http.Handler {
+ if !dev {
+ return next
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Cache-Control", "no-store")
+ next.ServeHTTP(w, r)
+ })
+}
+
+func main() {
+ http.Handle("/static/",
+ disableCacheInDevMode(
+ http.StripPrefix("/static",
+ http.FileServer(http.Dir("web/static")))))
+
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ views.Index().Render(r.Context(), w)
+ })
+
+ http.HandleFunc("/comfy", func(w http.ResponseWriter, r *http.Request) {
+ boards.Comfy().Render(r.Context(), w)
+ })
+
+ fmt.Println("Listening on :8080")
+ http.ListenAndServe(":8080", nil)
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..829ca38
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module github.com/dominicf2001/comfychan
+
+go 1.23.8
+
+require github.com/a-h/templ v0.3.857
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..62aa53a
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,4 @@
+github.com/a-h/templ v0.3.857 h1:6EqcJuGZW4OL+2iZ3MD+NnIcG7nGkaQeF2Zq5kf9ZGg=
+github.com/a-h/templ v0.3.857/go.mod h1:qhrhAkRFubE7khxLZHsBFHfX+gWwVNKbzKeF9GlPV4M=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
diff --git a/internal/db/db.go b/internal/db/db.go
new file mode 100644
index 0000000..3a49c63
--- /dev/null
+++ b/internal/db/db.go
@@ -0,0 +1 @@
+package db
diff --git a/internal/handlers.go b/internal/handlers.go
new file mode 100644
index 0000000..5bf0569
--- /dev/null
+++ b/internal/handlers.go
@@ -0,0 +1 @@
+package internal
diff --git a/internal/models.go b/internal/models.go
new file mode 100644
index 0000000..5bf0569
--- /dev/null
+++ b/internal/models.go
@@ -0,0 +1 @@
+package internal
diff --git a/web/static/index.css b/web/static/index.css
new file mode 100644
index 0000000..af8aca2
--- /dev/null
+++ b/web/static/index.css
@@ -0,0 +1,16 @@
+body {
+ background: #EEF2FF;
+}
+
+#boardList {
+ font-size: 12px;
+}
+
+#boardList a {
+ cursor: pointer;
+ color: #575F68;
+}
+
+#boardList a:hover {
+ color: #ff0000;
+}
diff --git a/web/views/boards/comfy.templ b/web/views/boards/comfy.templ
new file mode 100644
index 0000000..19db58e
--- /dev/null
+++ b/web/views/boards/comfy.templ
@@ -0,0 +1,11 @@
+package boards
+
+import "github.com/dominicf2001/comfychan/web/views/shared"
+
+templ Comfy() {
+@shared.Layout() {
+
+}
+}
diff --git a/web/views/boards/comfy_templ.go b/web/views/boards/comfy_templ.go
new file mode 100644
index 0000000..3b99cf4
--- /dev/null
+++ b/web/views/boards/comfy_templ.go
@@ -0,0 +1,60 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.857
+package boards
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import "github.com/dominicf2001/comfychan/web/views/shared"
+
+func Comfy() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ 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 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+ templ_7745c5c3_Err = shared.Layout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/web/views/index.templ b/web/views/index.templ
new file mode 100644
index 0000000..47d680a
--- /dev/null
+++ b/web/views/index.templ
@@ -0,0 +1,11 @@
+package views
+
+import "github.com/dominicf2001/comfychan/web/views/shared"
+
+templ Index() {
+ @shared.Layout() {
+
+ }
+}
diff --git a/web/views/index_templ.go b/web/views/index_templ.go
new file mode 100644
index 0000000..bb3b0f6
--- /dev/null
+++ b/web/views/index_templ.go
@@ -0,0 +1,60 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.857
+package views
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import "github.com/dominicf2001/comfychan/web/views/shared"
+
+func Index() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ 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 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+ templ_7745c5c3_Err = shared.Layout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/web/views/shared/layout.templ b/web/views/shared/layout.templ
new file mode 100644
index 0000000..2eb5705
--- /dev/null
+++ b/web/views/shared/layout.templ
@@ -0,0 +1,32 @@
+package shared
+
+templ Layout() {
+
+
+
+
+
+ Comfychan
+
+
+
+
+
+ { children... }
+
+
+
+}
diff --git a/web/views/shared/layout_templ.go b/web/views/shared/layout_templ.go
new file mode 100644
index 0000000..4aba5ee
--- /dev/null
+++ b/web/views/shared/layout_templ.go
@@ -0,0 +1,48 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.857
+package shared
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+func Layout() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ 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 = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "Comfychan")
+ 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 = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate