@@ -0,0 +1,136 @@
1+import Head from "next/head";
2+import Link from "next/link";
3+import { getPage } from "../../lib/lib";
4+import { join } from "path";
5+import Meta from "../../components/Meta";
6+import CopyLink from "../../components/CopyLink";
7+import Container from "../../components/Container";
8+import SingleColumn from "../../components/SingleColumn";
9+import ErrorPage from "../404";
10+import Section from "../../components/Section";
11+import ob from "urbit-ob";
12+import { decode } from "html-entities";
13+import Markdown from "../../components/Markdown";
15+const GroupPage = ({ data, markdown, params }) => {
16+ const { group } = params;
17+ if (!ob.isValidPatp(group[0])) {
18+ return <ErrorPage />;
24+ <title>{data.title} • Groups • urbit.org</title>
28+ <Section className="space-y-12" narrow>
29+ <div className="flex items-center space-x-4">
30+ {/* Group logo and fallback */}
33+ className="rounded-xl"
40+ className="object-contain shadow-sm rounded-xl"
41+ style={{ height: 100, width: 100 }}
42+ src="https://media.urbit.org/logo/urbit-logo-card.png"
45+ <div className="flex flex-col">
46+ <h2>{data.title}</h2>
50+ <div className="flex flex-col md:flex-row space-y-4 md:space-y-0 justify-between">
51+ <div className="flex flex-col">
52+ <p className="font-bold text-wall-400">Group Type</p>
53+ <p>{data.type ? data.type : "Unknown"}</p>
55+ <div className="flex flex-col">
56+ <p className="font-bold text-wall-400">Members</p>
58+ {data.participant_range ? data.participant_range : "Unknown"}
61+ <div className="flex flex-col">
62+ <p className="font-bold text-wall-400">Host</p>
63+ <Link href={`/id/${group[0]}`}>
64+ <a className="type-ui font-mono text-green-400">{group[0]}</a>
67+ <CopyLink content={data.shortcode ? data.shortcode : data.title} />
69+ {(data.description !== "A group on Urbit." || markdown) && (
70+ <div className="flex flex-col space-y-4">
71+ <p className="font-bold text-wall-400">Description</p>
74+ className="flex flex-col space-y-4"
75+ dangerouslySetInnerHTML={{ __html: decode(markdown) }}
78+ <p>{data.description}</p>
82+ <hr className="text-wall-200" />
83+ <div className="flex flex-col space-y-6">
85+ Urbit is a clean-slate, peer-to-peer operating system and network.
87+ <div className="flex flex-col space-y-4">
88+ <p className="text-sm font-semibold text-wall-400">
89+ Get on the network and join this group.
91+ {/* TODO: Joining groups guide. */}
92+ <button className="button-lg max-w-xs bg-green-400 text-white">
97+ <hr className="text-wall-200" />
98+ <div className="flex flex-col space-y-1">
99+ <p>Have a group you'd like to share publicly through urbit.org?</p>
100+ {/* TODO Submission guide. */}
101+ <p className="type-ui text-green-400">
102+ Learn how to submit your group.
106+ <a className="text-xl pt-8 block font-semibold">Urbit.org</a>
114+export const getServerSideProps = async ({ params }) => {
115+ let { data, content } = getPage(
116+ join(process.cwd(), "content/group", params.group?.join("/") || "/")
117+ ) || { data: {}, content: {} };
120+ data = { title: params.group?.join("/"), description: "A group on Urbit." };
123+ const markdown = content
124+ ? await Markdown({ post: { content: content } })
136+export default GroupPage;