196 lines
6.5 KiB
TypeScript
196 lines
6.5 KiB
TypeScript
import Link from "next/link";
|
||
import Image from "next/image";
|
||
import {
|
||
ArrowRight,
|
||
ArrowUpRight,
|
||
Compass,
|
||
Cuboid,
|
||
Map,
|
||
MapPin,
|
||
Move,
|
||
Timer,
|
||
} from "lucide-react";
|
||
import { Header, Footer, EmptyState } from "@/components/Shell";
|
||
import { MapCard } from "@/components/MapCard";
|
||
import { catalog } from "@/lib/catalog";
|
||
export const dynamic = "force-dynamic";
|
||
export default async function Home() {
|
||
const maps = await catalog();
|
||
const serverCount = new Set(maps.map((m) => m.server_id)).size;
|
||
const locations = maps.reduce((n, m) => n + m.panorama_count, 0);
|
||
return (
|
||
<>
|
||
<Header />
|
||
<main>
|
||
<section className="hero">
|
||
<div className="hero-grid" />
|
||
<div className="hero-copy">
|
||
<div className="status-label">
|
||
<span className="live-dot" /> MINECRAFT WORLDS. REAL EXPLORATION.
|
||
</div>
|
||
<h1>
|
||
Get lost in a<br />
|
||
<span>familiar world.</span>
|
||
</h1>
|
||
<p>
|
||
Somewhere between the blocks, there’s a place you know.
|
||
<br className="desktop" /> Look around. Trust your instincts. Make
|
||
your guess.
|
||
</p>
|
||
<div className="hero-actions">
|
||
<Link href="/servers" className="button primary">
|
||
Find your next world <ArrowRight size={18} />
|
||
</Link>
|
||
<Link href="/about" className="text-link">
|
||
How it works <ArrowUpRight size={15} />
|
||
</Link>
|
||
</div>
|
||
<div className="hero-notes">
|
||
<span>
|
||
<Compass size={15} /> 360° panoramas
|
||
</span>
|
||
<span>
|
||
<Move size={15} /> No roads. No moving.
|
||
</span>
|
||
<span>
|
||
<Cuboid size={15} /> Just you and the blocks.
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div
|
||
className="hero-art"
|
||
aria-label="Minecraft terrain map illustration"
|
||
>
|
||
<div className="artifact-caption">
|
||
YOUR NEXT ADVENTURE IS OUT THERE
|
||
</div>
|
||
<div className="floating-coord">
|
||
<span className="square-dot" /> OVERWORLD
|
||
<span className="coord-muted">X ? · Z ?</span>
|
||
</div>
|
||
<div className="map-art-frame">
|
||
<Image
|
||
src="/images/example-map.webp"
|
||
alt="Top-down map of the real Paper renderer test world"
|
||
width={1024}
|
||
height={1024}
|
||
priority
|
||
unoptimized
|
||
/>
|
||
<div className="map-grid" />
|
||
<div className="map-pin">
|
||
<MapPin size={38} fill="currentColor" />
|
||
</div>
|
||
<div className="map-corner top-left" />
|
||
<div className="map-corner bottom-right" />
|
||
</div>
|
||
<span className="compass-art">
|
||
<Compass size={42} />
|
||
<small>N</small>
|
||
</span>
|
||
<div className="floating-tag">
|
||
<MapPin size={15} /> ONE WORLD. COUNTLESS POSSIBILITIES.
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<div className="grass-divider">
|
||
<span />
|
||
</div>
|
||
<section className="world-stats">
|
||
<div>
|
||
<strong>{serverCount}</strong>
|
||
<span>COMMUNITY SERVERS</span>
|
||
</div>
|
||
<div>
|
||
<strong>{maps.length}</strong>
|
||
<span>WORLDS TO EXPLORE</span>
|
||
</div>
|
||
<div>
|
||
<strong>{locations}</strong>
|
||
<span>PLACES TO GET LOST</span>
|
||
</div>
|
||
<div className="stat-note">
|
||
<span className="live-dot" />
|
||
Built by explorers.
|
||
<br />
|
||
For explorers.
|
||
</div>
|
||
</section>
|
||
<section className="section catalog-section">
|
||
<div className="section-heading">
|
||
<div>
|
||
<span className="eyebrow">PICK A WORLD. DROP A PIN.</span>
|
||
<h2>Where to today?</h2>
|
||
</div>
|
||
<Link className="text-link" href="/servers">
|
||
All worlds <ArrowRight size={16} />
|
||
</Link>
|
||
</div>
|
||
{maps.length ? (
|
||
<div className="cards-grid">
|
||
{maps.slice(0, 3).map((m, i) => (
|
||
<MapCard map={m} index={i} key={m.id} />
|
||
))}
|
||
</div>
|
||
) : (
|
||
<EmptyState title="The world is yours to map">
|
||
The catalog is waiting for its first approved community map.
|
||
Capture a world with our mod or server plugin.
|
||
</EmptyState>
|
||
)}
|
||
</section>
|
||
<section className="section journey">
|
||
<div className="journey-intro">
|
||
<span className="eyebrow">A NEW WAY TO SEE MINECRAFT</span>
|
||
<h2>
|
||
Every block
|
||
<br />
|
||
tells a story.
|
||
</h2>
|
||
<p>
|
||
That mountain. That oddly placed tower. That very suspicious dirt
|
||
hut. You’ve been here before… right?
|
||
</p>
|
||
<Link href="/about" className="text-link">
|
||
Learn how to play <ArrowRight size={16} />
|
||
</Link>
|
||
</div>
|
||
<div className="steps">
|
||
<article>
|
||
<span>01</span>
|
||
<Compass />
|
||
<h3>Take a look around</h3>
|
||
<p>Find clues in a full 360° view of a Minecraft world.</p>
|
||
</article>
|
||
<article>
|
||
<span>02</span>
|
||
<Map />
|
||
<h3>Trust your coordinates</h3>
|
||
<p>Open the map and pin the spot where you think you are.</p>
|
||
</article>
|
||
<article>
|
||
<span>03</span>
|
||
<Timer />
|
||
<h3>Beat the clock</h3>
|
||
<p>Five rounds. One world. How close can you get?</p>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
<section className="section contribute-banner">
|
||
<div>
|
||
<span className="eyebrow">YOUR SERVER DESERVES TO BE EXPLORED</span>
|
||
<h2>Put your world on the map.</h2>
|
||
<p>
|
||
Bring your builds, your landscapes, and your community to MineGeo.
|
||
</p>
|
||
</div>
|
||
<Link href="/downloads" className="button primary">
|
||
Create a map <ArrowUpRight size={18} />
|
||
</Link>
|
||
</section>
|
||
</main>
|
||
<Footer />
|
||
</>
|
||
);
|
||
}
|