Compare commits

..

No commits in common. "0017d1a3d58c7b0ff7e0a5903a641f5889e026b4" and "52ccf472f34b5765c3f83fef1bca20132b96ee4e" have entirely different histories.

7 changed files with 184 additions and 267 deletions

View File

@ -1,28 +0,0 @@
name: Deploy application with Docker
on:
push:
branches:
- master
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: azpect3120/option.gophernest:latest

View File

@ -1,54 +1,15 @@
# Fetch stage # TEMPORARY SOLUTION
FROM golang:latest AS fetch-stage # Need a real way to build tailwind and build the templ files
FROM golang:1.24
COPY go.mod go.sum /app
WORKDIR /app WORKDIR /app
COPY . .
RUN go mod download 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 EXPOSE 3000
USER nonroot:nonroot CMD [ "/app/app" ]
ENTRYPOINT ["/entrypoint"]

View File

@ -56,7 +56,7 @@ func Init(port int) *Server {
func (s *Server) ConfigureAuth() *Server { func (s *Server) ConfigureAuth() *Server {
err := godotenv.Load(".env") err := godotenv.Load(".env")
if err != nil { if err != nil {
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err) panic("Could not load env file")
} }
redirect_domain := os.Getenv("DOMAIN") redirect_domain := os.Getenv("DOMAIN")
@ -80,7 +80,7 @@ func (s *Server) ConfigureAuth() *Server {
func (s *Server) ConnectDatabase() *Server { func (s *Server) ConnectDatabase() *Server {
err := godotenv.Load(".env") err := godotenv.Load(".env")
if err != nil { if err != nil {
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err) panic("Could not load env file")
} }
var connUrl string = os.Getenv("DATABASE_URL") var connUrl string = os.Getenv("DATABASE_URL")
@ -107,7 +107,7 @@ func (s *Server) Start() {
func (s *Server) Setup() *Server { func (s *Server) Setup() *Server {
err := godotenv.Load(".env") err := godotenv.Load(".env")
if err != nil { if err != nil {
fmt.Printf("No .env file found or error loading .env: %v. Relying on system environment variables.", err) panic("Could not load env file")
} }
jwtSecret := []byte(os.Getenv("JWT_SECRET")) jwtSecret := []byte(os.Getenv("JWT_SECRET"))

View File

@ -4,14 +4,9 @@ import "strings"
import "github.com/haydenhargreaves/Potion/internal/domain/server" import "github.com/haydenhargreaves/Potion/internal/domain/server"
templ navLink(current, name, url string) { templ navLink(current, name, url string) {
<a <a href={ templ.SafeURL(url) } if strings.ToLower(current)==strings.ToLower(name) {
href={ templ.SafeURL(url) } class="text-gray-700 border-b-2 border-blue-500 px-1 cursor-pointer" } else {
if strings.ToLower(current)==strings.ToLower(name) { class="text-gray-700 border-b-2 hover:border-blue-400 px-1 cursor-pointer border-white duration-150" }>
class="text-gray-700 border-b-2 border-blue-500 px-1 cursor-pointer"
} else {
class="text-gray-700 border-b-2 hover:border-blue-400 px-1 cursor-pointer border-white duration-150"
}
>
{ name } { name }
</a> </a>
} }
@ -24,19 +19,16 @@ templ dropdownLink(name, url string) {
templ listIcon(current, name, url string) { templ listIcon(current, name, url string) {
<a href={ templ.SafeURL(url) }> <a href={ templ.SafeURL(url) }>
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512"
if strings.ToLower(current) == strings.ToLower(name) { if strings.ToLower(current) == strings.ToLower(name) {
class="h-4 text-blue-500" class="h-4 text-blue-500"
} else { } else {
class="h-4 text-gray-700 hover:text-blue-400 duration-150" class="h-4 text-gray-700 hover:text-blue-400 duration-150"
} }
> >
<path <path fill="currentColor"
fill="currentColor" d="M0 24C0 10.7 10.7 0 24 0L69.5 0c22 0 41.5 12.8 50.6 32l411 0c26.3 0 45.5 25 38.6 50.4l-41 152.3c-8.5 31.4-37 53.3-69.5 53.3l-288.5 0 5.4 28.5c2.2 11.3 12.1 19.5 23.6 19.5L488 336c13.3 0 24 10.7 24 24s-10.7 24-24 24l-288.3 0c-34.6 0-64.3-24.6-70.7-58.5L77.4 54.5c-.7-3.8-4-6.5-7.9-6.5L24 48C10.7 48 0 37.3 0 24zM128 464a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm336-48a48 48 0 1 1 0 96 48 48 0 1 1 0-96z">
d="M0 24C0 10.7 10.7 0 24 0L69.5 0c22 0 41.5 12.8 50.6 32l411 0c26.3 0 45.5 25 38.6 50.4l-41 152.3c-8.5 31.4-37 53.3-69.5 53.3l-288.5 0 5.4 28.5c2.2 11.3 12.1 19.5 23.6 19.5L488 336c13.3 0 24 10.7 24 24s-10.7 24-24 24l-288.3 0c-34.6 0-64.3-24.6-70.7-58.5L77.4 54.5c-.7-3.8-4-6.5-7.9-6.5L24 48C10.7 48 0 37.3 0 24zM128 464a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm336-48a48 48 0 1 1 0 96 48 48 0 1 1 0-96z" </path>
></path>
</svg> </svg>
</a> </a>
} }
@ -44,8 +36,7 @@ templ listIcon(current, name, url string) {
templ Navbar(current string) { templ Navbar(current string) {
<nav class="block md:fixed w-full z-10"> <nav class="block md:fixed w-full z-10">
<div <div
class="relative w-full px-8 md:px-44 p-4 border-b border-gray-300 shadow-sm shadow-gray-300 bg-white flex justify-between items-center" class="relative w-full px-8 md:px-44 p-4 border-b border-gray-300 shadow-sm shadow-gray-300 bg-white flex justify-between items-center">
>
<div> <div>
<a href={ domain.WEB_HOME }> <a href={ domain.WEB_HOME }>
<p class="select-none">Potion</p> <p class="select-none">Potion</p>
@ -61,22 +52,17 @@ templ Navbar(current string) {
<div class="md:hidden grid place-content-center"> <div class="md:hidden grid place-content-center">
<button onclick="toggleMenu()" class="p-2"> <button onclick="toggleMenu()" class="p-2">
// carot // carot
<svg <svg id="mobile-menu-button-carot" class="hidden size-5" xmlns="http://www.w3.org/2000/svg"
id="mobile-menu-button-carot" viewBox="0 0 320 512">
class="hidden size-5"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512"
>
<path <path
d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8l256 0c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z" d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8l256 0c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z">
></path> </path>
</svg> </svg>
// bars // bars
<svg id="mobile-menu-button-bars" class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"> <svg id="mobile-menu-button-bars" class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path <path fill="currentColor"
fill="currentColor" d="M0 96C0 78.3 14.3 64 32 64l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 128C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32L32 448c-17.7 0-32-14.3-32-32s14.3-32 32-32l384 0c17.7 0 32 14.3 32 32z">
d="M0 96C0 78.3 14.3 64 32 64l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 128C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32L32 448c-17.7 0-32-14.3-32-32s14.3-32 32-32l384 0c17.7 0 32 14.3 32 32z" </path>
></path>
</svg> </svg>
</button> </button>
</div> </div>
@ -107,10 +93,8 @@ templ hamburgerMenu() {
} }
} }
</script> </script>
<div <div id="mobile-menu-content"
id="mobile-menu-content" class="hidden w-full flex-col items-center absolute top-[100%] left-0 py-2 bg-white border-b border-gray-300 shadow-sm shadow-gray-300 z-20">
class="hidden w-full flex-col items-center absolute top-[100%] left-0 py-2 bg-white border-b border-gray-300 shadow-sm shadow-gray-300 z-20"
>
@dropdownLink("Home", domain.WEB_HOME) @dropdownLink("Home", domain.WEB_HOME)
@dropdownLink("Favorites", domain.WEB_FAVORITES) @dropdownLink("Favorites", domain.WEB_FAVORITES)
@dropdownLink("Create", domain.WEB_CREATE) @dropdownLink("Create", domain.WEB_CREATE)
@ -118,3 +102,4 @@ templ hamburgerMenu() {
@dropdownLink("Shopping List", domain.WEB_LIST) @dropdownLink("Shopping List", domain.WEB_LIST)
</div> </div>
} }

View File

@ -63,7 +63,7 @@ func navLink(current, name, url string) templ.Component {
var templ_7745c5c3_Var3 string var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(name) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 15, Col: 8} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 10, Col: 8}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -114,7 +114,7 @@ func dropdownLink(name, url string) templ.Component {
var templ_7745c5c3_Var6 string var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(name) templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 21, Col: 8} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/components/navbar.templ`, Line: 16, Col: 8}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -211,7 +211,7 @@ func Navbar(current string) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"><p class=\"select-none text-red-800\">Potion</p></a></div><div class=\"hidden md:flex lg:flex items-center gap-8 select-none\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\"><p class=\"select-none\">Potion</p></a></div><div class=\"hidden md:flex lg:flex items-center gap-8 select-none\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -10,10 +10,8 @@ templ introSection() {
<video class="" autoplay loop muted playsinline> <video class="" autoplay loop muted playsinline>
<source src="/v1/web/static/img/salmon_video.mp4" type="video/mp4" /> <source src="/v1/web/static/img/salmon_video.mp4" type="video/mp4" />
</video> </video>
<h1 <h1 class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center text-white text-3xl w-4/5 font-bold z-10">
text-white text-3xl w-4/5 font-bold z-10"
>
Discover Your Next Favorite Meal Discover Your Next Favorite Meal
</h1> </h1>
</div> </div>
@ -92,8 +90,7 @@ templ listsSection(loggedIn bool, viewed, made []domainRecipe.Recipe) {
templ ctaSection() { templ ctaSection() {
<section <section
class="w-full flex flex-col items-center justify-center mt-16 py-8 md:py-12 bg-gradient-to-br from-blue-100 to-purple-100 text-center" class="w-full flex flex-col items-center justify-center mt-16 py-8 md:py-12 bg-gradient-to-br from-blue-100 to-purple-100 text-center">
>
<h2 class="text-2xl md:text-3xl font-extrabold text-gray-800 mb-6 px-4"> <h2 class="text-2xl md:text-3xl font-extrabold text-gray-800 mb-6 px-4">
Unleash Your Inner Chef! Unleash Your Inner Chef!
</h2> </h2>
@ -101,14 +98,11 @@ templ ctaSection() {
Have a unique recipe idea? Want to share your culinary masterpiece with the world? Have a unique recipe idea? Want to share your culinary masterpiece with the world?
It's time to bring your creations to life! It's time to bring your creations to life!
</p> </p>
<a <a href={ domain.WEB_CREATE } class="flex items-center justify-center
href={ domain.WEB_CREATE }
class="flex items-center justify-center
bg-gradient-to-r from-blue-400 to-blue-600 text-white bg-gradient-to-r from-blue-400 to-blue-600 text-white
px-12 py-5 rounded-full shadow-sm hover:shadow-md px-12 py-5 rounded-full shadow-sm hover:shadow-md
transition-all duration-300 ease-in-out shadow-blue-700 transition-all duration-300 ease-in-out shadow-blue-700
text-lg md:text-2xl font-bold uppercase tracking-wide" text-lg md:text-2xl font-bold uppercase tracking-wide">
>
Create Your Recipe! Create Your Recipe!
</a> </a>
</section> </section>

View File

@ -9,7 +9,6 @@
monospace; monospace;
--color-red-100: oklch(93.6% 0.032 17.717); --color-red-100: oklch(93.6% 0.032 17.717);
--color-red-500: oklch(63.7% 0.237 25.331); --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-green-500: oklch(72.3% 0.219 149.579);
--color-blue-50: oklch(97% 0.014 254.604); --color-blue-50: oklch(97% 0.014 254.604);
--color-blue-100: oklch(93.2% 0.032 255.585); --color-blue-100: oklch(93.2% 0.032 255.585);
@ -260,12 +259,18 @@
.z-20 { .z-20 {
z-index: 20; z-index: 20;
} }
.m-4 {
margin: calc(var(--spacing) * 4);
}
.mx-2 { .mx-2 {
margin-inline: calc(var(--spacing) * 2); margin-inline: calc(var(--spacing) * 2);
} }
.mx-4 { .mx-4 {
margin-inline: calc(var(--spacing) * 4); margin-inline: calc(var(--spacing) * 4);
} }
.mx-8 {
margin-inline: calc(var(--spacing) * 8);
}
.mx-auto { .mx-auto {
margin-inline: auto; margin-inline: auto;
} }
@ -657,6 +662,9 @@
.bg-red-100 { .bg-red-100 {
background-color: var(--color-red-100); background-color: var(--color-red-100);
} }
.bg-red-500 {
background-color: var(--color-red-500);
}
.bg-white { .bg-white {
background-color: var(--color-white); background-color: var(--color-white);
} }
@ -873,9 +881,6 @@
.text-red-500 { .text-red-500 {
color: var(--color-red-500); color: var(--color-red-500);
} }
.text-red-800 {
color: var(--color-red-800);
}
.text-white { .text-white {
color: var(--color-white); color: var(--color-white);
} }