Initial commit — Bar Pivoine cocktail recipe site
Hugo Extended site with 426 cocktail recipes from the open cocktail dataset. Dark amber/gold editorial aesthetic, Tailwind CSS v4, Alpine.js client-side search and filtering, HTMX page transitions, Docker + nginx production build. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ .Site.LanguageCode }}" class="scroll-smooth">
|
||||
<head>
|
||||
{{- partial "head.html" . -}}
|
||||
</head>
|
||||
<body
|
||||
class="bg-bg text-ink font-sans min-h-screen flex flex-col antialiased"
|
||||
hx-boost="true"
|
||||
hx-select="#main-content"
|
||||
hx-target="#main-content"
|
||||
hx-swap="outerHTML"
|
||||
hx-push-url="true"
|
||||
>
|
||||
<!-- HTMX progress bar -->
|
||||
<div id="progress-bar" aria-hidden="true"></div>
|
||||
|
||||
{{- partial "nav.html" . -}}
|
||||
|
||||
<main id="main-content" class="flex-1" hx-history-elt>
|
||||
{{- block "main" . }}{{- end }}
|
||||
</main>
|
||||
|
||||
{{- partial "footer.html" . -}}
|
||||
|
||||
<!-- HTMX -->
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js"></script>
|
||||
|
||||
<!-- Site JS — must load before Alpine so cocktailSearch() is defined -->
|
||||
{{- $js := resources.Get "js/main.js" -}}
|
||||
{{- if eq hugo.Environment "production" -}}
|
||||
{{- $js = $js | minify | fingerprint "sha256" -}}
|
||||
{{- end -}}
|
||||
<script
|
||||
src="{{ $js.RelPermalink }}"
|
||||
{{ if eq hugo.Environment "production" }}integrity="{{ $js.Data.Integrity }}"{{ end }}
|
||||
defer
|
||||
></script>
|
||||
|
||||
<!-- Alpine.js -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.8/dist/cdn.min.js"></script>
|
||||
|
||||
{{- block "scripts" . }}{{- end }}
|
||||
|
||||
{{- if and (eq hugo.Environment "production") .Site.Params.umamiId -}}
|
||||
<script defer src="{{ .Site.Params.umamiSrc }}" data-website-id="{{ .Site.Params.umamiId }}"></script>
|
||||
{{- end -}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
{{ define "main" }}
|
||||
<div class="bg-bg-deep border-b border-warm/10">
|
||||
<div class="max-w-[1280px] mx-auto px-8 max-[860px]:px-5 py-16">
|
||||
<div class="eyebrow mb-3">Archive</div>
|
||||
<h1 class="display text-[clamp(36px,6vw,72px)] mb-4">{{ .Title }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-[1280px] mx-auto px-8 max-[860px]:px-5 py-16">
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 mb-12">
|
||||
{{- range .Paginator.Pages -}}
|
||||
{{- partial "cocktail-card.html" . -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- if gt .Paginator.TotalPages 1 -}}
|
||||
{{- partial "pagination.html" . -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{ define "main" }}
|
||||
<div class="max-w-[1280px] mx-auto px-8 max-[860px]:px-5 py-20">
|
||||
<h1 class="display text-[clamp(36px,5vw,64px)] mb-8">{{ .Title }}</h1>
|
||||
<div class="prose text-ink-soft leading-relaxed">{{ .Content }}</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,98 @@
|
||||
{{ define "main" }}
|
||||
{{- $taxType := .Type -}}
|
||||
{{- $taxIcon := "❖" -}}
|
||||
{{- if eq $taxType "glasses" -}}{{- $taxIcon = "▽" -}}
|
||||
{{- else if eq $taxType "ingredients" -}}{{- $taxIcon = "✦" -}}
|
||||
{{- else if eq $taxType "categories" -}}{{- $taxIcon = "❖" -}}
|
||||
{{- end -}}
|
||||
{{- $cnt := len .Pages -}}
|
||||
{{- $siblings := slice -}}
|
||||
{{- $allTerms := index .Site.Taxonomies $taxType -}}
|
||||
{{- if $allTerms -}}
|
||||
{{- range $allTerms.ByCount -}}
|
||||
{{- if ne .Page.Title $.Title -}}
|
||||
{{- $siblings = $siblings | append . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
<div class="max-w-[1280px] mx-auto px-8 max-[860px]:px-5 pb-[90px]">
|
||||
|
||||
<!-- Breadcrumbs -->
|
||||
<nav class="flex gap-[11px] items-center font-mono text-[11px] tracking-[0.1em] uppercase text-ink-faint pt-10 pb-8 flex-wrap">
|
||||
<a href="/" class="text-ink-mute hover:text-gold-2 transition-colors duration-[160ms]">Bar Pivoine</a>
|
||||
<span>/</span>
|
||||
<a href="/{{ .Type }}/" class="text-ink-mute hover:text-gold-2 transition-colors duration-[160ms]">{{ .Type | title }}</a>
|
||||
<span>/</span>
|
||||
<span class="text-gold">{{ .Title }}</span>
|
||||
</nav>
|
||||
|
||||
<!-- Tax hero -->
|
||||
<header class="pb-[46px]">
|
||||
<div class="text-gold text-[56px] leading-none mb-4">{{ $taxIcon }}</div>
|
||||
<h1 class="display text-[clamp(44px,6.4vw,80px)]">{{ .Title }}</h1>
|
||||
<p class="text-ink-soft text-[16px] mt-4">{{ $cnt }} {{ if eq $cnt 1 }}recipe{{ else }}recipes{{ end }}</p>
|
||||
</header>
|
||||
|
||||
<!-- Grid -->
|
||||
{{- if .Paginator.Pages -}}
|
||||
<div class="grid [grid-template-columns:repeat(auto-fill,minmax(258px,1fr))] gap-[22px] max-[560px]:[grid-template-columns:repeat(auto-fill,minmax(150px,1fr))] max-[560px]:gap-3.5 mb-12">
|
||||
{{- range .Paginator.Pages -}}
|
||||
{{- partial "cocktail-card.html" . -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
|
||||
<!-- Hugo pagination -->
|
||||
{{- if gt .Paginator.TotalPages 1 -}}
|
||||
<nav class="flex items-center justify-center gap-[6px] pt-14 flex-wrap" aria-label="pages">
|
||||
{{- if .Paginator.HasPrev -}}
|
||||
<a href="{{ .Paginator.Prev.URL }}" class="inline-flex items-center gap-[7px] font-mono text-[12px] tracking-[0.1em] uppercase text-ink-soft bg-transparent border border-warm/10 rounded-full px-5 py-[11px] transition-all duration-[180ms] hover:border-gold hover:text-gold-2">
|
||||
{{- partial "icon.html" "arrow-left" -}} Prev
|
||||
</a>
|
||||
{{- else -}}
|
||||
<span class="inline-flex items-center gap-[7px] font-mono text-[12px] tracking-[0.1em] uppercase text-ink-soft bg-transparent border border-warm/10 rounded-full px-5 py-[11px] opacity-[0.28] cursor-default">
|
||||
{{- partial "icon.html" "arrow-left" -}} Prev
|
||||
</span>
|
||||
{{- end -}}
|
||||
<div class="flex items-center gap-[2px]">
|
||||
{{- range .Paginator.Pagers -}}
|
||||
<a
|
||||
href="{{ .URL }}"
|
||||
class="{{ if eq . $.Paginator }}bg-gold text-[#1a1206] font-semibold pointer-events-none{{ else }}bg-transparent text-ink-mute hover:text-ink hover:bg-warm/[0.07]{{ end }} font-mono text-[13px] w-[38px] h-[38px] rounded-full flex items-center justify-center transition-all duration-[150ms]"
|
||||
{{ if eq . $.Paginator }}aria-current="page"{{ end }}
|
||||
>{{ .PageNumber }}</a>
|
||||
{{- end -}}
|
||||
</div>
|
||||
{{- if .Paginator.HasNext -}}
|
||||
<a href="{{ .Paginator.Next.URL }}" class="inline-flex items-center gap-[7px] font-mono text-[12px] tracking-[0.1em] uppercase text-ink-soft bg-transparent border border-warm/10 rounded-full px-5 py-[11px] transition-all duration-[180ms] hover:border-gold hover:text-gold-2">
|
||||
Next {{- partial "icon.html" "arrow-right" -}}
|
||||
</a>
|
||||
{{- else -}}
|
||||
<span class="inline-flex items-center gap-[7px] font-mono text-[12px] tracking-[0.1em] uppercase text-ink-soft bg-transparent border border-warm/10 rounded-full px-5 py-[11px] opacity-[0.28] cursor-default">
|
||||
Next {{- partial "icon.html" "arrow-right" -}}
|
||||
</span>
|
||||
{{- end -}}
|
||||
</nav>
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
<p class="text-ink-soft text-center py-24">No recipes found.</p>
|
||||
{{- end -}}
|
||||
|
||||
<!-- More in this taxonomy -->
|
||||
{{- if gt (len $siblings) 0 -}}
|
||||
<div class="mt-16 pt-[34px] border-t border-warm/10">
|
||||
<h4 class="font-mono text-[11px] tracking-[0.2em] uppercase text-gold mb-[18px] pb-3 border-b border-warm/10">More {{ .Type }}</h4>
|
||||
<div class="flex flex-wrap gap-2.5 mt-3">
|
||||
{{- range first 12 $siblings -}}
|
||||
<a href="{{ .Page.RelPermalink }}" class="chip">
|
||||
<span class="dot"></span>
|
||||
{{ .Page.Title }}
|
||||
<span class="font-mono opacity-60 ml-1">{{ .Count }}</span>
|
||||
</a>
|
||||
{{- end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{- end -}}
|
||||
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,29 @@
|
||||
{{ define "main" }}
|
||||
<div class="bg-bg-deep border-b border-warm/10">
|
||||
<div class="max-w-[1280px] mx-auto px-8 max-[860px]:px-5 py-16">
|
||||
<div class="eyebrow mb-3">{{ .Type | title }}</div>
|
||||
<h1 class="display text-[clamp(36px,6vw,72px)] mb-4">{{ .Title }}</h1>
|
||||
<p class="text-ink-soft text-lg">{{ len .Pages }} {{ .Type | singularize }} types across {{ len .Site.RegularPages }} recipes.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="max-w-[1280px] mx-auto px-8 max-[860px]:px-5 py-16">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
{{- range .Pages.ByTitle -}}
|
||||
<a
|
||||
href="{{ .RelPermalink }}"
|
||||
class="group flex items-center justify-between p-4 rounded-xl border border-warm/10 bg-surface hover:border-gold/40 hover:bg-surface-2 transition-all duration-200"
|
||||
>
|
||||
<div>
|
||||
<div class="font-serif font-medium text-xl group-hover:text-gold transition-colors">{{ .Title }}</div>
|
||||
{{- $cnt := len .Pages -}}
|
||||
<div class="font-mono text-[11px] text-ink-mute mt-1">{{ $cnt }} {{ if eq $cnt 1 }}recipe{{ else }}recipes{{ end }}</div>
|
||||
</div>
|
||||
<div class="text-ink-faint group-hover:text-gold transition-colors">
|
||||
{{- partial "icon.html" "arrow-right" -}}
|
||||
</div>
|
||||
</a>
|
||||
{{- end -}}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user