mirror of
https://github.com/urbit/developers.urbit.org.git
synced 2024-09-11 21:57:16 +03:00
guides: add lib, renders, index pages for guides section
This commit is contained in:
parent
66062c2f66
commit
7150949f15
3
content/guides/_index.md
Normal file
3
content/guides/_index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
+++
|
||||||
|
title = "Guides"
|
||||||
|
+++
|
5
content/guides/additional/_index.md
Normal file
5
content/guides/additional/_index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
+++
|
||||||
|
title = "Additional Guides"
|
||||||
|
weight = 3
|
||||||
|
type = "tab"
|
||||||
|
+++
|
5
content/guides/core/_index.md
Normal file
5
content/guides/core/_index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
+++
|
||||||
|
title = "Core Curriculum"
|
||||||
|
weight = 2
|
||||||
|
type = "tab"
|
||||||
|
+++
|
4
content/guides/quickstart/_index.md
Normal file
4
content/guides/quickstart/_index.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
+++
|
||||||
|
title = "Quickstart"
|
||||||
|
weight = 1
|
||||||
|
+++
|
20
lib/lib.js
20
lib/lib.js
@ -135,3 +135,23 @@ export function getPreviousPost(slug, fields = [], key, sort = "date") {
|
|||||||
});
|
});
|
||||||
return resultPost;
|
return resultPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getPage = (path) => {
|
||||||
|
try {
|
||||||
|
let fileContents = fs.readFileSync(`${path}.md`, "utf8");
|
||||||
|
if (fileContents) {
|
||||||
|
const { data, content } = matter(fileContents, options);
|
||||||
|
return { data, content };
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
let fileContents = fs.readFileSync(`${path}/_index.md`, "utf8");
|
||||||
|
if (fileContents) {
|
||||||
|
const { data, content } = matter(fileContents, options);
|
||||||
|
return { data, content };
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
console.error("no md file for slug");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
325
pages/guides/[[...slug]].js
Normal file
325
pages/guides/[[...slug]].js
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
import Head from "next/head";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import classnames from "classnames";
|
||||||
|
import Meta from "../../components/Meta";
|
||||||
|
import Header from "../../components/Header";
|
||||||
|
import Footer from "../../components/Footer";
|
||||||
|
import Card from "../../components/Card";
|
||||||
|
import ContentArea from "../../components/ContentArea";
|
||||||
|
import Sidebar from "../../components/Sidebar";
|
||||||
|
import TallCard from "../../components/TallCard";
|
||||||
|
import Pagination from "../../components/Pagination";
|
||||||
|
import {
|
||||||
|
Container,
|
||||||
|
Section,
|
||||||
|
SingleColumn,
|
||||||
|
TwoUp,
|
||||||
|
Markdown,
|
||||||
|
} from "foundation-design-system";
|
||||||
|
import { Comms, MintFiller } from "../../components/icons";
|
||||||
|
import guidesTree from "../../cache/guides.json";
|
||||||
|
import { join } from "path";
|
||||||
|
import { getPage, getPreviousPost, getNextPost } from "../../lib/lib";
|
||||||
|
|
||||||
|
export default function GuidePage({
|
||||||
|
search,
|
||||||
|
posts,
|
||||||
|
data,
|
||||||
|
markdown,
|
||||||
|
params,
|
||||||
|
previousPost,
|
||||||
|
nextPost,
|
||||||
|
}) {
|
||||||
|
if (!params.slug) {
|
||||||
|
return <Landing search={search} />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>{data.title} • Guides • developers.urbit.org</title>
|
||||||
|
{Meta(data)}
|
||||||
|
</Head>
|
||||||
|
<div className="flex h-screen min-h-screen w-screen sidebar">
|
||||||
|
<Sidebar search={search}>
|
||||||
|
{childPages("/guides", posts.children)}
|
||||||
|
</Sidebar>
|
||||||
|
<ContentArea
|
||||||
|
breadcrumbs={breadcrumbs(posts, params.slug?.slice(0, -1) || "")}
|
||||||
|
title={data.title}
|
||||||
|
search={search}
|
||||||
|
section="Guides"
|
||||||
|
params={params}
|
||||||
|
>
|
||||||
|
<div className="markdown technical">
|
||||||
|
<Markdown.render content={JSON.parse(markdown)} />
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between mt-16">
|
||||||
|
{previousPost === null ? (
|
||||||
|
<div className={""} />
|
||||||
|
) : (
|
||||||
|
<Pagination
|
||||||
|
previous
|
||||||
|
title="Previous Post"
|
||||||
|
post={previousPost}
|
||||||
|
className=""
|
||||||
|
section={join("guides", params.slug?.slice(0, -1).join("/"))}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{nextPost === null ? (
|
||||||
|
<div className={""} />
|
||||||
|
) : (
|
||||||
|
<Pagination
|
||||||
|
next
|
||||||
|
title="Next Post"
|
||||||
|
post={nextPost}
|
||||||
|
className=""
|
||||||
|
section={join("guides", params.slug?.slice(0, -1).join("/"))}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
className="font-semibold rounded-xl block p-2 text-wall-400 hover:text-green-400 mt-16"
|
||||||
|
target="_blank"
|
||||||
|
href={`https://github.com/urbit/developers.urbit.org/blob/master/content/docs/${
|
||||||
|
params.slug?.join("/") || "_index"
|
||||||
|
}.md`}
|
||||||
|
>
|
||||||
|
Edit this page on GitHub
|
||||||
|
</a>
|
||||||
|
</ContentArea>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const breadcrumbs = (posts, paths) => {
|
||||||
|
const results = [<Link href="/">Guides</Link>];
|
||||||
|
let thisLink = "/guides";
|
||||||
|
for (const path of paths) {
|
||||||
|
posts = posts.children[path];
|
||||||
|
thisLink = join(thisLink, path);
|
||||||
|
results.push(
|
||||||
|
<span className="px-1">/</span>,
|
||||||
|
<Link href={thisLink}>{posts.title}</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
const childPages = (thisLink, children, level = 0) => (
|
||||||
|
<ul className="pl-0">
|
||||||
|
{Object.entries(children).map(([childSlug, child]) => (
|
||||||
|
<li>{pageTree(join(thisLink, childSlug), child, level)}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
|
||||||
|
const pageTree = (thisLink, tree, level = 0) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const firstCrumb = "/" + router.asPath.split("/").slice(1, -1).join("/");
|
||||||
|
|
||||||
|
const includesThisPage = firstCrumb.includes(thisLink);
|
||||||
|
const isThisPage = router.asPath === thisLink;
|
||||||
|
const [isOpen, toggleTree] = useState(includesThisPage);
|
||||||
|
|
||||||
|
const activeClasses = classnames({
|
||||||
|
hidden: !isOpen,
|
||||||
|
});
|
||||||
|
|
||||||
|
const headingItemClasses = classnames({
|
||||||
|
"pl-0 text-wall-600 text-base font-semibold hover:text-green-400 leading-relaxed":
|
||||||
|
level === 0,
|
||||||
|
"pl-4 text-wall-600 text-base font-semibold hover:text-green-400":
|
||||||
|
level === 1,
|
||||||
|
"pl-8 text-wall-600 text-base hover:text-green-400": level === 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
const pageItemClasses = classnames({
|
||||||
|
"pl-4 text-base hover:text-green-400": level === 0,
|
||||||
|
"pl-8 text-base hover:text-green-400": level === 1,
|
||||||
|
"pl-12 text-base hover:text-green-400": level === 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (tree?.type === "tab") {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p className="text-xs uppercase font-semibold text-wall-400 mt-4">
|
||||||
|
{tree.title}
|
||||||
|
</p>
|
||||||
|
{childPages(thisLink, tree.children, level)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span onClick={() => toggleTree(!isOpen)}>
|
||||||
|
<p className={`${headingItemClasses} cursor-pointer`}>{tree.title}</p>
|
||||||
|
</span>
|
||||||
|
<div className={activeClasses}>
|
||||||
|
<ul className={""}>
|
||||||
|
{tree.pages.map(({ title, slug }) => {
|
||||||
|
const href = join(thisLink, slug);
|
||||||
|
const isSelected = router.asPath === href;
|
||||||
|
const selectedClasses = classnames({
|
||||||
|
dot: isSelected,
|
||||||
|
"text-green-400": isSelected,
|
||||||
|
"text-wall-600": !isSelected,
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<Link href={href} passHref>
|
||||||
|
<a
|
||||||
|
className={`relative inline-block ${selectedClasses} ${pageItemClasses} `}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
{childPages(thisLink, tree.children, level + 1)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function Landing({ search }) {
|
||||||
|
const post = {
|
||||||
|
title: "Guides",
|
||||||
|
description:
|
||||||
|
"Everything you need to know to start building applications on Urbit.",
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Head>
|
||||||
|
<title>Guides • developers.urbit.org</title>
|
||||||
|
{Meta(post)}
|
||||||
|
</Head>
|
||||||
|
<Header search={search} />
|
||||||
|
<SingleColumn>
|
||||||
|
<Section>
|
||||||
|
<h1>Guides</h1>
|
||||||
|
</Section>
|
||||||
|
<Section short>
|
||||||
|
<h3 className="pt-12">Quickstart: Lightning Tutorials</h3>
|
||||||
|
<p className="pt-4">
|
||||||
|
Build an application on Urbit in 15 minutes with these instant
|
||||||
|
application guides.
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col space-y-8 md:space-y-0 md:flex-row md:space-x-8 pt-12">
|
||||||
|
<Card
|
||||||
|
icon={<Comms />}
|
||||||
|
title="Encrypted Chat Application"
|
||||||
|
text="Build your own secure comms tool"
|
||||||
|
className="basis-1/2"
|
||||||
|
/>
|
||||||
|
<Card
|
||||||
|
icon={<MintFiller />}
|
||||||
|
title="Lorem Ipsum Dolorem"
|
||||||
|
text="Roll your own encrypted chat application in minutes"
|
||||||
|
className="basis-1/2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section short className="space-y-6">
|
||||||
|
<h3>Core Curriculum</h3>
|
||||||
|
<p>
|
||||||
|
The following guides will teach you everything you need to know to
|
||||||
|
start building applications on Urbit.
|
||||||
|
</p>
|
||||||
|
<TwoUp>
|
||||||
|
<TallCard
|
||||||
|
title="Environment Setup"
|
||||||
|
description="Learn how to get your urbit development environment configured"
|
||||||
|
callout="View Guide"
|
||||||
|
href="/guides/additional/development/environment"
|
||||||
|
image="/images/environment.svg"
|
||||||
|
className="h-full"
|
||||||
|
/>
|
||||||
|
<TallCard
|
||||||
|
title="Hoon School"
|
||||||
|
description="Learn the fundamentals of the Hoon programming language"
|
||||||
|
callout="View Guide"
|
||||||
|
href="/guides/core/hoon-school"
|
||||||
|
image="/images/hoon.svg"
|
||||||
|
className="h-full"
|
||||||
|
/>
|
||||||
|
</TwoUp>
|
||||||
|
<TwoUp className="!mt-0">
|
||||||
|
<TallCard
|
||||||
|
title="App School"
|
||||||
|
description="Learn how to build Urbit userspace applications by writing your own Gall agents"
|
||||||
|
callout="View Guide"
|
||||||
|
href="/guides/core/app-school"
|
||||||
|
image="/images/app.svg"
|
||||||
|
className="h-full"
|
||||||
|
/>
|
||||||
|
<TallCard
|
||||||
|
title="Full Stack Integration"
|
||||||
|
description="Learn how to create Gall agents and integrate them into a React front-end"
|
||||||
|
callout="View Guide"
|
||||||
|
href="/guides/core/app-school-full-stack"
|
||||||
|
image="/images/fullstack.svg"
|
||||||
|
className="h-full"
|
||||||
|
/>
|
||||||
|
</TwoUp>
|
||||||
|
</Section>
|
||||||
|
</SingleColumn>
|
||||||
|
<Footer />
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps({ params }) {
|
||||||
|
let posts = guidesTree;
|
||||||
|
|
||||||
|
const { data, content } = getPage(
|
||||||
|
join(process.cwd(), "content/guides", params.slug?.join("/") || "/")
|
||||||
|
);
|
||||||
|
|
||||||
|
const previousPost =
|
||||||
|
getPreviousPost(
|
||||||
|
params.slug?.slice(-1).join("") || "guides",
|
||||||
|
["title", "slug", "weight"],
|
||||||
|
join("guides", params.slug?.slice(0, -1).join("/") || "/"),
|
||||||
|
"weight"
|
||||||
|
) || null;
|
||||||
|
|
||||||
|
const nextPost =
|
||||||
|
getNextPost(
|
||||||
|
params.slug?.slice(-1).join("") || "guides",
|
||||||
|
["title", "slug", "weight"],
|
||||||
|
join("guides", params.slug?.slice(0, -1).join("/") || "/"),
|
||||||
|
"weight"
|
||||||
|
) || null;
|
||||||
|
|
||||||
|
const markdown = JSON.stringify(Markdown.parse({ post: { content } }));
|
||||||
|
|
||||||
|
return { props: { posts, data, markdown, params, previousPost, nextPost } };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const posts = guidesTree;
|
||||||
|
const slugs = [];
|
||||||
|
|
||||||
|
const allHrefs = (thisLink, tree) => {
|
||||||
|
slugs.push(thisLink, ...tree.pages.map((e) => join(thisLink, e.slug)));
|
||||||
|
allHrefsChildren(thisLink, tree.children);
|
||||||
|
};
|
||||||
|
|
||||||
|
const allHrefsChildren = (thisLink, children) => {
|
||||||
|
Object.entries(children).map(([childSlug, child]) => {
|
||||||
|
allHrefs(join(thisLink, childSlug), child);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
allHrefs("/guides", posts);
|
||||||
|
return {
|
||||||
|
paths: slugs,
|
||||||
|
fallback: false,
|
||||||
|
};
|
||||||
|
}
|
@ -1,100 +0,0 @@
|
|||||||
import Head from "next/head";
|
|
||||||
import Meta from "../../components/Meta";
|
|
||||||
import Header from "../../components/Header";
|
|
||||||
import Footer from "../../components/Footer";
|
|
||||||
import Card from "../../components/Card";
|
|
||||||
import TallCard from "../../components/TallCard";
|
|
||||||
import {
|
|
||||||
Container,
|
|
||||||
Section,
|
|
||||||
SingleColumn,
|
|
||||||
TwoUp,
|
|
||||||
} from "foundation-design-system";
|
|
||||||
import { Comms, MintFiller } from "../../components/icons";
|
|
||||||
|
|
||||||
export default function GuidePage({ search }) {
|
|
||||||
const post = {
|
|
||||||
title: "Guides",
|
|
||||||
description:
|
|
||||||
"Everything you need to know to start building applications on Urbit.",
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<Head>
|
|
||||||
<title>Guides • developers.urbit.org</title>
|
|
||||||
{Meta(post)}
|
|
||||||
</Head>
|
|
||||||
<Header search={search} />
|
|
||||||
<SingleColumn>
|
|
||||||
<Section>
|
|
||||||
<h1>Guides</h1>
|
|
||||||
</Section>
|
|
||||||
<Section short>
|
|
||||||
<h3 className="pt-12">Quickstart: Lightning Tutorials</h3>
|
|
||||||
<p className="pt-4">
|
|
||||||
Build an application on Urbit in 15 minutes with these instant
|
|
||||||
application guides.
|
|
||||||
</p>
|
|
||||||
<div className="flex flex-col space-y-8 md:space-y-0 md:flex-row md:space-x-8 pt-12">
|
|
||||||
<Card
|
|
||||||
icon={<Comms />}
|
|
||||||
title="Encrypted Chat Application"
|
|
||||||
text="Build your own secure comms tool"
|
|
||||||
className="basis-1/2"
|
|
||||||
/>
|
|
||||||
<Card
|
|
||||||
icon={<MintFiller />}
|
|
||||||
title="Lorem Ipsum Dolorem"
|
|
||||||
text="Roll your own encrypted chat application in minutes"
|
|
||||||
className="basis-1/2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Section>
|
|
||||||
<Section short className="space-y-6">
|
|
||||||
<h3>Core Curriculum</h3>
|
|
||||||
<p>
|
|
||||||
The following guides will teach you everything you need to know to
|
|
||||||
start building applications on Urbit.
|
|
||||||
</p>
|
|
||||||
<TwoUp>
|
|
||||||
<TallCard
|
|
||||||
title="Environment Setup"
|
|
||||||
description="Learn how to get your urbit development environment configured"
|
|
||||||
callout="View Guide"
|
|
||||||
href="/guides/environment-setup"
|
|
||||||
image="/images/environment.svg"
|
|
||||||
className="h-full"
|
|
||||||
/>
|
|
||||||
<TallCard
|
|
||||||
title="Hoon School"
|
|
||||||
description="Learn the fundamentals of the Hoon programming language"
|
|
||||||
callout="View Guide"
|
|
||||||
href="/guides/hoon-school"
|
|
||||||
image="/images/hoon.svg"
|
|
||||||
className="h-full"
|
|
||||||
/>
|
|
||||||
</TwoUp>
|
|
||||||
<TwoUp className="!mt-0">
|
|
||||||
<TallCard
|
|
||||||
title="App School"
|
|
||||||
description="Learn how to build Urbit userspace applications by writing your own Gall agents"
|
|
||||||
callout="View Guide"
|
|
||||||
href="/guides/app-school"
|
|
||||||
image="/images/app.svg"
|
|
||||||
className="h-full"
|
|
||||||
/>
|
|
||||||
<TallCard
|
|
||||||
title="Full Stack Integration"
|
|
||||||
description="Learn how to create Gall agents and integrate them into a React front-end"
|
|
||||||
callout="View Guide"
|
|
||||||
href="/guides/full-stack"
|
|
||||||
image="/images/fullstack.svg"
|
|
||||||
className="h-full"
|
|
||||||
/>
|
|
||||||
</TwoUp>
|
|
||||||
</Section>
|
|
||||||
</SingleColumn>
|
|
||||||
<Footer />
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user