Skip to content

Commit bf02186

Browse files
committed
iterate
1 parent 25e3d12 commit bf02186

9 files changed

Lines changed: 308 additions & 4 deletions

File tree

apps/web/app/about/page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Footer from '@/components/Footer'
2+
13
export const metadata = {
24
title: 'About — Gray Farms',
35
description: 'Gray Farms is an open directory of coffee and tea estates across India, built by Gray Cup.',
@@ -85,6 +87,7 @@ export default function AboutPage() {
8587
Visit graycup.org →
8688
</a>
8789
</div>
90+
<Footer />
8891
</div>
8992
</div>
9093
)

apps/web/app/globals.css

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,44 @@ header {
188188
.navbar-links a:visited { color: #555; }
189189
.navbar-links a:hover { background: #f4f4f4; color: #111; }
190190

191+
.navbar-pages-wrap {
192+
position: relative;
193+
}
194+
.navbar-pages-btn {
195+
font-size: 0.9rem;
196+
color: #555;
197+
padding: 0.35rem 0.55rem;
198+
border-radius: 6px;
199+
background: none;
200+
border: none;
201+
cursor: pointer;
202+
font-family: inherit;
203+
}
204+
.navbar-pages-btn:hover { background: #f4f4f4; color: #111; }
205+
.navbar-pages-dropdown {
206+
position: absolute;
207+
top: calc(100% + 6px);
208+
left: 0;
209+
background: #fff;
210+
border: 1px solid #e5e5e5;
211+
border-radius: 8px;
212+
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
213+
min-width: 180px;
214+
padding: 0.35rem;
215+
z-index: 200;
216+
display: flex;
217+
flex-direction: column;
218+
}
219+
.navbar-pages-dropdown a {
220+
font-size: 0.875rem;
221+
color: #444;
222+
padding: 0.45rem 0.65rem;
223+
border-radius: 5px;
224+
display: block;
225+
}
226+
.navbar-pages-dropdown a:visited { color: #444; }
227+
.navbar-pages-dropdown a:hover { background: #f4f4f4; color: #111; }
228+
191229
.navbar-right {
192230
display: flex;
193231
align-items: center;
@@ -747,6 +785,104 @@ header {
747785
}
748786

749787

788+
/* ── Sitemap page ────────────────────────────────────────── */
789+
.sitemap-section {
790+
margin-bottom: 2rem;
791+
}
792+
.sitemap-section h2 {
793+
font-size: var(--text-base);
794+
font-weight: 600;
795+
margin-bottom: 0.6rem;
796+
padding-bottom: 0.4rem;
797+
border-bottom: 1px solid var(--app-color-border);
798+
}
799+
.sitemap-section ul {
800+
list-style: none;
801+
padding: 0;
802+
display: flex;
803+
flex-direction: column;
804+
gap: 0.3rem;
805+
}
806+
.sitemap-section li {
807+
font-size: var(--text-small);
808+
}
809+
.sitemap-section a {
810+
color: #444;
811+
}
812+
.sitemap-section a:hover { color: #111; }
813+
814+
/* ── Pages grid ──────────────────────────────────────────── */
815+
.pages-grid {
816+
display: grid;
817+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
818+
gap: 0.75rem;
819+
margin-bottom: 2rem;
820+
}
821+
.pages-card {
822+
display: flex;
823+
flex-direction: column;
824+
gap: 0.35rem;
825+
padding: 1rem 1.1rem;
826+
border: 1px solid var(--app-color-border);
827+
border-radius: 8px;
828+
color: inherit;
829+
transition: border-color 0.15s, box-shadow 0.15s;
830+
}
831+
.pages-card:visited { color: inherit; }
832+
.pages-card:hover {
833+
border-color: #bbb;
834+
box-shadow: 0 2px 8px rgba(0,0,0,0.07);
835+
color: inherit;
836+
}
837+
.pages-card-label {
838+
font-weight: 600;
839+
font-size: var(--text-base);
840+
color: #111;
841+
}
842+
.pages-card-desc {
843+
font-size: var(--text-small);
844+
color: var(--app-color-muted);
845+
line-height: 1.5;
846+
}
847+
848+
/* ── Site footer ─────────────────────────────────────────── */
849+
.site-footer {
850+
border-top: 1px solid var(--app-color-border);
851+
padding: 1.5rem 1.5rem;
852+
margin-top: 3rem;
853+
}
854+
.site-footer-inner {
855+
max-width: 720px;
856+
margin: 0 auto;
857+
display: flex;
858+
align-items: center;
859+
gap: 1.5rem;
860+
flex-wrap: wrap;
861+
font-size: var(--text-small);
862+
}
863+
.site-footer-brand {
864+
font-weight: 500;
865+
color: #111;
866+
}
867+
.site-footer-links {
868+
display: flex;
869+
gap: 0.25rem;
870+
flex: 1;
871+
}
872+
.site-footer-links a {
873+
color: #555;
874+
padding: 0.2rem 0.4rem;
875+
border-radius: 4px;
876+
}
877+
.site-footer-links a:visited { color: #555; }
878+
.site-footer-links a:hover { color: #111; }
879+
.site-footer-copy {
880+
color: var(--app-color-muted);
881+
margin-left: auto;
882+
}
883+
.site-footer-copy a { color: var(--app-color-muted); }
884+
.site-footer-copy a:hover { color: #111; }
885+
750886
/* ── Submit form page ────────────────────────────────────── */
751887
.form-page {
752888
max-width: 640px;

apps/web/app/impressum/page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Footer from '@/components/Footer'
2+
13
export const metadata = {
24
title: 'Impressum — Gray Farms',
35
}
@@ -38,6 +40,7 @@ export default function ImpressumPage() {
3840
for follow-up if needed). No data is sold or shared with third parties.
3941
</p>
4042
</div>
43+
<Footer />
4144
</div>
4245
</div>
4346
)

apps/web/app/pages/page.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import Footer from '@/components/Footer'
2+
3+
export const metadata = {
4+
title: 'Pages | Gray Farms',
5+
description: 'All pages on Gray Farms — explore coffee and tea farms by region across India.',
6+
}
7+
8+
const CARDS = [
9+
{
10+
label: 'South India',
11+
href: '/region/south-india',
12+
description: 'Coffee and tea farms in Karnataka, Kerala, Tamil Nadu, and Andhra Pradesh.',
13+
},
14+
{
15+
label: 'North East India',
16+
href: '/region/north-east-india',
17+
description: 'Tea estates in Assam, Sikkim, Meghalaya, and across the seven sisters.',
18+
},
19+
{
20+
label: 'East India',
21+
href: '/region/east-india',
22+
description: 'Darjeeling and other estates in West Bengal, Odisha, and Jharkhand.',
23+
},
24+
{
25+
label: 'North India',
26+
href: '/region/north-india',
27+
description: 'High-altitude tea gardens in Himachal Pradesh and Uttarakhand.',
28+
},
29+
{
30+
label: 'West India',
31+
href: '/region/west-india',
32+
description: 'Emerging coffee and tea farms in Maharashtra and surrounding states.',
33+
},
34+
]
35+
36+
export default function PagesPage() {
37+
return (
38+
<div className="layout" style={{ display: 'block', height: '100vh', overflowY: 'auto' }}>
39+
<div className="form-page" style={{ height: 'auto', overflow: 'visible', maxWidth: '720px' }}>
40+
<a href="/" className="back">← Back to directory</a>
41+
<h1 style={{ fontSize: 'var(--text-heading)', marginBottom: '0.5rem' }}>Pages</h1>
42+
<p style={{ color: 'var(--app-color-muted)', fontSize: 'var(--text-small)', marginBottom: '2rem' }}>
43+
Everything on Gray Farms.
44+
</p>
45+
<div className="pages-grid">
46+
{CARDS.map(card => (
47+
<a key={card.href} href={card.href} className="pages-card">
48+
<span className="pages-card-label">{card.label}</span>
49+
<span className="pages-card-desc">{card.description}</span>
50+
</a>
51+
))}
52+
</div>
53+
<Footer />
54+
</div>
55+
</div>
56+
)
57+
}

apps/web/app/region/[region]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { notFound } from 'next/navigation'
22
import { getCoffeeFarms, getTeaFarms, stripContact, toSlug } from '@/lib/farms'
33
import { REGIONS, getRegion } from '@/lib/regions'
4+
import Footer from '@/components/Footer'
45

56
export const dynamic = 'force-static'
67

@@ -97,6 +98,7 @@ export default async function RegionPage({ params }: { params: Promise<{ region:
9798
)}
9899
</div>
99100
)}
101+
<Footer />
100102
</div>
101103
</div>
102104
)

apps/web/app/sitemap.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export default function sitemap(): MetadataRoute.Sitemap {
2121

2222
return [
2323
{ url: BASE_URL, changeFrequency: 'weekly', priority: 1 },
24+
{ url: `${BASE_URL}/pages`, changeFrequency: 'monthly', priority: 0.6 },
25+
{ url: `${BASE_URL}/blog`, changeFrequency: 'weekly', priority: 0.7 },
26+
{ url: `${BASE_URL}/sitemap`, changeFrequency: 'monthly', priority: 0.4 },
2427
{ url: `${BASE_URL}/about`, changeFrequency: 'monthly', priority: 0.5 },
2528
{ url: `${BASE_URL}/impressum`, changeFrequency: 'yearly', priority: 0.3 },
2629
...regionUrls,

apps/web/app/sitemap/page.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { getCoffeeFarms, getTeaFarms, toSlug } from '@/lib/farms'
2+
import { REGIONS } from '@/lib/regions'
3+
import Footer from '@/components/Footer'
4+
5+
export const metadata = {
6+
title: 'Sitemap | Gray Farms',
7+
description: 'A full list of all pages on Gray Farms.',
8+
}
9+
10+
const STATIC_PAGES = [
11+
{ label: 'Home', href: '/' },
12+
{ label: 'Pages', href: '/pages' },
13+
{ label: 'Blog', href: '/blog' },
14+
{ label: 'About', href: '/about' },
15+
{ label: 'Impressum', href: '/impressum' },
16+
]
17+
18+
export default function SitemapPage() {
19+
const coffeeFarms = getCoffeeFarms()
20+
const teaFarms = getTeaFarms()
21+
22+
return (
23+
<div className="layout" style={{ display: 'block', height: '100vh', overflowY: 'auto' }}>
24+
<div className="form-page" style={{ height: 'auto', overflow: 'visible', maxWidth: '720px' }}>
25+
<a href="/" className="back">← Back to directory</a>
26+
<h1 style={{ fontSize: 'var(--text-heading)', marginBottom: '2rem' }}>Sitemap</h1>
27+
28+
<div className="sitemap-section">
29+
<h2>General</h2>
30+
<ul>
31+
{STATIC_PAGES.map(p => (
32+
<li key={p.href}><a href={p.href}>{p.label}</a></li>
33+
))}
34+
</ul>
35+
</div>
36+
37+
<div className="sitemap-section">
38+
<h2>Regions</h2>
39+
<ul>
40+
{REGIONS.map(r => (
41+
<li key={r.slug}><a href={`/region/${r.slug}`}>{r.label}</a></li>
42+
))}
43+
</ul>
44+
</div>
45+
46+
<div className="sitemap-section">
47+
<h2>Coffee Farms ({coffeeFarms.length})</h2>
48+
<ul>
49+
{coffeeFarms.map(f => (
50+
<li key={f.id}>
51+
<a href={`/farms/${toSlug(f.name)}`}>{f.name}</a>
52+
<span style={{ color: 'var(--app-color-muted)', fontSize: 'var(--text-small)', marginLeft: '0.5rem' }}>
53+
{f.city}, {f.state}
54+
</span>
55+
</li>
56+
))}
57+
</ul>
58+
</div>
59+
60+
<div className="sitemap-section">
61+
<h2>Tea Estates ({teaFarms.length})</h2>
62+
<ul>
63+
{teaFarms.map(f => (
64+
<li key={f.id}>
65+
<a href={`/farms/${toSlug(f.name)}`}>{f.name}</a>
66+
<span style={{ color: 'var(--app-color-muted)', fontSize: 'var(--text-small)', marginLeft: '0.5rem' }}>
67+
{f.city}, {f.state}
68+
</span>
69+
</li>
70+
))}
71+
</ul>
72+
</div>
73+
74+
<Footer />
75+
</div>
76+
</div>
77+
)
78+
}

apps/web/components/Footer.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Link from 'next/link'
2+
3+
export default function Footer() {
4+
return (
5+
<footer className="site-footer">
6+
<div className="site-footer-inner">
7+
<span className="site-footer-brand">Gray Farms</span>
8+
<nav className="site-footer-links">
9+
<Link href="/about">About</Link>
10+
<Link href="/blog">Blog</Link>
11+
<Link href="/impressum">Impressum</Link>
12+
</nav>
13+
<span className="site-footer-copy">
14+
&copy; {new Date().getFullYear()}{' '}
15+
<a href="https://graycup.org" target="_blank" rel="noopener noreferrer">Gray Cup Enterprises</a>
16+
</span>
17+
</div>
18+
</footer>
19+
)
20+
}

apps/web/components/Navbar.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ export default function Navbar() {
1616
<Link href="/" className="navbar-brand">Gray Farms</Link>
1717
<span className="navbar-sep" aria-hidden>|</span>
1818
<nav className="navbar-links">
19-
<Link href="/about">About</Link>
20-
<Link href="/impressum">Impressum</Link>
19+
<Link href="/pages">Pages</Link>
20+
<Link href="/blog">Blog</Link>
21+
<Link href="/sitemap">Sitemap</Link>
2122
</nav>
2223
</div>
2324

@@ -51,8 +52,9 @@ export default function Navbar() {
5152
<aside className={`mobile-drawer${menuOpen ? ' open' : ''}`}>
5253
<button className="mobile-close" onClick={() => setMenuOpen(false)} aria-label="Close menu"></button>
5354
<nav className="mobile-nav">
54-
<Link href="/about" onClick={() => setMenuOpen(false)}>About</Link>
55-
<Link href="/impressum" onClick={() => setMenuOpen(false)}>Impressum</Link>
55+
<Link href="/pages" onClick={() => setMenuOpen(false)}>Pages</Link>
56+
<Link href="/blog" onClick={() => setMenuOpen(false)}>Blog</Link>
57+
<Link href="/sitemap" onClick={() => setMenuOpen(false)}>Sitemap</Link>
5658
<SubmitDialog />
5759
</nav>
5860
<div className="mobile-actions">

0 commit comments

Comments
 (0)