Merge pull request '(CI/CD): Workflow and Docker implementation.' (#26) from dev into master
Some checks failed
Deploy application with Docker / build_and_deploy (push) Failing after 1m34s

Reviewed-on: #26
This commit is contained in:
Hayden Hargreaves 2025-07-21 20:23:54 -07:00
commit 13596f7cb6
7 changed files with 267 additions and 184 deletions

28
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,28 @@
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,15 +1,54 @@
# TEMPORARY SOLUTION # Fetch stage
# Need a real way to build tailwind and build the templ files FROM golang:latest AS fetch-stage
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
CMD [ "/app/app" ] USER nonroot:nonroot
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 {
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") 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 {
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") 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 {
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")) jwtSecret := []byte(os.Getenv("JWT_SECRET"))

View File

@ -4,75 +4,89 @@ 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 href={ templ.SafeURL(url) } if strings.ToLower(current)==strings.ToLower(name) { <a
class="text-gray-700 border-b-2 border-blue-500 px-1 cursor-pointer" } else { href={ templ.SafeURL(url) }
class="text-gray-700 border-b-2 hover:border-blue-400 px-1 cursor-pointer border-white duration-150" }> if strings.ToLower(current)==strings.ToLower(name) {
{ name } class="text-gray-700 border-b-2 border-blue-500 px-1 cursor-pointer"
</a> } else {
class="text-gray-700 border-b-2 hover:border-blue-400 px-1 cursor-pointer border-white duration-150"
}
>
{ name }
</a>
} }
templ dropdownLink(name, url string) { templ dropdownLink(name, url string) {
<a class="py-2" href={ templ.SafeURL(url) }> <a class="py-2" href={ templ.SafeURL(url) }>
{ name } { name }
</a> </a>
} }
templ listIcon(current, name, url string) { templ listIcon(current, name, url string) {
<a href={ templ.SafeURL(url) }> <a href={ templ.SafeURL(url) }>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" <svg
if strings.ToLower(current) == strings.ToLower(name) { xmlns="http://www.w3.org/2000/svg"
class="h-4 text-blue-500" viewBox="0 0 576 512"
} else { if strings.ToLower(current)==strings.ToLower(name) {
class="h-4 text-gray-700 hover:text-blue-400 duration-150" class="h-4 text-blue-500"
} } else {
> class="h-4 text-gray-700 hover:text-blue-400 duration-150"
<path 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"> >
</path> <path
</svg> fill="currentColor"
</a> 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>
</svg>
</a>
} }
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> >
<a href={ domain.WEB_HOME }> <div>
<p class="select-none">Potion</p> <a href={ domain.WEB_HOME }>
</a> <p class="select-none">Potion</p>
</div> </a>
<div class="hidden md:flex lg:flex items-center gap-8 select-none"> </div>
@navLink(current, "Home", domain.WEB_HOME) <div class="hidden md:flex lg:flex items-center gap-8 select-none">
@navLink(current, "Favorites", domain.WEB_FAVORITES) @navLink(current, "Home", domain.WEB_HOME)
@navLink(current, "Create", domain.WEB_CREATE) @navLink(current, "Favorites", domain.WEB_FAVORITES)
@navLink(current, "Profile", domain.WEB_PROFIlE) @navLink(current, "Create", domain.WEB_CREATE)
@listIcon(current, "List", domain.WEB_LIST) @navLink(current, "Profile", domain.WEB_PROFIlE)
</div> @listIcon(current, "List", domain.WEB_LIST)
<div class="md:hidden grid place-content-center"> </div>
<button onclick="toggleMenu()" class="p-2"> <div class="md:hidden grid place-content-center">
// carot <button onclick="toggleMenu()" class="p-2">
<svg id="mobile-menu-button-carot" class="hidden size-5" xmlns="http://www.w3.org/2000/svg" // carot
viewBox="0 0 320 512"> <svg
<path id="mobile-menu-button-carot"
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"> class="hidden size-5"
</path> xmlns="http://www.w3.org/2000/svg"
</svg> viewBox="0 0 320 512"
// bars >
<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" 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="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> // bars
</button> <svg id="mobile-menu-button-bars" class="size-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
</div> <path
@hamburgerMenu() fill="currentColor"
</div> 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"
</nav> ></path>
</svg>
</button>
</div>
@hamburgerMenu()
</div>
</nav>
} }
templ hamburgerMenu() { templ hamburgerMenu() {
<script> <script>
function toggleMenu() { function toggleMenu() {
const menu = document.getElementById("mobile-menu-content"); const menu = document.getElementById("mobile-menu-content");
const carotButton = document.getElementById("mobile-menu-button-carot"); const carotButton = document.getElementById("mobile-menu-button-carot");
@ -93,13 +107,14 @@ templ hamburgerMenu() {
} }
} }
</script> </script>
<div id="mobile-menu-content" <div
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"> id="mobile-menu-content"
@dropdownLink("Home", domain.WEB_HOME) 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("Favorites", domain.WEB_FAVORITES) >
@dropdownLink("Create", domain.WEB_CREATE) @dropdownLink("Home", domain.WEB_HOME)
@dropdownLink("Profile", domain.WEB_PROFIlE) @dropdownLink("Favorites", domain.WEB_FAVORITES)
@dropdownLink("Shopping List", domain.WEB_LIST) @dropdownLink("Create", domain.WEB_CREATE)
</div> @dropdownLink("Profile", domain.WEB_PROFIlE)
@dropdownLink("Shopping List", domain.WEB_LIST)
</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: 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)) _, 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: 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)) _, 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\">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 text-red-800\">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

@ -5,118 +5,124 @@ import "github.com/haydenhargreaves/Potion/internal/domain/server"
import domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe" import domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe"
templ introSection() { templ introSection() {
<section class="w-full h-fit mb-16"> <section class="w-full h-fit mb-16">
<div class="relative"> <div class="relative">
<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 class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center <h1
text-white text-3xl w-4/5 font-bold z-10"> class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center
Discover Your Next Favorite Meal text-white text-3xl w-4/5 font-bold z-10"
</h1> >
</div> Discover Your Next Favorite Meal
<p class="leading-relaxed p-4 my-8"> </h1>
Welcome to your ultimate recipe hub! Whether you're a seasoned chef or just starting your culinary adventure, </div>
we're here to inspire. Explore thousands of delicious recipes, from quick weeknight dinners to gourmet delights, <p class="leading-relaxed p-4 my-8">
all at your fingertips. Find exactly what you're craving with our powerful search and intuitive filters, or Welcome to your ultimate recipe hub! Whether you're a seasoned chef or just starting your culinary adventure,
browse our trending dishes for fresh ideas. we're here to inspire. Explore thousands of delicious recipes, from quick weeknight dinners to gourmet delights,
</p> all at your fingertips. Find exactly what you're craving with our powerful search and intuitive filters, or
</section> browse our trending dishes for fresh ideas.
</p>
</section>
} }
templ searchSection() { templ searchSection() {
<section class="w-full flex flex-col items-center justify-center my-8 py-4"> <section class="w-full flex flex-col items-center justify-center my-8 py-4">
@components.BannerText("Craving Something Specific?") @components.BannerText("Craving Something Specific?")
<div class="w-full md:w-3/4"> <div class="w-full md:w-3/4">
@components.SearchBar(domainRecipe.SearchFilters{}, true, false, false) @components.SearchBar(domainRecipe.SearchFilters{}, true, false, false)
</div> </div>
<div class="hidden" id="result-list"></div> <div class="hidden" id="result-list"></div>
</section> </section>
} }
templ highlightSection(liked bool) { templ highlightSection(liked bool) {
<section class="w-full flex flex-col items-center justify-center my-8 py-4"> <section class="w-full flex flex-col items-center justify-center my-8 py-4">
@components.BannerText("Recipe of the Week!") @components.BannerText("Recipe of the Week!")
<p class="leading-relaxed p-4 my-8"> <p class="leading-relaxed p-4 my-8">
Our 'Recipe of the Week' is the cream of the crop! We handpick it by looking at what recipes 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 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 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 the true fan favorite of the week. It's our way of highlighting the best recipes that truly
resonate with our users! resonate with our users!
</p> </p>
<div class="flex items-center justify-center w-full"> <div class="flex items-center justify-center w-full">
@components.RecipeCardLarge(false) @components.RecipeCardLarge(false)
</div> </div>
</section> </section>
} }
templ listsSection(loggedIn bool, viewed, made []domainRecipe.Recipe) { templ listsSection(loggedIn bool, viewed, made []domainRecipe.Recipe) {
<section class="w-full flex flex-col items-center justify-center my-8 py-4"> <section class="w-full flex flex-col items-center justify-center my-8 py-4">
@components.BannerText("Take Another Look.") @components.BannerText("Take Another Look.")
<div class="w-full"> <div class="w-full">
<h3 class="text-lg mt-8 mx-4">Recently viewed</h3> <h3 class="text-lg mt-8 mx-4">Recently viewed</h3>
if loggedIn { if loggedIn {
<div class="flex overflow-x-auto gap-x-4 mx-4 my-4"> <div class="flex overflow-x-auto gap-x-4 mx-4 my-4">
for _, recipe := range viewed { for _, recipe := range viewed {
@components.RecipeCardSmall(recipe) @components.RecipeCardSmall(recipe)
} }
@components.ContentCardSmall("View full history...", "/v1/web/history") @components.ContentCardSmall("View full history...", "/v1/web/history")
</div> </div>
} else { } else {
<div class="my-2 mx-4 text-gray-800"> <div class="my-2 mx-4 text-gray-800">
<a class="underline" href={ domain.WEB_LOGIN }> <a class="underline" href={ domain.WEB_LOGIN }>
<p class="text-sm">Log in to view metrics.</p> <p class="text-sm">Log in to view metrics.</p>
</a> </a>
</div> </div>
} }
<h3 class="text-lg mt-8 mx-4">Make again</h3> <h3 class="text-lg mt-8 mx-4">Make again</h3>
if loggedIn { if loggedIn {
<div class="flex overflow-x-auto gap-x-4 mx-4 my-4"> <div class="flex overflow-x-auto gap-x-4 mx-4 my-4">
for _, recipe := range made { for _, recipe := range made {
@components.RecipeCardSmall(recipe) @components.RecipeCardSmall(recipe)
} }
@components.ContentCardSmall("View full history...", "/v1/web/history") @components.ContentCardSmall("View full history...", "/v1/web/history")
</div> </div>
} else { } else {
<div class="my-2 mx-4 text-gray-800"> <div class="my-2 mx-4 text-gray-800">
<a class="underline" href={ domain.WEB_LOGIN }> <a class="underline" href={ domain.WEB_LOGIN }>
<p class="text-sm">Log in to view metrics.</p> <p class="text-sm">Log in to view metrics.</p>
</a> </a>
</div> </div>
} }
</div> </div>
</section> </section>
} }
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"> >
Unleash Your Inner Chef! <h2 class="text-2xl md:text-3xl font-extrabold text-gray-800 mb-6 px-4">
</h2> Unleash Your Inner Chef!
<p class="text-md md:text-lg text-gray-700 max-w-2xl mb-10 px-4 leading-relaxed"> </h2>
Have a unique recipe idea? Want to share your culinary masterpiece with the world? <p class="text-md md:text-lg text-gray-700 max-w-2xl mb-10 px-4 leading-relaxed">
It's time to bring your creations to life! Have a unique recipe idea? Want to share your culinary masterpiece with the world?
</p> It's time to bring your creations to life!
<a href={ domain.WEB_CREATE } class="flex items-center justify-center </p>
<a
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! >
</a> Create Your Recipe!
</section> </a>
</section>
} }
templ HomePage(loggedIn bool, viewed, made []domainRecipe.Recipe) { templ HomePage(loggedIn bool, viewed, made []domainRecipe.Recipe) {
@components.Navbar("home") @components.Navbar("home")
<div class="w-full h-fit flex justify-center"> <div class="w-full h-fit flex justify-center">
<div class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 h-full border-l border-r border-gray-300 bg-white"> <div class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 h-full border-l border-r border-gray-300 bg-white">
@introSection() @introSection()
@searchSection() @searchSection()
@highlightSection(false) @highlightSection(false)
@listsSection(loggedIn, viewed, made) @listsSection(loggedIn, viewed, made)
@ctaSection() @ctaSection()
</div> </div>
</div> </div>
} }

View File

@ -9,6 +9,7 @@
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);
@ -259,18 +260,12 @@
.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;
} }
@ -662,9 +657,6 @@
.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);
} }
@ -881,6 +873,9 @@
.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);
} }