Refresh the homepage and improve export and draft guidance
This commit is contained in:
282
app/page.tsx
282
app/page.tsx
@@ -2,190 +2,246 @@ import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
ArrowRight,
|
||||
ArrowUpRight,
|
||||
Compass,
|
||||
Cuboid,
|
||||
Map,
|
||||
MapPin,
|
||||
Move,
|
||||
Timer,
|
||||
Blocks,
|
||||
Upload,
|
||||
} from "lucide-react";
|
||||
import { Header, Footer, EmptyState } from "@/components/Shell";
|
||||
import { Header, Footer } 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);
|
||||
const servers = new Set(maps.map((map) => map.server_id)).size;
|
||||
const locations = maps.reduce((total, map) => total + map.panorama_count, 0);
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main>
|
||||
<main className="home-page">
|
||||
<section className="hero">
|
||||
<div className="hero-grid" />
|
||||
<div className="hero-copy">
|
||||
<div className="status-label">
|
||||
<span className="live-dot" /> MINECRAFT WORLDS. REAL EXPLORATION.
|
||||
<span className="live-dot" /> MINECRAFT · EXPLORE · GUESS
|
||||
</div>
|
||||
<h1>
|
||||
Get lost in a<br />
|
||||
<span>familiar world.</span>
|
||||
Guess where you are
|
||||
<br />
|
||||
in a <span>blocky 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.
|
||||
Drop into a random corner of a Minecraft world.
|
||||
<br className="desktop" /> Look around, spot the landmarks, and
|
||||
place your pin
|
||||
<br className="desktop" /> before the clock runs out.
|
||||
</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} />
|
||||
Start exploring <ArrowRight size={18} />
|
||||
</Link>
|
||||
<span className="hero-mode-note">3 difficulty levels</span>
|
||||
</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 className="mode-dots" aria-hidden="true">
|
||||
<i />
|
||||
<i />
|
||||
<i />
|
||||
<i />
|
||||
</span>
|
||||
<span>Five rounds. No roads. Just your instincts.</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="hero-art" aria-label="Minecraft surface map">
|
||||
<div className="map-art-frame">
|
||||
<Image
|
||||
src="/images/example-map.webp"
|
||||
alt="Top-down map of the real Paper renderer test world"
|
||||
src={maps[0]?.mapImage || "/images/example-map.webp"}
|
||||
alt="A Minecraft surface map framed in parchment"
|
||||
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" />
|
||||
<span className="square-pin pin-green" />
|
||||
<span className="square-pin pin-red" />
|
||||
<span className="square-pin pin-gold" />
|
||||
</div>
|
||||
<span className="compass-art">
|
||||
<Compass size={42} />
|
||||
<span className="compass-art" aria-hidden="true">
|
||||
<Compass size={43} />
|
||||
<small>N</small>
|
||||
</span>
|
||||
<div className="floating-tag">
|
||||
<MapPin size={15} /> ONE WORLD. COUNTLESS POSSIBILITIES.
|
||||
<MapPin size={14} />
|
||||
<strong>X: ??? Z: ???</strong>
|
||||
<span>Overworld</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div className="grass-divider">
|
||||
<div className="grass-divider" aria-hidden="true">
|
||||
<span />
|
||||
</div>
|
||||
<section className="world-stats">
|
||||
<section className="world-stats" aria-label="Community statistics">
|
||||
<div>
|
||||
<strong>{serverCount}</strong>
|
||||
<span>COMMUNITY SERVERS</span>
|
||||
<i className="stat-cube green-cube" />
|
||||
<div>
|
||||
<strong>{servers.toLocaleString()}</strong>
|
||||
<span>COMMUNITY SERVERS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{maps.length}</strong>
|
||||
<span>WORLDS TO EXPLORE</span>
|
||||
<i className="stat-cube gold-cube" />
|
||||
<div>
|
||||
<strong>{maps.length.toLocaleString()}</strong>
|
||||
<span>PUBLISHED MAPS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{locations}</strong>
|
||||
<span>PLACES TO GET LOST</span>
|
||||
<i className="stat-cube cyan-cube" />
|
||||
<div>
|
||||
<strong>{locations.toLocaleString()}</strong>
|
||||
<span>PLACES TO DISCOVER</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="stat-note">
|
||||
<span className="live-dot" />
|
||||
Built by explorers.
|
||||
<br />
|
||||
For explorers.
|
||||
<div>
|
||||
<i className="stat-cube red-cube" />
|
||||
<div>
|
||||
<strong>5 rounds</strong>
|
||||
<span>EVERY EXPEDITION</span>
|
||||
</div>
|
||||
</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>
|
||||
<span className="eyebrow">COMMUNITY MAPS</span>
|
||||
<h2>Where will you go today?</h2>
|
||||
</div>
|
||||
<Link className="text-link" href="/servers">
|
||||
All worlds <ArrowRight size={16} />
|
||||
All {maps.length} maps <ArrowRight size={15} />
|
||||
</Link>
|
||||
</div>
|
||||
{maps.length ? (
|
||||
<div className="cards-grid">
|
||||
{maps.slice(0, 3).map((m, i) => (
|
||||
<MapCard map={m} index={i} key={m.id} />
|
||||
{maps.slice(0, 4).map((map, index) => (
|
||||
<MapCard map={map} index={index} key={map.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>
|
||||
<div className="first-map-panel">
|
||||
<div className="empty-map-art" aria-hidden="true">
|
||||
<Image
|
||||
src="/images/example-map.webp"
|
||||
alt=""
|
||||
width={180}
|
||||
height={180}
|
||||
unoptimized
|
||||
/>
|
||||
<span>YOUR WORLD HERE</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="eyebrow">
|
||||
THE FIRST EXPEDITION STARTS WITH YOU
|
||||
</span>
|
||||
<h3>Put your server on the map.</h3>
|
||||
<p>
|
||||
No community maps have been published yet. Export your world
|
||||
with the server plugin, or capture five locations with the
|
||||
Fabric mod. Preview your map and submit it for review.
|
||||
</p>
|
||||
<Link className="button primary" href="/downloads">
|
||||
<Upload size={16} /> Get the capture tools
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</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} />
|
||||
<section className="section home-panels">
|
||||
<article className="home-panel">
|
||||
<span className="eyebrow">HOW TO PLAY</span>
|
||||
<h2>Know your blocks?</h2>
|
||||
<ol className="play-steps">
|
||||
<li>
|
||||
<span>01</span>
|
||||
<div>
|
||||
<h3>Pick your world</h3>
|
||||
<p>Choose a community server, map, and difficulty.</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span>02</span>
|
||||
<div>
|
||||
<h3>Look for the clues</h3>
|
||||
<p>
|
||||
Rotate the panorama. Find builds, biomes, and landmarks.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<span>03</span>
|
||||
<div>
|
||||
<h3>Make your guess</h3>
|
||||
<p>Drop a pin on the map. Closer guesses earn more points.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
<Link className="text-link" href="/about">
|
||||
Read the field guide <ArrowRight size={14} />
|
||||
</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>
|
||||
</article>
|
||||
<article className="home-panel">
|
||||
<span className="eyebrow">CHOOSE YOUR CHALLENGE</span>
|
||||
<h2>One world. Three ways.</h2>
|
||||
<div className="mode-list">
|
||||
{[
|
||||
{
|
||||
name: "Easy",
|
||||
time: "180 seconds",
|
||||
detail: "Take your time. Rotate and zoom.",
|
||||
color: "green",
|
||||
},
|
||||
{
|
||||
name: "Normal",
|
||||
time: "90 seconds",
|
||||
detail: "Trust your eye. Rotate and zoom.",
|
||||
color: "gold",
|
||||
},
|
||||
{
|
||||
name: "Hard",
|
||||
time: "30 seconds",
|
||||
detail: "Think fast. No zoom allowed.",
|
||||
color: "red",
|
||||
},
|
||||
].map((mode) => (
|
||||
<Link href="/servers" className="mode-row" key={mode.name}>
|
||||
<i className={`stat-cube ${mode.color}-cube`} />
|
||||
<div>
|
||||
<h3>
|
||||
{mode.name}
|
||||
<span>
|
||||
<Timer size={12} />
|
||||
{mode.time}
|
||||
</span>
|
||||
</h3>
|
||||
<p>{mode.detail}</p>
|
||||
</div>
|
||||
<ArrowRight size={15} />
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<p className="mode-footnote">
|
||||
Up to 5,000 points per round. How close can you get?
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
<section className="section contribute-banner">
|
||||
<Blocks size={38} />
|
||||
<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>
|
||||
<span className="eyebrow">BUILT BY THE COMMUNITY</span>
|
||||
<h2>Your world deserves to be explored.</h2>
|
||||
<p>Share your builds and your favorite corners of Minecraft.</p>
|
||||
</div>
|
||||
<Link href="/downloads" className="button primary">
|
||||
Create a map <ArrowUpRight size={18} />
|
||||
<Link href="/downloads" className="button">
|
||||
Create a map <ArrowRight size={16} />
|
||||
</Link>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user