@@ -0,0 +1,314 @@
1+import Head from "next/head";
2+import Link from "next/link";
3+import { useRouter } from "next/router";
4+import classnames from "classnames";
5+import React from "react";
6+import { DateTime } from "luxon";
7+import {
8+ Container,
9+ Section,
10+ SingleColumn,
11+ TwoUp,
12+ IntraNav,
13+ getAllPosts,
14+ generateRealtimeDate,
15+ getPage,
16+ Markdown,
17+ getPreviousPost,
18+ getNextPost,
19+} from "@urbit/foundation-design-system";
20+import { getAllEvents } from "../../lib/lib";
21+import { join } from 'path';
22+import Header from "../../components/Header";
23+import Footer from "../../components/Footer";
24+import Contact from "../../components/Contact";
25+import PostPreview from "../../components/PostPreview";
26+import EventPreview from "../../components/EventPreview";
27+import Sidebar from "../../components/Sidebar";
28+import { eventKeys } from "../../lib/constants";
29+import IndexCard from "../../components/ecosystem/IndexCard";
30+import HighlightCard from "../../components/HighlightCard";
31+import fs from "fs";
32+import path from "path";
33+import Meta from "../../components/Meta";
34+import campusTree from "../../cache/campus.json";
35+import { matchEcosystemPost } from "../../lib/lib";
36+
37+export default function Home({
38+ posts,
39+ highlights,
40+ ecosystem,
41+ events,
42+ grantNumbers,
43+ search,
44+ data,
45+ markdown,
46+}) {
47+ const post = {
48+ title: "Urbit",
49+ description: "A clean-slate OS and network for the 21st century.",
50+ image: "https://storage.googleapis.com/media.urbit.org/site/opengraph/urbit.png"
51+ };
52+ return (
53+ <Container>
54+ <Head>
55+ <title>Urbit</title>
56+ {Meta(post, false, true)}
57+ </Head>
58+ <IntraNav ourSite="https://urbit.org" search={search} />
59+
60+ <SingleColumn>
61+ <Header search={search} />
62+
63+ {/* Hero statement */}
64+ <Section className="pb-6">
65+ <div className="flex flex-col space-y-4">
66+ <h1 className="max-w-prose">
67+ Campus Outreach Program
68+ </h1>
69+ <h3 className="">
70+ Leave your mark on the future. Build on Urbit.
71+ </h3>
72+ </div>
73+ </Section>
74+
75+
76+
77+ {/* Brief explanatory paragraph */}
78+ <Section className="sm:flex sm:space-x-8 space-y-8 sm:space-y-0">
79+
80+ <div className="sm:w-2/3 space-y-8">
81+ <div className="space-y-4">
82+ <p className="type-ui">
83+ For those with the will to think outside the box: a complete reimagining of networked computing from the OS up, designed to facilitate the construction
84+ of powerful, enduring, and decentralized systems.
85+ </p>
86+ <p className="type-ui">
87+ The Urbit Foundation’s Campus Outreach Program aims to find ambitious students interested in leaving the old
88+ world behind and providing them with the information and resources to help build a better future.
89+ If you fit that description and want us to come to your university,{" "}
90+ <Link href="/campus#contact" passHref>
91+ <a>get in touch.</a>
92+ </Link>{" "}
93+ </p>
94+ </div>
95+
96+ </div>
97+
98+ <div className="sm:w-1/3">
99+
100+ <Link href="https://airtable.com/shrmfUVpMskWw145u" passHref>
101+ <a className="button-lg bg-green-400 text-white type-ui max-w-fit">
102+ Get on Urbit
103+ </a>
104+ </Link>
105+
106+ </div>
107+ </Section>
108+
109+ {/*
110+ how to make an in-page link (href to hashtag element id)
111+ <a href="#events"> cheebo </a>
112+ */}
113+
114+
115+
116+ {
117+ //funnel, repurposed from /overview page:
118+ }
119+ <div id="reading"></div>
120+
121+ <Section>
122+
123+ <h2 className="pb-16">Learn about Urbit for</h2>
124+
125+ <div className="flex justify-between sidebar md:space-x-8">
126+ <Sidebar search={search}>
127+ {childPages("/campus", posts.pages)}
128+ </Sidebar>
129+ <div className={'markdown max-w-prose ' + data.slug }>
130+ <Markdown.render content={JSON.parse(markdown)} />
131+ </div>
132+ </div>
133+ </Section>
134+
135+
136+
137+ {
138+ //Events
139+ }
140+
141+ <Section className="pb-1">
142+
143+ <br></br>
144+ <div className="mt-6">
145+ <h2 className="mb-8" id="events">Events</h2>
146+ {events.length > 0 ? (
147+ <TwoUp>
148+ <EventPreview event={events[0]} className="mb-8" />
149+ {events[1] ? <EventPreview event={events[1]} className="mb-8" /> : <div />}
150+ </TwoUp>
151+ ) : (
152+ <p className="pb-8">No events yet — check back later.</p>
153+ )}
154+ <Link href="/events?tag=campus">
155+ <a className="bg-wall-600 text-white button-lg w-fit">
156+ View All
157+ </a>
158+ </Link>
159+ </div>
160+ </Section>
161+
162+ <div id="contact"></div>
163+
164+ <Section className="pb-12">
165+
166+ <div className="bg-wall-100 w-full p-4 md:p-8 rounded-3xl flex flex-wrap items-center">
167+
168+ <div className="sm:pl-2 align-middle">
169+ <h2 className=" text-2xl pb-2" >Get in touch</h2 >
170+ <p className="max-w-prose pb-4">
171+ Not sure how to get started after attending an event? Want to schedule one at your university?
172+ Don't be a stranger. Reach out at the email below, or{" "}
173+ <Link href="https://urbit.org/groups/~tidren-nosryg/campus-outreach" passHref>
174+ <a>find us on Urbit.</a>
175+ </Link>{" "}
176+ </p>
177+ <Link href="mailto:campus@urbit.org">
178+ <a className="button-sm border-2 border-wall-600 text-wall-600 type-sm max-w-fit">
179+ campus@urbit.org
180+ </a>
181+ </Link>
182+ </div>
183+ </div>
184+ </Section>
185+
186+
187+
188+
189+ </SingleColumn>
190+
191+
192+
193+ <Footer />
194+ </Container>
195+ );
196+}
197+
198+const childPages = (thisLink, children, level = 0) => {
199+ const router = useRouter();
200+
201+ const isThisPage = router.asPath === thisLink || router.asPath === `${thisLink}#reading`;
202+
203+ const pageItemClasses = classnames({
204+ "text-base type-ui": level === 0,
205+ "text-wall-400": !isThisPage,
206+ "text-black": isThisPage,
207+ });
208+ return (
209+ <ul className="">
210+ <li className="pb-2">
211+ <Link href="/campus#reading">
212+ <a className={`${pageItemClasses} cursor-pointer`}>Software Developers</a>
213+ </Link>
214+ </li>
215+ {children?.map((child) => (
216+ <li className="pb-2">
217+ {pageTree(join(thisLink, child.slug), child, level)}
218+ </li>
219+ ))}
220+ </ul>
221+ );
222+};
223+
224+const pageTree = (thisLink, tree, level = 0) => {
225+ const router = useRouter();
226+
227+
228+ const isThisPage = router.asPath.includes(thisLink);
229+
230+ const pageItemClasses = classnames({
231+ "text-base type-ui": level === 0,
232+ "text-wall-400": !isThisPage,
233+ "text-black": isThisPage,
234+ });
235+
236+ return (
237+ <>
238+ <Link href={thisLink + "#reading"}>
239+ <a className={`${pageItemClasses} cursor-pointer`}>{tree.title}</a>
240+ </Link>
241+ </>
242+ );
243+};
244+
245+export async function getStaticPaths() {
246+ const posts = campusTree;
247+
248+ const slugs = [];
249+
250+ const allHrefs = (thisLink, tree) => {
251+ slugs.push(thisLink, ...tree.pages.map((e) => join(thisLink, e.slug)));
252+ allHrefsChildren(thisLink, tree.children);
253+ };
254+
255+ const allHrefsChildren = (thisLink, children) => {
256+ Object.entries(children).map(([childSlug, child]) => {
257+ allHrefs(join(thisLink, childSlug), child);
258+ });
259+ };
260+
261+ allHrefs("/campus", posts);
262+
263+ return {
264+ paths: slugs,
265+ fallback: false,
266+ };
267+}
268+
269+export async function getStaticProps({ params }) {
270+ const posts = campusTree;
271+
272+ const { data, content } = getPage(
273+ join(process.cwd(), "content/campus", params.slug?.join("/") || "/")
274+ );
275+ const markdown = JSON.stringify(Markdown.parse({ post: { content } }));
276+
277+ const previousPost =
278+ getPreviousPost(
279+ params.slug?.slice(-1).join("") || "campus",
280+ ["title", "slug", "weight"],
281+ join("campus", params.slug?.slice(0, -1).join("/") || "/"),
282+ "weight"
283+ ) || null;
284+
285+ const nextPost =
286+ getNextPost(
287+ params.slug?.slice(-1).join("") || "campus",
288+ ["title", "slug", "weight"],
289+ join("campus", params.slug?.slice(0, -1).join("/") || "/"),
290+ "weight"
291+ ) || null;
292+
293+ const allEvents = getAllEvents(eventKeys, "events");
294+ const events = allEvents.filter((e) => e?.tags?.includes("campus")) || [];
295+
296+ return { props: { posts, data, markdown, params, previousPost, nextPost, events } };
297+}
298+
299+
300+
301+/* export async function getStaticProps() {
302+
303+
304+ const events = getAllEvents(eventKeys, "events").filter((e) => e?.tags?.includes("campus"));
305+
306+ // const { data, content } = getPage(join(process.cwd(), 'content', 'bitcoin'));
307+
308+ return {
309+ props: {
310+ events
311+ }
312+ }
313+}
314+ */