Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add keystatic live preview and eternum game primary display #293

Merged
merged 7 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions apps/nextjs/content/blogs/eternum-the-oktober-test.mdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: 'Eternum: The OktoberTest'
image: image.png
subtitle: >-
An upgraded version of Eternum dropped. We invite you to celebrate, get to
know the game with the devs, and play with your fellow Lords in the
OktoberTest community events. Prost!
---
My Lord, schedule yourself an armor fitting—Eternum is coming out swinging. First OktoberTest, then the Mainnet Preview. Prepare to make landfall in Eternum with this guide.

## **What is the Eternum OktoberTest?**

Play the latest version of Eternum and join the Realms community over October.  There are player challenges, community events - including game design briefings, economic reviews,  play-alongs with the game’s developers - and the chance to earn a little beer money.

You do not need to be a Realm owner to play in the Eternum OktoberTest.  You will be assigned a Realm when you first play. The OktoberTest of Eternum takes place on a free-to-use testnet and there are zero in-game wallet transactions thanks to the [Cartridge](https://cartridge.gg/) Controller.  Let’s raise a drink to frictionless UX!

**What type of game is Eternum?**

Eternum is a real time strategy MMO that will feel familiar to those who have played other strategy games.  You will understand the game and be up and running quickly.

What we are all set to experience together is how a competitive multiplayer grand strategy game plays out when it is running on an open network. 

There is a wildness to a blockchain-based game that cannot be compared to one running on a publisher’s centrally administered server. We expect players to push the boundaries of this mercurial world—and expand it—in ways no one has yet imagined for a strategy game, writing stories onchain, imperishably, and forever.

Read about the fully onchain game, Eternum, [here](https://github.com/BibliothecaDAO/world-guide/blob/main/realms-world-guide-v1.0.0.pdf) and [here](https://realms.world/games/realms-eternum). 

## **What’s the goal of OktoberTest?**

OktoberTest will ease you into the new world. You will learn about the game from devs and other players, compete in a low stakes environment, develop allies and enemies - toasting both with a beer.

Following OktoberTest is the Eternum *Mainnet Preview.* Prepare yourself, my Lord, for your victories and defeats to settle on Ethereum via Starknet in a high-stakes environment.

In the *Mainnet Preview* Lords will be taking residence in their owned Realm, surveying surrounding geography,  directing their economy, military and diplomacy efforts - and seeking to make their mark. $Lords will flow around the economy and [the Lordship Protocol.](https://realms.world/blogs/the-lordship-protocol)

So please consider OktoberTest as the best way to prepare yourself for the mercurial brutality of Eternum mainnet.

## **OktoberTest Schedule** 

We will post weekly schedules and pop up play sessions here and in the discord.  

Events will include game design briefings and social play sessions.  There will be challenges and rewards, and undoubtedly the astute Lords will be seeking alpha to carry into the Mainnet Preview. 

Most events take place in Discord. It’s OktoberTest, so please bring your own stein, ml. 

## **Play Eternum**

You can play the game in your browser [here](https://alpha-eternum.realms.world/) - desktop needed for current build.

[Join the community](https://discord.gg/realmsworld) and head to the Eternum channel.

Read about Eternum in the [World Guide](https://github.com/BibliothecaDAO/world-guide/blob/main/realms-world-guide-v1.0.0.pdf).

Follow the [new X profile](https://x.com/RealmsEternum) for Eternum alpha.\
\
 **Release notes**
2 changes: 1 addition & 1 deletion apps/nextjs/content/games/realms-eternum.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ screenshots:
- screenshots/2.png
- screenshots/3.png
links:
homepage: https://eternum.realms.world/
homepage: https://alpha-eternum.realms.world/
discord: https://discord.gg/uQnjZhZPfu
twitter: https://twitter.com/LootRealms
github: https://github.com/BibliothecaDAO/eternum
Expand Down
6 changes: 6 additions & 0 deletions apps/nextjs/keystatic.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default config({
label: "Games",
slugField: "title",
path: "content/games/*",
previewUrl: `/preview/start?branch={branch}&to=/games/{slug}`,
format: { contentField: "content" },
columns: ["title", "icon"],
schema: {
Expand Down Expand Up @@ -162,6 +163,7 @@ export default config({
slugField: "title",
path: "content/blogs/*",
format: { contentField: "content" },
previewUrl: `/preview/start?branch={branch}&to=/blogs/{slug}`,
columns: ["title", "subtitle"],
schema: {
author: fields.text({ label: "Author" }),
Expand All @@ -171,6 +173,10 @@ export default config({
label: "Banner Image",
directory: "public/content/blogs",
}),
previewImage: fields.image({
label: "Preview Image",
directory: "public/content/blogs",
}),
subtitle: fields.text({ label: "Subtitle" }),
content: fields.markdoc({
label: "Content",
Expand Down
2 changes: 1 addition & 1 deletion apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@avnu/avnu-sdk": "^2.1.1",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@keystatic/core": "^0.5.30",
"@keystatic/core": "^0.5.36",
"@keystatic/next": "^5.0.1",
"@markdoc/markdoc": "^0.4.0",
"@mdx-js/loader": "^3.0.1",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 31 additions & 23 deletions apps/nextjs/src/app/(app)/blogs/BlogCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,37 @@ import { Badge } from "@realms-world/ui/components/ui/badge";
import { Card } from "@realms-world/ui/components/ui/card";
import type { CollectionEntry } from "@/utils/keystatic";

export const BlogCard = ({
blog,
slug,
}: {
blog: CollectionEntry<"blogs">;
slug: string;
}) => {
return (
<Card>
<Link href={`/blogs/${slug}`} className="flex flex-col">
<Image
className="min-h-[400px] w-full rounded-l object-cover"
src={`/content/blogs/${slug}/${blog.previewImage ?? blog.image}`}
width={500}
height={500}
alt={blog.title}
/>
<div className="align-center p-4">
<Badge>
{" "}
<time dateTime={blog?.publishDate || ""}>
{new Date(blog?.publishDate || "").toLocaleDateString()}
</time>
</Badge>

export const BlogCard = ({ blog, slug }: { blog: CollectionEntry<'blogs'>, slug: string }) => {
return (
<Card>
<Link href={`/blogs/${slug}`} className="flex flex-col">
<Image
className="min-h-[400px] w-full rounded-l object-cover"
src={`/content/blogs/${slug}/${blog.image}`}
width={500}
height={500}
alt={blog.title}
/>
<div className="align-center p-4">
<Badge> <time dateTime={blog?.publishDate || ''}>
{new Date(blog?.publishDate || '').toLocaleDateString()}
</time></Badge>

<h4 className="my-4 text-2xl">{blog.title}</h4>
<p>{blog.subtitle}</p>
</div>
</Link>
</Card>
);
<h4 className="my-4 text-2xl">{blog.title}</h4>
<p>{blog.subtitle}</p>
</div>
</Link>
</Card>
);
};

export default BlogCard;
export default BlogCard;
2 changes: 1 addition & 1 deletion apps/nextjs/src/app/(app)/blogs/BlogGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BlogCard } from "./BlogCard";
import { reader } from "@/utils/keystatic";

export const BlogGrid = async () => {
const blogs = await reader.collections.blogs.all();
const blogs = await reader().collections.blogs.all();
const blogsSortedByDate = blogs.sort(function (a, b) {
// Turn your strings into dates, and then subtract them
// to get a value that is either negative, positive, or zero.
Expand Down
6 changes: 3 additions & 3 deletions apps/nextjs/src/app/(app)/blogs/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export async function generateMetadata({
}: {
params: { slug: string };
}): Promise<Metadata> {
let blog = await reader.collections.blogs.read(params.slug);
let blog = await reader().collections.blogs.read(params.slug);

return {
title: `${blog?.title}`,
Expand Down Expand Up @@ -46,7 +46,7 @@ export async function generateMetadata({
}

export default async function Page({ params }: { params: { slug: string } }) {
const blog = await reader.collections.blogs.read(params.slug);
const blog = await reader().collections.blogs.read(params.slug);
if (!blog) {
return <div>No Blog Found</div>;
}
Expand Down Expand Up @@ -111,6 +111,6 @@ export default async function Page({ params }: { params: { slug: string } }) {
}

export async function generateStaticParams() {
const blogSlugs = await reader.collections.blogs.list();
const blogSlugs = await reader().collections.blogs.list();
return blogSlugs.map((blogSlug) => ({ slug: blogSlug }));
}
46 changes: 25 additions & 21 deletions apps/nextjs/src/app/(app)/events/EventGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@

import { EventCard } from "./EventCard";
import { reader } from "@/utils/keystatic";


interface EventGridProps {
isHomepage?: boolean;
}

export const EventGrid = async ({ isHomepage }: EventGridProps) => {
const currentDate = new Date();
const events = await reader.collections.events.all();
const events = await reader().collections.events.all();

const upcomingEvents = events.filter(event => event.entry.startDate && new Date(event.entry.startDate) > currentDate);
const pastEvents = events.filter(event => event.entry.endDate && new Date(event.entry.endDate) < currentDate);
const upcomingEvents = events.filter(
(event) =>
event.entry.startDate && new Date(event.entry.startDate) > currentDate,
);
const pastEvents = events.filter(
(event) =>
event.entry.endDate && new Date(event.entry.endDate) < currentDate,
);

return (
<div>
{
upcomingEvents.length
?
<div className="mb-4">
<h2 className="text-xl font-bold mb-2">Upcoming Events</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-4">
{upcomingEvents.map((event, index) => (
<EventCard key={index} event={event.entry} slug={event.slug} />
))}
</div>
</div>
:
<div className="mb-4">
<h2 className="text-xl font-bold mb-2">Check back soon for upcoming events!</h2>
{upcomingEvents.length ? (
<div className="mb-4">
<h2 className="mb-2 text-xl font-bold">Upcoming Events</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-4">
{upcomingEvents.map((event, index) => (
<EventCard key={index} event={event.entry} slug={event.slug} />
))}
</div>
}
</div>
) : (
<div className="mb-4">
<h2 className="mb-2 text-xl font-bold">
Check back soon for upcoming events!
</h2>
</div>
)}
{!isHomepage && (
<div>
<h2 className="text-xl font-bold mb-2">Past Events</h2>
<h2 className="mb-2 text-xl font-bold">Past Events</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-4">
{pastEvents.map((event, index) => (
<EventCard key={index} event={event.entry} slug={event.slug} />
Expand Down
26 changes: 13 additions & 13 deletions apps/nextjs/src/app/(app)/events/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,28 @@ import Markdoc from "@markdoc/markdoc";
import { Button } from "@realms-world/ui/components/ui/button";
import { reader } from "@/utils/keystatic";


export async function generateMetadata({
params,
}: {
params: { slug: string };
}): Promise<Metadata> {
let event = await reader.collections.events.read(params.slug);
let event = await reader().collections.events.read(params.slug);
return {
title: `${event?.name}`,
description: `${params.slug} - Created for Adventurers by Bibliotheca DAO`,
};
}


export default async function Page({ params }: { params: { slug: string } }) {
const event = await reader.collections.events.read(params.slug);
const event = await reader().collections.events.read(params.slug);
if (!event) {
return <div>No Event Found</div>;
}
const { node } = await event.content();
const errors = Markdoc.validate(node);
if (errors.length) {
console.error(errors);
throw new Error('Invalid content');
throw new Error("Invalid content");
}
const renderable = Markdoc.transform(node);
return (
Expand All @@ -45,13 +43,16 @@ export default async function Page({ params }: { params: { slug: string } }) {
/>
)}
<div className="py-4">
<span className={`rounded border px-2 py-1 `}>
{new Date(event?.startDate || '').toLocaleDateString()} to {new Date(event?.endDate || '').toLocaleDateString()}
<span className={`rounded border px-2 py-1`}>
{new Date(event?.startDate || "").toLocaleDateString()} to{" "}
{new Date(event?.endDate || "").toLocaleDateString()}
</span>
</div>

<div className="text-lg">{event.description}</div>
<div className="prose prose-lg mx-auto mt-6 max-w-5xl px-6 pb-6 text-xl prose-headings:text-bright-yellow prose-p:font-thin prose-p:text-bright-yellow prose-a:text-flamingo prose-strong:text-bright-yellow prose-ul:text-bright-yellow md:mt-12"> {Markdoc.renderers.react(renderable, React)}
<div className="prose prose-lg mx-auto mt-6 max-w-5xl px-6 pb-6 text-xl prose-headings:text-bright-yellow prose-p:font-thin prose-p:text-bright-yellow prose-a:text-flamingo prose-strong:text-bright-yellow prose-ul:text-bright-yellow md:mt-12">
{" "}
{Markdoc.renderers.react(renderable, React)}
</div>
<hr className="my-8" />
<Button asChild>
Expand All @@ -61,9 +62,8 @@ export default async function Page({ params }: { params: { slug: string } }) {
);
}


export async function generateStaticParams() {
const eventSlugs = await reader.collections.events.list()
console.log(eventSlugs)
return eventSlugs.map((eventSlug) => ({ slug: eventSlug }))
}
const eventSlugs = await reader().collections.events.list();
console.log(eventSlugs);
return eventSlugs.map((eventSlug) => ({ slug: eventSlug }));
}
8 changes: 4 additions & 4 deletions apps/nextjs/src/app/(app)/games/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ export async function generateMetadata({
}: {
params: { slug: string };
}): Promise<Metadata> {
let game = await reader.collections.games.read(params.slug);
let game = await reader().collections.games.read(params.slug);
return {
title: `${game?.title}`,
description: `${params.slug} - Created for Adventurers by Bibliotheca DAO`,
};
}

export default async function Page({ params }: { params: { slug: string } }) {
const keyStaticGame = await reader.collections.games.read(params.slug);
const keyStaticGame = await reader().collections.games.read(params.slug);

if (!keyStaticGame) return;
const { node } = await keyStaticGame.content();
Expand All @@ -60,7 +60,7 @@ export default async function Page({ params }: { params: { slug: string } }) {
}));

// grab studio via developer slug from game so we can spit out the studio's title instead of its slug
const studio = await reader.collections.studios.read(
const studio = await reader().collections.studios.read(
keyStaticGame?.developer || "",
);

Expand Down Expand Up @@ -324,6 +324,6 @@ export default async function Page({ params }: { params: { slug: string } }) {
}

export async function generateStaticParams() {
const gameSlugs = await reader.collections.games.list();
const gameSlugs = await reader().collections.games.list();
return gameSlugs.map((gameSlug) => ({ slug: gameSlug }));
}
9 changes: 8 additions & 1 deletion apps/nextjs/src/app/(app)/games/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ export const metadata: Metadata = {
};

export default async function Page() {
const games = await reader.collections.games.all();
const allGames = await reader().collections.games.all();

const games = allGames.sort((a, b) => {
if (a.slug === "realms-eternum") return -1;
if (b.slug === "realms-eternum") return 1;
return 0;
});

return (
<PageLayout title="Onchain Games">
<div className="mt-8 grid grid-cols-1 gap-4 px-4 sm:px-8 md:grid-cols-2 lg:grid-cols-3">
Expand Down
Loading
Loading