diff --git a/Dockerfile b/Dockerfile index aba010d..a018fdb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,54 @@ -# TEMPORARY SOLUTION -# Need a real way to build tailwind and build the templ files -FROM golang:1.24 +# Fetch stage +FROM golang:latest AS fetch-stage + +COPY go.mod go.sum /app WORKDIR /app -COPY . . - RUN go mod download -RUN CGO_ENABLED=0 GOOS=linux go build -o /app/app /app/cmd/web/main.go + +# Generate stage +FROM ghcr.io/a-h/templ:latest AS generate-stage + +COPY --chown=65532:65532 . /app + +WORKDIR /app + +RUN ["templ", "generate"] + +# Generate stage two + +FROM node:lts-alpine AS tailwind-build-stage + +COPY --from=generate-stage /app /app + +WORKDIR /app + +RUN npm install tailwindcss @tailwindcss/cli && npx @tailwindcss/cli -i ./web/static/css/main.css -o ./web/static/css/tailwind.css --minify -c ./tailwind.config.js + + +# Build stage +FROM golang:1.24 AS build-stage + +COPY --from=tailwind-build-stage /app /app + +WORKDIR /app + +RUN CGO_ENABLED=0 GOOS=linux go build -o /entrypoint /app/cmd/web/main.go + +# Deploy. +FROM gcr.io/distroless/static-debian11 AS release-stage + +WORKDIR / + +COPY --from=build-stage /entrypoint /entrypoint + +COPY --from=build-stage /app/web/static /web/static + EXPOSE 3000 -CMD [ "/app/app" ] +USER nonroot:nonroot + +ENTRYPOINT ["/entrypoint"] diff --git a/internal/app/server/server.go b/internal/app/server/server.go index 0084d93..9863e17 100644 --- a/internal/app/server/server.go +++ b/internal/app/server/server.go @@ -56,7 +56,7 @@ func Init(port int) *Server { func (s *Server) ConfigureAuth() *Server { err := godotenv.Load(".env") if err != nil { - panic("Could not load env file") + fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err) } redirect_domain := os.Getenv("DOMAIN") @@ -80,7 +80,7 @@ func (s *Server) ConfigureAuth() *Server { func (s *Server) ConnectDatabase() *Server { err := godotenv.Load(".env") if err != nil { - panic("Could not load env file") + fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err) } var connUrl string = os.Getenv("DATABASE_URL") @@ -107,7 +107,7 @@ func (s *Server) Start() { func (s *Server) Setup() *Server { err := godotenv.Load(".env") if err != nil { - panic("Could not load env file") + fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err) } jwtSecret := []byte(os.Getenv("JWT_SECRET")) diff --git a/internal/templates/components/navbar.templ b/internal/templates/components/navbar.templ index 2132139..63daaa7 100644 --- a/internal/templates/components/navbar.templ +++ b/internal/templates/components/navbar.templ @@ -4,75 +4,89 @@ import "strings" import "github.com/haydenhargreaves/Potion/internal/domain/server" templ navLink(current, name, url string) { - - { name } - + + { name } + } templ dropdownLink(name, url string) { - - { name } - + + { name } + } templ listIcon(current, name, url string) { - - - - - - + + + + + } templ Navbar(current string) { - + } templ hamburgerMenu() { - - + } - diff --git a/internal/templates/components/navbar_templ.go b/internal/templates/components/navbar_templ.go index 84bc6ac..0ae98db 100644 --- a/internal/templates/components/navbar_templ.go +++ b/internal/templates/components/navbar_templ.go @@ -63,7 +63,7 @@ func navLink(current, name, url string) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 10, Col: 8} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 15, Col: 8} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -114,7 +114,7 @@ func dropdownLink(name, url string) templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 16, Col: 8} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 21, Col: 8} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -211,7 +211,7 @@ func Navbar(current string) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">

Potion

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">

Potion

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/internal/templates/pages/home.templ b/internal/templates/pages/home.templ index afc26a8..657caf9 100644 --- a/internal/templates/pages/home.templ +++ b/internal/templates/pages/home.templ @@ -5,118 +5,124 @@ import "github.com/haydenhargreaves/Potion/internal/domain/server" import domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe" templ introSection() { -
-
- -

- Discover Your Next Favorite Meal -

-
-

- Welcome to your ultimate recipe hub! Whether you're a seasoned chef or just starting your culinary adventure, - we're here to inspire. Explore thousands of delicious recipes, from quick weeknight dinners to gourmet delights, - all at your fingertips. Find exactly what you're craving with our powerful search and intuitive filters, or - browse our trending dishes for fresh ideas. -

-
+
+
+ +

+ Discover Your Next Favorite Meal +

+
+

+ Welcome to your ultimate recipe hub! Whether you're a seasoned chef or just starting your culinary adventure, + we're here to inspire. Explore thousands of delicious recipes, from quick weeknight dinners to gourmet delights, + all at your fingertips. Find exactly what you're craving with our powerful search and intuitive filters, or + browse our trending dishes for fresh ideas. +

+
} templ searchSection() { -
- @components.BannerText("Craving Something Specific?") -
- @components.SearchBar(domainRecipe.SearchFilters{}, true, false, false) -
- -
+
+ @components.BannerText("Craving Something Specific?") +
+ @components.SearchBar(domainRecipe.SearchFilters{}, true, false, false) +
+ +
} templ highlightSection(liked bool) { -
- @components.BannerText("Recipe of the Week!") -

- Our 'Recipe of the Week' is the cream of the crop! We handpick it by looking at what recipes - our community loves most. This isn't just about how many people view a recipe; it's also about - how many times it's been made, liked, reviewed, and its average rating, all combined to find - the true fan favorite of the week. It's our way of highlighting the best recipes that truly - resonate with our users! -

-
- @components.RecipeCardLarge(false) -
-
+
+ @components.BannerText("Recipe of the Week!") +

+ Our 'Recipe of the Week' is the cream of the crop! We handpick it by looking at what recipes + our community loves most. This isn't just about how many people view a recipe; it's also about + how many times it's been made, liked, reviewed, and its average rating, all combined to find + the true fan favorite of the week. It's our way of highlighting the best recipes that truly + resonate with our users! +

+
+ @components.RecipeCardLarge(false) +
+
} templ listsSection(loggedIn bool, viewed, made []domainRecipe.Recipe) { -
- @components.BannerText("Take Another Look.") -
-

Recently viewed

- if loggedIn { -
- for _, recipe := range viewed { - @components.RecipeCardSmall(recipe) - } - @components.ContentCardSmall("View full history...", "/v1/web/history") -
- } else { - - } -

Make again

- if loggedIn { -
- for _, recipe := range made { - @components.RecipeCardSmall(recipe) - } - @components.ContentCardSmall("View full history...", "/v1/web/history") -
- } else { - - } -
-
+
+ @components.BannerText("Take Another Look.") +
+

Recently viewed

+ if loggedIn { +
+ for _, recipe := range viewed { + @components.RecipeCardSmall(recipe) + } + @components.ContentCardSmall("View full history...", "/v1/web/history") +
+ } else { + + } +

Make again

+ if loggedIn { +
+ for _, recipe := range made { + @components.RecipeCardSmall(recipe) + } + @components.ContentCardSmall("View full history...", "/v1/web/history") +
+ } else { + + } +
+
} templ ctaSection() { -
-

- Unleash Your Inner Chef! -

-

- Have a unique recipe idea? Want to share your culinary masterpiece with the world? - It's time to bring your creations to life! -

- +

+ Unleash Your Inner Chef! +

+

+ Have a unique recipe idea? Want to share your culinary masterpiece with the world? + It's time to bring your creations to life! +

+
- Create Your Recipe! - -
+ text-lg md:text-2xl font-bold uppercase tracking-wide" + > + Create Your Recipe! + + } templ HomePage(loggedIn bool, viewed, made []domainRecipe.Recipe) { -@components.Navbar("home") -
-
- @introSection() - @searchSection() - @highlightSection(false) - @listsSection(loggedIn, viewed, made) - @ctaSection() -
-
+ @components.Navbar("home") +
+
+ @introSection() + @searchSection() + @highlightSection(false) + @listsSection(loggedIn, viewed, made) + @ctaSection() +
+
} diff --git a/web/static/css/tailwind.css b/web/static/css/tailwind.css index 035fbd3..a1d4d52 100644 --- a/web/static/css/tailwind.css +++ b/web/static/css/tailwind.css @@ -9,6 +9,7 @@ monospace; --color-red-100: oklch(93.6% 0.032 17.717); --color-red-500: oklch(63.7% 0.237 25.331); + --color-red-800: oklch(44.4% 0.177 26.899); --color-green-500: oklch(72.3% 0.219 149.579); --color-blue-50: oklch(97% 0.014 254.604); --color-blue-100: oklch(93.2% 0.032 255.585); @@ -259,18 +260,12 @@ .z-20 { z-index: 20; } - .m-4 { - margin: calc(var(--spacing) * 4); - } .mx-2 { margin-inline: calc(var(--spacing) * 2); } .mx-4 { margin-inline: calc(var(--spacing) * 4); } - .mx-8 { - margin-inline: calc(var(--spacing) * 8); - } .mx-auto { margin-inline: auto; } @@ -662,9 +657,6 @@ .bg-red-100 { background-color: var(--color-red-100); } - .bg-red-500 { - background-color: var(--color-red-500); - } .bg-white { background-color: var(--color-white); } @@ -881,6 +873,9 @@ .text-red-500 { color: var(--color-red-500); } + .text-red-800 { + color: var(--color-red-800); + } .text-white { color: var(--color-white); }