Initial build: Great Bear microbrewery site

- TanStack Start (React 19, Tailwind 4) frontend recreated from Stitch design
- PocketBase backend with schema migration + idempotent content seed
- Single Docker image running both services (non-root, healthchecked)
- deploy.sh to build & push to registry.tanshu.com
- Ansible playbook (roles: app, caddy) deploying to www.greatbear.in
  with Caddy TLS entries for the site and the PocketBase admin
This commit is contained in:
2026-09-03 08:51:47 +05:30
commit 7b070fde81
66 changed files with 8375 additions and 0 deletions
+159
View File
@@ -0,0 +1,159 @@
import { createFileRoute } from '@tanstack/react-router'
import { getVisitData } from '~/lib/data'
import { ReservationForm } from '~/components/reservation-form'
export const Route = createFileRoute('/visit')({
head: () => ({
meta: [
{ title: 'Visit & Contact | The Great Bear Microbrewery' },
{
name: 'description',
content:
'Reserve your table at Chandigarhs premier microbrewery — SCO 32, Sector 26, Madhya Marg. Open daily 12:00 PM 1:00 AM.',
},
],
}),
loader: () => getVisitData(),
component: VisitPage,
})
function VisitPage() {
const settings = Route.useLoaderData()
const directionsUrl = `https://maps.google.com/?q=${encodeURIComponent(settings.maps_query)}`
const embedUrl = `https://maps.google.com/maps?q=${encodeURIComponent(settings.maps_query)}&output=embed`
return (
<div className="flex w-full flex-col">
{/* Hero Section with Immersive Atmosphere */}
<div className="relative flex min-h-[500px] w-full items-center justify-center overflow-hidden bg-surface">
<div
className="absolute inset-0 bg-cover bg-center opacity-40 mix-blend-luminosity"
style={{ backgroundImage: "url('/images/visit-hero.jpg')" }}
/>
<div className="absolute inset-0 bg-gradient-to-t from-surface via-surface/60 to-transparent" />
<div className="relative z-10 mx-auto flex max-w-7xl flex-col items-center gap-space-md px-grid-margin py-space-2xl text-center">
<span className="text-label-lg uppercase tracking-widest text-primary">
Get in Touch &amp; Experience The Craft
</span>
<h1 className="font-headline-xl text-headline-xl text-on-surface">
Visit The Great Bear
</h1>
<p className="max-w-2xl font-body-lg text-body-lg text-on-surface-variant">
Step into Chandigarh's premier microbrewery. Whether you're planning an evening with
close friends or reserving a table for a celebration, our doors are open daily.
</p>
</div>
</div>
{/* Main Content Grid: Reservation & Quick Info */}
<section className="mx-auto grid w-full max-w-7xl grid-cols-1 items-start gap-grid-gutter px-grid-margin py-space-xl lg:grid-cols-12">
{/* Left Column: Reservation Form */}
<div className="flex flex-col gap-space-lg rounded-xl bg-surface-container p-space-lg shadow-xl lg:col-span-7">
<div className="flex flex-col gap-space-xs">
<span className="text-label-lg uppercase text-primary">Table Booking</span>
<h2 className="font-headline-lg text-on-surface">Reserve Your Experience</h2>
<p className="text-body-sm text-on-surface-variant">
Fill out the details below and our host will confirm your table promptly.
</p>
</div>
<ReservationForm />
</div>
{/* Right Column: Location, Hours, Contact Card */}
<div className="flex flex-col gap-space-lg lg:col-span-5">
<div className="flex flex-col gap-space-md rounded-xl bg-surface-container p-space-lg shadow-xl">
<div className="flex items-center gap-space-md border-b border-outline-variant/20 pb-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">schedule</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface">Operating Hours</h3>
<p className="text-body-sm font-medium text-primary">{settings.hours_line}</p>
</div>
</div>
<div className="flex items-center gap-space-md border-b border-outline-variant/20 pb-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">location_on</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface">Location</h3>
<p className="text-body-sm text-on-surface-variant">
{settings.address_line}
<br />
{settings.city_line}
</p>
</div>
</div>
<div className="flex items-center gap-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/20 text-primary">
<span className="material-symbols-outlined">call</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface">Direct Lines</h3>
<p className="text-body-sm text-on-surface-variant">
{settings.phone_primary}
<br />
{settings.phone_secondary}
</p>
</div>
</div>
</div>
{/* Quick Social Callout */}
<a
className="group flex items-center justify-between rounded-xl bg-surface-container p-space-lg shadow-xl transition-all hover:bg-surface-container-high"
href={settings.instagram_url}
rel="noopener noreferrer"
target="_blank"
>
<div className="flex items-center gap-space-md">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-tr from-amber-600 via-rose-600 to-purple-600 text-white">
<span className="material-symbols-outlined">photo_camera</span>
</div>
<div>
<h3 className="font-headline-md text-on-surface transition-colors group-hover:text-primary">
Instagram Feed
</h3>
<p className="text-body-sm text-on-surface-variant">{settings.instagram_handle}</p>
</div>
</div>
<span className="material-symbols-outlined text-on-surface-variant transition-transform group-hover:translate-x-1">
arrow_forward
</span>
</a>
</div>
</section>
{/* Interactive Map Section */}
<section className="w-full bg-surface-container-low py-space-xl">
<div className="mx-auto flex max-w-7xl flex-col gap-space-lg px-grid-margin">
<div className="flex flex-col justify-between gap-space-md md:flex-row md:items-end">
<div>
<span className="text-label-lg uppercase text-primary">Find Us Easily</span>
<h2 className="font-headline-lg text-on-surface">Sector 26, Madhya Marg Hub</h2>
</div>
<a
className="flex items-center gap-space-xs self-start rounded-lg border border-primary bg-transparent px-space-md py-space-sm text-label-lg text-primary transition-all hover:bg-primary hover:text-on-primary md:self-auto"
href={directionsUrl}
rel="noopener noreferrer"
target="_blank"
>
<span className="material-symbols-outlined text-[18px]">directions</span>
Get Directions
</a>
</div>
<div className="h-[450px] w-full overflow-hidden rounded-xl shadow-xl">
<iframe
title="The Great Bear Microbrewery location map"
src={embedUrl}
className="h-full w-full border-0"
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
allowFullScreen
/>
</div>
</div>
</section>
</div>
)
}