Render the header and footer from the root layout

Every page was importing Header and Footer and repeating the same store
name, logo, copyright and nav links. Hoisting both into the root layout
renders them once, and a new config/site.ts holds the values they shared.

The body becomes a flex column so the footer sits at the bottom of short
pages. not-found and error now render inside that chrome, so their
full-viewport centering drops to 60vh.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D1vsTA4MX6qFd7nqSAKtdV
This commit is contained in:
Rami Bitar
2026-08-05 15:03:44 -04:00
co-authored by Claude Opus 5
parent 8602e03079
commit ff4adba2fb
17 changed files with 174 additions and 309 deletions
+18 -24
View File
@@ -1,5 +1,3 @@
import Header from '@/components/shopify/header';
import Footer from '@/components/shopify/footer';
import AccountForm from '@/components/shopify/account-form';
export const metadata = { title: 'Activate your account — Shop' };
@@ -13,27 +11,23 @@ export default async function Page({
const { id, token } = await params;
return (
<>
<Header storeName="Shop" logoUrl="" />
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Activate your account"
description="Choose a password to finish setting up your account."
fields={[
{
name: 'password',
label: 'Password',
type: 'password',
autoComplete: 'new-password',
},
]}
submitLabel="Activate account"
endpoint="/api/account/activate"
extraPayload={{ id, activationToken: token }}
redirectTo="/account"
/>
</main>
<Footer storeName="Shop" copyright="© 2026 Shop. All rights reserved." />
</>
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Activate your account"
description="Choose a password to finish setting up your account."
fields={[
{
name: 'password',
label: 'Password',
type: 'password',
autoComplete: 'new-password',
},
]}
submitLabel="Activate account"
endpoint="/api/account/activate"
extraPayload={{ id, activationToken: token }}
redirectTo="/account"
/>
</main>
);
}
+29 -35
View File
@@ -1,44 +1,38 @@
import Header from '@/components/shopify/header';
import Footer from '@/components/shopify/footer';
import AccountForm, { AccountFormLink } from '@/components/shopify/account-form';
export const metadata = { title: 'Sign in — Shop' };
export default function Page() {
return (
<>
<Header storeName="Shop" logoUrl="" />
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Sign in"
fields={[
{ name: 'email', label: 'Email', type: 'email', autoComplete: 'email' },
{
name: 'password',
label: 'Password',
type: 'password',
autoComplete: 'current-password',
},
]}
submitLabel="Sign in"
endpoint="/api/account/login"
redirectTo="/account"
footer={
<>
<span>
New here?{' '}
<AccountFormLink href="/account/register">
Create an account
</AccountFormLink>
</span>
<AccountFormLink href="/account/recover">
Forgot your password?
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Sign in"
fields={[
{ name: 'email', label: 'Email', type: 'email', autoComplete: 'email' },
{
name: 'password',
label: 'Password',
type: 'password',
autoComplete: 'current-password',
},
]}
submitLabel="Sign in"
endpoint="/api/account/login"
redirectTo="/account"
footer={
<>
<span>
New here?{' '}
<AccountFormLink href="/account/register">
Create an account
</AccountFormLink>
</>
}
/>
</main>
<Footer storeName="Shop" copyright="© 2026 Shop. All rights reserved." />
</>
</span>
<AccountFormLink href="/account/recover">
Forgot your password?
</AccountFormLink>
</>
}
/>
</main>
);
}
+11 -19
View File
@@ -1,6 +1,4 @@
import { redirect } from 'next/navigation';
import Header from '@/components/shopify/header';
import Footer from '@/components/shopify/footer';
import OrderHistory from '@/components/shopify/order-history';
import { getSessionToken } from '@/services/shopify/session';
import { getCustomer } from '@/services/shopify/customer';
@@ -16,23 +14,17 @@ export default async function Page() {
if (!customer) redirect('/account/login');
return (
<>
<Header storeName="Shop" logoUrl="" />
<main className="max-w-screen-2xl mx-auto w-full px-8 py-12">
<h1 className="text-2xl md:text-3xl font-normal text-foreground">
Order history
</h1>
<p className="mt-1 text-sm text-muted-foreground">
{customer.displayName} · {customer.email}
</p>
<main className="max-w-screen-2xl mx-auto w-full px-8 py-12">
<h1 className="text-2xl md:text-3xl font-normal text-foreground">
Order history
</h1>
<p className="mt-1 text-sm text-muted-foreground">
{customer.displayName} · {customer.email}
</p>
<div className="mt-10">
<OrderHistory customer={customer} />
</div>
</main>
<Footer storeName="Shop" copyright="© 2026 Shop. All rights reserved." />
</>
<div className="mt-10">
<OrderHistory customer={customer} />
</div>
</main>
);
}
+15 -21
View File
@@ -1,29 +1,23 @@
import Header from '@/components/shopify/header';
import Footer from '@/components/shopify/footer';
import AccountForm, { AccountFormLink } from '@/components/shopify/account-form';
export const metadata = { title: 'Reset password — Shop' };
export default function Page() {
return (
<>
<Header storeName="Shop" logoUrl="" />
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Reset password"
description="Enter your email and we'll send you a link to set a new password."
fields={[
{ name: 'email', label: 'Email', type: 'email', autoComplete: 'email' },
]}
submitLabel="Send reset link"
endpoint="/api/account/recover"
successMessage="If that email has an account, a reset link is on its way."
footer={
<AccountFormLink href="/account/login">Back to sign in</AccountFormLink>
}
/>
</main>
<Footer storeName="Shop" copyright="© 2026 Shop. All rights reserved." />
</>
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Reset password"
description="Enter your email and we'll send you a link to set a new password."
fields={[
{ name: 'email', label: 'Email', type: 'email', autoComplete: 'email' },
]}
submitLabel="Send reset link"
endpoint="/api/account/recover"
successMessage="If that email has an account, a reset link is on its way."
footer={
<AccountFormLink href="/account/login">Back to sign in</AccountFormLink>
}
/>
</main>
);
}
+35 -41
View File
@@ -1,49 +1,43 @@
import Header from '@/components/shopify/header';
import Footer from '@/components/shopify/footer';
import AccountForm, { AccountFormLink } from '@/components/shopify/account-form';
export const metadata = { title: 'Create account — Shop' };
export default function Page() {
return (
<>
<Header storeName="Shop" logoUrl="" />
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Create account"
fields={[
{
name: 'firstName',
label: 'First name',
autoComplete: 'given-name',
required: false,
},
{
name: 'lastName',
label: 'Last name',
autoComplete: 'family-name',
required: false,
},
{ name: 'email', label: 'Email', type: 'email', autoComplete: 'email' },
{
name: 'password',
label: 'Password',
type: 'password',
autoComplete: 'new-password',
},
]}
submitLabel="Create account"
endpoint="/api/account/register"
redirectTo="/account"
footer={
<span>
Already have an account?{' '}
<AccountFormLink href="/account/login">Sign in</AccountFormLink>
</span>
}
/>
</main>
<Footer storeName="Shop" copyright="© 2026 Shop. All rights reserved." />
</>
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Create account"
fields={[
{
name: 'firstName',
label: 'First name',
autoComplete: 'given-name',
required: false,
},
{
name: 'lastName',
label: 'Last name',
autoComplete: 'family-name',
required: false,
},
{ name: 'email', label: 'Email', type: 'email', autoComplete: 'email' },
{
name: 'password',
label: 'Password',
type: 'password',
autoComplete: 'new-password',
},
]}
submitLabel="Create account"
endpoint="/api/account/register"
redirectTo="/account"
footer={
<span>
Already have an account?{' '}
<AccountFormLink href="/account/login">Sign in</AccountFormLink>
</span>
}
/>
</main>
);
}
+17 -23
View File
@@ -1,5 +1,3 @@
import Header from '@/components/shopify/header';
import Footer from '@/components/shopify/footer';
import AccountForm from '@/components/shopify/account-form';
export const metadata = { title: 'Set a new password — Shop' };
@@ -13,26 +11,22 @@ export default async function Page({
const { id, token } = await params;
return (
<>
<Header storeName="Shop" logoUrl="" />
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Set a new password"
fields={[
{
name: 'password',
label: 'New password',
type: 'password',
autoComplete: 'new-password',
},
]}
submitLabel="Save password"
endpoint="/api/account/reset"
extraPayload={{ id, resetToken: token }}
redirectTo="/account"
/>
</main>
<Footer storeName="Shop" copyright="© 2026 Shop. All rights reserved." />
</>
<main className="max-w-screen-2xl mx-auto w-full px-8 py-16">
<AccountForm
title="Set a new password"
fields={[
{
name: 'password',
label: 'New password',
type: 'password',
autoComplete: 'new-password',
},
]}
submitLabel="Save password"
endpoint="/api/account/reset"
extraPayload={{ id, resetToken: token }}
redirectTo="/account"
/>
</main>
);
}