diff --git a/.gitignore b/.gitignore
index f176ba4..b65df1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,9 @@ node_modules
/tmp
/tmp/*
/build
+
.env
.env.*
!.env.example
+
+/web/**/*_templ.go
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..b2e91bc
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,54 @@
+# Stage 1: Build frontend assets
+FROM node:24-alpine AS frontend-builder
+WORKDIR /app
+
+# Enable pnpm via corepack
+RUN corepack enable pnpm
+
+# Install dependencies
+COPY package.json pnpm-lock.yaml ./
+RUN pnpm install --frozen-lockfile
+
+# Copy source and build assets
+COPY . .
+RUN pnpm run build:css && pnpm run build:js
+
+# Stage 2: Build Go binary
+FROM golang:1.26-alpine AS go-builder
+WORKDIR /app
+
+# Install git for potential private modules (though not strictly needed here)
+RUN apk add --no-cache git
+
+# Download Go modules
+COPY go.mod go.sum ./
+RUN go mod download
+
+# Copy source code
+COPY . .
+
+# Copy built frontend assets from the previous stage
+COPY --from=frontend-builder /app/web/static/css/output.css ./web/static/css/
+COPY --from=frontend-builder /app/web/static/js/htmx.min.js ./web/static/js/
+
+# Generate templ files using the tool defined in go.mod
+RUN go tool templ generate
+
+# Build the optimized binary
+RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server ./cmd/schreifuchs-ch
+
+# Stage 3: Final minimal image
+FROM alpine:latest
+WORKDIR /app
+
+# Install root certificates and timezone data
+RUN apk --no-cache add ca-certificates tzdata
+
+# Copy the compiled binary from the builder stage
+COPY --from=go-builder /app/server .
+
+# Expose the application port
+EXPOSE 8080
+
+# Set the entrypoint
+ENTRYPOINT ["/app/server"]
diff --git a/package.json b/package.json
index 065a776..8d62f79 100644
--- a/package.json
+++ b/package.json
@@ -1,41 +1,4 @@
{
-<<<<<<< HEAD
- "name": "schreifuchs",
- "version": "0.0.1",
- "private": true,
- "scripts": {
- "dev": "vite dev",
- "build": "vite build",
- "preview": "vite preview",
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
- },
- "devDependencies": {
- "@sveltejs/adapter-auto": "^3.0.0",
- "@sveltejs/adapter-node": "^5.5.1",
- "@sveltejs/kit": "^2.5.27",
- "@sveltejs/vite-plugin-svelte": "^4.0.0",
- "@types/mime-types": "^3.0.1",
- "@types/node": "^25.0.9",
- "autoprefixer": "^10.4.19",
- "postcss": "^8.4.38",
- "svelte": "^5.0.0",
- "svelte-check": "^4.0.0",
- "tailwindcss": "^3.4.3",
- "typescript": "^5.5.0",
- "vite": "^5.4.4"
- },
- "type": "module",
- "dependencies": {
- "@fontsource/outfit": "^5.0.13",
- "@inlang/paraglide-js": "^1.11.0",
- "@inlang/paraglide-sveltekit": "^0.16.1",
- "@ts-stack/markdown": "^1.5.0",
- "lru-cache": "^11.2.4",
- "mime-types": "^3.0.2",
- "svelte-preprocess": "^6.0.2",
- "webdav": "^5.8.0"
-=======
"name": "schreifuchs.ch",
"version": "1.0.0",
"description": "",
@@ -58,6 +21,5 @@
},
"dependencies": {
"htmx.org": "^2.0.8"
->>>>>>> cbc2a1a (feat: translation middleware)
}
}
diff --git a/web/components/hello_templ.go b/web/components/hello_templ.go
deleted file mode 100644
index 165fd99..0000000
--- a/web/components/hello_templ.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.977
-package components
-
-//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 Hello() 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, "
Hello World
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/web/components/imagetile_templ.go b/web/components/imagetile_templ.go
deleted file mode 100644
index 917ba23..0000000
--- a/web/components/imagetile_templ.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.977
-package components
-
-//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 "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/images"
-
-func ImageTile(src string) 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, ")
")
- 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, 4, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/web/layouts/base_templ.go b/web/layouts/base_templ.go
deleted file mode 100644
index 1a40fd5..0000000
--- a/web/layouts/base_templ.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.977
-package layouts
-
-//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 "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/translate"
-import "strings"
-import "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/templer"
-
-func Base(title string) 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, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `layouts/base.templ`, Line: 13, Col: 17}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "schreifuchs.ch")
- 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, 10, "")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate
diff --git a/web/pages/index.templ b/web/pages/index.templ
index 50ec709..734bb0d 100644
--- a/web/pages/index.templ
+++ b/web/pages/index.templ
@@ -2,13 +2,14 @@ package pages
import (
"git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/page"
+ "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/translate"
"git.schreifuchs.ch/schreifuchs/schreifuchs.ch/web/components"
)
templ Home(pages []page.PageHeader) {
for _, page := range pages {
@components.ImageTile("/images/" + page.CoverImageUID) {
-
+
diff --git a/web/pages/index_templ.go b/web/pages/index_templ.go
deleted file mode 100644
index 36b6e1d..0000000
--- a/web/pages/index_templ.go
+++ /dev/null
@@ -1,91 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.977
-package pages
-
-//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 (
- "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/page"
- "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/web/components"
-)
-
-func Home(pages []page.PageHeader) 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)
- for _, page := range pages {
- 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
- }
- var templ_7745c5c3_Var4 string
- templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(page.Title)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `pages/index.templ`, Line: 15, Col: 17}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
- templ_7745c5c3_Err = components.ImageTile("/images/"+page.CoverImageUID).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/pages/page_templ.go b/web/pages/page_templ.go
deleted file mode 100644
index 5152eb0..0000000
--- a/web/pages/page_templ.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Code generated by templ - DO NOT EDIT.
-
-// templ: version: v0.3.977
-package pages
-
-//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 "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/internal/components/page"
-import "git.schreifuchs.ch/schreifuchs/schreifuchs.ch/web/components"
-
-func ContentPage(content page.Page) 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
- }
- var templ_7745c5c3_Var3 string
- templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(content.Title)
- if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `pages/page.templ`, Line: 9, Col: 18}
- }
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
- 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
- })
- templ_7745c5c3_Err = components.ImageTile("/images/"+content.PageHeader.CoverImageUID).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templ.Raw(content.Content).Render(ctx, templ_7745c5c3_Buffer)
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "
")
- if templ_7745c5c3_Err != nil {
- return templ_7745c5c3_Err
- }
- return nil
- })
-}
-
-var _ = templruntime.GeneratedTemplate