homepage tweaks

This commit is contained in:
2025-12-28 17:37:02 -05:00
parent 2202abe89f
commit 0dd89a751b
4 changed files with 201 additions and 45 deletions
+181 -45
View File
@@ -3,6 +3,14 @@
import { FormEvent, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import {
WrenchScrewdriverIcon,
ShieldExclamationIcon,
CurrencyDollarIcon,
BookmarkSquareIcon,
BuildingStorefrontIcon,
ChatBubbleLeftRightIcon,
} from "@heroicons/react/20/solid";
export default function HomePage() {
const [email, setEmail] = useState("");
@@ -39,7 +47,12 @@ export default function HomePage() {
const res = await fetch("/api/beta-signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, useCase, acceptedTos: accepted, tosVersion: TOS_VERSION }),
body: JSON.stringify({
email,
useCase,
acceptedTos: accepted,
tosVersion: TOS_VERSION,
}),
});
if (!res.ok) {
@@ -60,6 +73,43 @@ export default function HomePage() {
}
}
const features = [
{
name: "Guided part roles",
description: "Pick parts by role so youre not guessing what fits where.",
icon: WrenchScrewdriverIcon,
},
{
name: "Basic compatibility warnings",
description:
"Early guardrails to catch obvious mismatches before you buy.",
icon: ShieldExclamationIcon,
},
{
name: "Live pricing totals",
description:
"See the running total as you build, with real retailer listings.",
icon: CurrencyDollarIcon,
},
{
name: "Save builds",
description: "Save a build to your account so you can finish it later.",
icon: BookmarkSquareIcon,
},
{
name: "Limited retailers (for now)",
description:
"Were starting small with a couple merchants and expanding fast.",
icon: BuildingStorefrontIcon,
},
{
name: "Feedback-driven roadmap",
description:
"Tell us whats confusing, wrong, or missing — well fix that first.",
icon: ChatBubbleLeftRightIcon,
},
];
return (
<main className="min-h-screen bg-black text-zinc-50">
{/* Abstract Brand Background */}
@@ -112,48 +162,71 @@ export default function HomePage() {
{/* Top Bar / Logo */}
<header className="flex items-center justify-between gap-4">
<div className="flex items-center gap-3">
<div className="flex items-center">
<Image
src="/battl/battl-logo-mark-f.svg"
alt="Battl Builders Logo"
width={260} // adjust to taste
height={48} // adjust to taste
className="block"
/>
</div>
<Image
src="/battl/battl-logo-mark-f.svg"
alt="Battl Builders Logo"
width={260}
height={48}
className="block"
/>
</div>
<span className="rounded-full border border-amber-500/40 bg-amber-500/10 px-3 py-1 text-xs font-medium text-amber-300">
Private Beta Coming Soon
</span>
<nav className="flex items-center gap-2 sm:gap-3">
<a
href="#request-access"
className="rounded-md border border-zinc-800 bg-zinc-950/60 px-3 py-2 text-xs font-medium text-zinc-200 hover:bg-zinc-900 hover:text-white"
>
Request Access
</a>
<Link
href="/login"
className="rounded-md border border-amber-500/60 bg-amber-500/15 px-3 py-2 text-xs font-medium text-amber-200 hover:bg-amber-500/20"
>
Sign In
</Link>
</nav>
</header>
{/* Hero */}
<section className="mt-16 grid gap-10 md:grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)] md:items-center">
<section className="mt-16 grid gap-10 md:grid-cols-[minmax(0,1.25fr)_minmax(0,1fr)] md:items-start">
<div>
<h1 className="text-balance text-3xl font-semibold tracking-tight sm:text-4xl md:text-5xl">
<div className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-black/30 px-3 py-1 text-xs uppercase tracking-[0.25em] text-white/70">
<span className="h-1.5 w-1.5 rounded-full bg-amber-400" />
Private Beta
<span className="text-white/40"></span>
<span className="text-white/60">AR-15 focus</span>
</div>
<h1 className="mt-6 text-balance text-3xl font-semibold tracking-tight sm:text-4xl md:text-5xl">
Stop Guessing.
<span className="block text-amber-300 py-0.16em">
Start Building.
</span>
<span className="block text-amber-300">Start Building.</span>
</h1>
<p className="mt-4 max-w-xl text-sm text-zinc-400 sm:text-base">
From part comparisons to full-build matchups, Battl Builders helps
you find the right components, catch compatibility issues, and
score the best deals all without juggling tabs or spreadsheets.
Battl Builders helps you plan an AR-15 build faster: choose parts
by role, get basic compatibility guidance, and compare real
listingswithout juggling tabs or spreadsheets.
</p>
<ul className="mt-6 space-y-2 text-sm text-zinc-300">
<li> Side-by-side part & build comparisons</li>
<li> Smart compatibility checks</li>
<li> Live pricing from vetted merchants</li>
<li> Save & share builds with your crew</li>
<li> Vote on the cleanest, meanest setups</li>
<li> Guided part roles (no where does this go?)</li>
<li> Basic compatibility warnings</li>
<li> Live pricing from current retailers</li>
<li> Save builds to your account</li>
</ul>
<p className="mt-4 text-xs text-white/50">
Early access beta. Data, pricing, and available parts are still
evolving.
</p>
</div>
{/* Beta Form */}
<div className="rounded-lg border border-zinc-800 bg-zinc-950/70 p-5 shadow-[0_0_0_1px_rgba(24,24,27,0.9)]">
<div
id="request-access"
className="scroll-mt-24 rounded-lg border border-zinc-800 bg-zinc-950/70 p-5 shadow-[0_0_0_1px_rgba(24,24,27,0.9)]"
>
<h2 className="text-sm font-semibold uppercase tracking-[0.18em] text-zinc-500">
Join the Beta List
</h2>
@@ -177,7 +250,7 @@ export default function HomePage() {
onChange={(e) => setEmail(e.target.value)}
placeholder="you@gearjunkie.com"
disabled={status === "loading" || status === "success"}
className="mt-1 w-full rounded-md border border-zinc-800 bg-zinc-950 px-3 py-2 text-sm text-zinc-50 outline-none ring-amber-500/30 placeholder:text-zinc-600 focus:border-amber-400/80 focus:ring-2 disabled:opacity-60 disabled:cursor-not-allowed"
className="mt-1 w-full rounded-md border border-zinc-800 bg-zinc-950 px-3 py-2 text-sm text-zinc-50 outline-none ring-amber-500/30 placeholder:text-zinc-600 focus:border-amber-400/80 focus:ring-2 disabled:cursor-not-allowed disabled:opacity-60"
required
/>
</div>
@@ -196,8 +269,8 @@ export default function HomePage() {
onChange={(e) => setUseCase(e.target.value)}
rows={3}
disabled={status === "loading" || status === "success"}
placeholder="E.g. Comparing build costs, finding the best deals, sharing my builds, weird influencer shit..."
className="mt-1 w-full rounded-md border border-zinc-800 bg-zinc-950 px-3 py-2 text-xs text-zinc-50 outline-none ring-amber-500/30 placeholder:text-zinc-600 focus:border-amber-400/80 focus:ring-2 disabled:opacity-60 disabled:cursor-not-allowed"
placeholder="E.g. Planning a build, comparing costs, sanity-checking compatibility..."
className="mt-1 w-full rounded-md border border-zinc-800 bg-zinc-950 px-3 py-2 text-xs text-zinc-50 outline-none ring-amber-500/30 placeholder:text-zinc-600 focus:border-amber-400/80 focus:ring-2 disabled:cursor-not-allowed disabled:opacity-60"
/>
</div>
@@ -215,14 +288,14 @@ export default function HomePage() {
I agree to the{" "}
<Link
href="/tos"
className="text-amber-300 hover:text-amber-200 underline"
className="text-amber-300 underline hover:text-amber-200"
>
Terms of Service
</Link>{" "}
and{" "}
<Link
href="/privacy"
className="text-amber-300 hover:text-amber-200 underline"
className="text-amber-300 underline hover:text-amber-200"
>
Privacy Policy
</Link>
@@ -261,19 +334,6 @@ export default function HomePage() {
</p>
)}
{status === "success" && (
<button
type="button"
onClick={() => {
setStatus("idle");
setMessage(null);
}}
className="w-full rounded-md border border-zinc-800 bg-zinc-950 px-3 py-2 text-xs text-zinc-200 hover:bg-zinc-900"
>
Submit another email
</button>
)}
<div className="mt-6 text-center text-[11px] text-zinc-500">
Already invited?{" "}
<a href="/login" className="underline hover:text-zinc-300">
@@ -284,6 +344,82 @@ export default function HomePage() {
</div>
</section>
{/* Screenshot Section */}
<section className="relative mt-24">
<div className="mx-auto max-w-6xl px-4 sm:px-6 lg:px-8">
<div className="relative overflow-hidden rounded-2xl border border-white/10 bg-black shadow-2xl">
{/* Screenshot */}
<Image
src="/builder-preview.png"
alt="Battl Builders app screenshot"
width={2400}
height={1400}
priority
className="w-full object-cover"
/>
{/* Bottom fade */}
<div
aria-hidden="true"
className="pointer-events-none absolute inset-x-0 bottom-0 h-24 bg-gradient-to-t from-black"
/>
</div>
</div>
</section>
{/* Info Section */}
<section className="mt-14 rounded-2xl border border-white/10 bg-white/5 px-6 py-14 sm:px-8">
<div className="mx-auto max-w-2xl text-left sm:text-center">
<p className="text-xs font-semibold uppercase tracking-[0.25em] text-amber-300/90">
Everything you need to test the core
</p>
<h2 className="mt-3 text-balance text-3xl font-semibold tracking-tight sm:text-4xl">
Build smarter rifles without the spreadsheet lifestyle.
</h2>
<p className="mt-4 text-sm leading-relaxed text-white/70 sm:text-base">
This private beta is focused on one thing: helping you plan an
AR-15 build faster and with fewer mistakes. Its early, its
evolving, and your feedback will decide what we build next.
</p>
</div>
<dl className="mx-auto mt-10 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-8 text-sm text-white/70 sm:grid-cols-2 lg:max-w-none lg:grid-cols-3">
{features.map((feature) => (
<div
key={feature.name}
className="relative rounded-xl border border-white/10 bg-black/30 p-5"
>
<dt className="flex items-center gap-2 text-sm font-semibold text-white">
<feature.icon
aria-hidden="true"
className="h-5 w-5 text-amber-300"
/>
{feature.name}
</dt>
<dd className="mt-2 text-sm text-white/70">
{feature.description}
</dd>
</div>
))}
</dl>
<div className="mx-auto mt-10 max-w-2xl rounded-xl border border-white/10 bg-black/30 p-5">
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-white/60">
What feedback we want
</div>
<ul className="mt-3 space-y-2 text-sm text-white/80">
<li> Where you got confused or stuck</li>
<li> Warnings that felt wrong (or missing)</li>
<li> Parts you expected to find but couldnt</li>
<li> If this beats your current build-planning process</li>
</ul>
<p className="mt-3 text-xs text-white/50">
By joining the private beta, you agree features, data, and pricing
may change.
</p>
</div>
</section>
{/* Footer strip */}
<footer className="mt-12 border-t border-zinc-900 pt-4 text-xs text-zinc-500">
<div className="flex flex-wrap items-center justify-between gap-3">
+19
View File
@@ -8,6 +8,7 @@
"name": "gunbuilder-prototype",
"version": "0.1.0",
"dependencies": {
"@heroicons/react": "^2.2.0",
"clsx": "^2.1.1",
"lucide-react": "^0.555.0",
"next": "14.2.3",
@@ -139,6 +140,15 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@heroicons/react": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
"integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==",
"license": "MIT",
"peerDependencies": {
"react": ">= 16 || ^19.0.0-rc"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -1012,6 +1022,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1452,6 +1463,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.25",
"caniuse-lite": "^1.0.30001754",
@@ -2134,6 +2146,7 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -2302,6 +2315,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -4531,6 +4545,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
@@ -4780,6 +4795,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -4792,6 +4808,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -5796,6 +5813,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -5965,6 +5983,7 @@
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
+1
View File
@@ -9,6 +9,7 @@
"lint": "next lint"
},
"dependencies": {
"@heroicons/react": "^2.2.0",
"clsx": "^2.1.1",
"lucide-react": "^0.555.0",
"next": "14.2.3",
Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB