@@ -6,7 +6,6 @@ import {
6 SingleColumn,
6 SingleColumn,
10 getAllPosts,
9 getAllPosts,
11 generateDisplayDate,
10 generateDisplayDate,
12 formatDate,
11 formatDate,
@@ -14,6 +13,7 @@ import {
14import Header from "../../components/Header";
13import Header from "../../components/Header";
15import Footer from "../../components/Footer";
14import Footer from "../../components/Footer";
16import Sidebar from "../../components/Sidebar";
15import Sidebar from "../../components/Sidebar";
16+import SpotlightArchive from "../../components/ecosystem/SpotlightArchive";
17import Post from "../../components/ecosystem/Post";
17import Post from "../../components/ecosystem/Post";
18import classnames from "classnames";
18import classnames from "classnames";
19import Link from "next/link";
19import Link from "next/link";
@@ -37,10 +37,15 @@ export default function Ecosystem({
38 const { type } = router.query;
38 const { type } = router.query;
40+ // Route ?type=archive to below component;
41+ // otherwise, show directory of ecosystem type
42+ // If no param, we show the spotlight for the month
40 if (type === "archive") {
43 if (type === "archive") {
41 return <SpotlightArchive posts={posts} search={search} />;
44 return <SpotlightArchive posts={posts} search={search} />;
47+ const spotlight = type === undefined;
44 let title;
49 let title;
45 if (type) {
50 if (type) {
46 switch (type) {
51 switch (type) {
@@ -92,21 +97,19 @@ export default function Ecosystem({
92 </Sidebar>
97 </Sidebar>
94 className={classnames("w-full", {
99 className={classnames("w-full", {
95− "max-w-prose": type === undefined,
100+ "max-w-prose": spotlight,
98− {type === undefined && (
103+ {/* Default layout */}
99− <h3>{`Ecosystem Spotlight - ${post.title}`}</h3>
104+ {spotlight && (
101− {type === undefined && (
106+ <h3>{`Ecosystem Spotlight - ${post.title}`}</h3>
103 <Post post={post} />
107 <Post post={post} />
104 <Link href="/ecosystem/?type=archive" passHref>
108 <Link href="/ecosystem/?type=archive" passHref>
105 <a className="button-lg bg-wall-600 text-white w-fit">
109 <a className="button-lg bg-wall-600 text-white w-fit">
106 Spotlight Archive
110 Spotlight Archive
110 <div className="pt-36">
113 <div className="pt-36">
111 <h3 className="pb-2">Urbit Monthly</h3>
114 <h3 className="pb-2">Urbit Monthly</h3>
112 <p className="pb-8">
115 <p className="pb-8">
@@ -117,124 +120,36 @@ export default function Ecosystem({
120−
123+ {/* Ecosystem type layouts */}
122 className={classnames("grid gap-12 w-full", {
125 className={classnames("grid gap-12 w-full", {
123 "grid-cols-2 md:grid-cols-3": type == "organizations" || type == "marketplaces",
126 "grid-cols-2 md:grid-cols-3": type == "organizations" || type == "marketplaces",
124 "grid-cols-1": type === "podcasts" || type === "articles",
127 "grid-cols-1": type === "podcasts" || type === "articles",
125 "grid-cols-1 md:grid-cols-1 lg:grid-cols-1 xl:grid-cols-2":
128 "grid-cols-1 md:grid-cols-1 lg:grid-cols-1 xl:grid-cols-2":
126 type === "applications" || type === "groups",
129 type === "applications" || type === "groups",
127− hidden: type === undefined,
130+ hidden: spotlight,
130 {type === "organizations" &&
133 {type === "organizations" &&
131− organizations.map((org) => (
132− <Link href={`/organizations/${org.slug}`}>
134+ <Organizations dir={organizations} />
133− <div className="flex flex-col space-y-4 items-center cursor-pointer hover:opacity-90">
134− <img className="w-36 rounded-xl" src={org.image} />
135− <p className="text-center font-bold">{org.title}</p>
140 {type === "applications" &&
137 {type === "applications" &&
141− applications.map((app) => (
138+ <Applications dir={applications} />
142− <Link href={`/applications/${app.ship}/${app.slug}`}>
143− <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
145− className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
147− backgroundColor: app?.bgColor || "rgba(0,0,0,0)",
152− className="items-center h-36 w-36"
158− <p className="text-left font-bold">{app.title}</p>
159− <p className="text-left text-wall-400 font-light">
166 {type === "groups" &&
140 {type === "groups" &&
167− groups.map((group) => (
141+ <Groups dir={groups} />
168− <Link href={`/groups/${group.ship}/${group.slug}`}>
169− <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
171− className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
173− backgroundColor: group?.tile?.startsWith("#")
178− {!group?.tile?.startsWith("#") && (
180− className="items-center h-36 w-36"
186− <p className="text-left font-bold">{group.title}</p>
187− <p className="text-left text-wall-400 font-light">
194 {type === "marketplaces" &&
143 {type === "marketplaces" &&
195− marketplaces.map((market) => (
196− <Link href={`/marketplaces/${market.slug}`}>
144+ <Marketplaces dir={marketplaces} />
197− <div className="flex flex-col space-y-4 justify-center items-center cursor-pointer hover:opacity-90">
198− <img className="w-36 rounded-xl" src={market.image} />
199− <p className="text-center font-bold">{market.title}</p>
203 {type === "podcasts" &&
146 {type === "podcasts" &&
204− podcasts.map((pod) => (
147+ <Podcasts dir={podcasts} />
205− <Link href={`/podcasts/${pod.slug}`}>
206− <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
207− <img className="w-28" src={pod.image} />
208− <div className="flex flex-col space-y-2 min-w-0">
209− <p className="font-bold">{pod.podcast}</p>
210− <p className="min-w-0 min-h-0 leading-5 ">
213− <p className="text-wall-400">
214− {formatDate(generateDisplayDate(pod.date))}
221 {type === "articles" &&
150 {type === "articles" &&
222− articles.map((article) => (
151+ <Articles dir={articles} />
223− <Link href={`/articles/${article.slug}`}>
224− <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
225− <img className="w-28" src={article.image} />
226− <div className="flex flex-col space-y-2 min-w-0">
227− <p className="font-bold">{article.publication}</p>
228− <p className="min-w-0 min-h-0 leading-5 ">
231− <p className="text-wall-400">
232− {formatDate(generateDisplayDate(article.date))}
@@ -245,149 +160,132 @@ export default function Ecosystem({
248−function ActiveLink({ children, href, className, currentPath }) {
163+const Organizations = ({ dir }) => {
249− // special casing this behaviour which overloads one nav
250− const archive = Boolean(
251− currentPath === "/ecosystem?type=archive" && href === "/ecosystem"
253− const activeClassName = classnames({
254− "text-wall-800": currentPath === href || archive,
255− "text-wall-400": currentPath !== href && !archive,
258− return (
164+ return dir.map((org) => (
259− <Link href={href} passHref>
165+ <Link href={`/organizations/${org.slug}`}>
260− <a className={`${className} ${activeClassName}`}>{children}</a>
166+ <div className="flex flex-col space-y-4 items-center cursor-pointer hover:opacity-90">
167+ <img className="w-36 rounded-xl" src={org.image} />
168+ <p className="text-center font-bold">{org.title}</p>
265−function EcosystemSidebar() {
174+const Applications = ({ dir }) => {
266− const router = useRouter();
267− let currentPath = router.asPath;
268− return (
175+ return dir.map((app) => (
176+ <Link href={`/applications/${app.ship}/${app.slug}`}>
269− <div className="flex flex-col space-y-4 pr-24">
177+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
270− <ActiveLink
178+ <div
271− currentPath={currentPath}
179+ className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
272− className="type-ui"
180+ style={{
273− href="/ecosystem"
181+ backgroundColor: app?.bgColor || "rgba(0,0,0,0)",
276− </ActiveLink>
184+ {app?.image && (
277− <ActiveLink
185+ <img
278− currentPath={currentPath}
280− href="/ecosystem?type=organizations"
285− currentPath={currentPath}
286− className="type-ui"
186+ className="items-center h-36 w-36"
287− href="/ecosystem?type=applications"
187+ src={app.image}
290− </ActiveLink>
190+ </div>
292− currentPath={currentPath}
293− className="type-ui"
191+ <div className="">
294− href="/ecosystem?type=groups"
192+ <p className="text-left font-bold">{app.title}</p>
295− >
193+ <p className="text-left text-wall-400 font-light">
296− Groups
194+ {app.description}
299− currentPath={currentPath}
301− href="/ecosystem?type=groups"
306− currentPath={currentPath}
307− className="mr-5 type-ui"
308− href="/ecosystem?type=podcasts"
311− </ActiveLink>
197+ </div>
313− <ActiveLink
202+const Groups = ({ dir }) => {
314− currentPath={currentPath}
203+ return dir.map((group) => (
315− className="mr-5 type-ui"
204+ <Link href={`/groups/${group.ship}/${group.slug}`}>
316− href="/ecosystem?type=articles"
205+ <div className="flex space-x-4 items-center cursor-pointer hover:opacity-90">
207+ className="h-36 w-36 rounded-xl items-center justify-center shrink-0 overflow-hidden"
209+ backgroundColor: group?.tile?.startsWith("#")
214+ {!group?.tile?.startsWith("#") && (
216+ className="items-center h-36 w-36"
222+ <p className="text-left font-bold">{group.title}</p>
223+ <p className="text-left text-wall-400 font-light">
319− </ActiveLink>
227+ </div>
232+const Marketplaces = ({ dir }) => {
233+ return dir.map((market) => (
234+ <Link href={`/marketplaces/${market.slug}`}>
235+ <div className="flex flex-col space-y-4 justify-center items-center cursor-pointer hover:opacity-90">
236+ <img className="w-36 rounded-xl" src={market.image} />
237+ <p className="text-center font-bold">{market.title}</p>
243+const Podcasts = ({ dir }) => {
244+ return dir.map((pod) => (
245+ <Link href={`/podcasts/${pod.slug}`}>
246+ <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
247+ <img className="w-28" src={pod.image} />
248+ <div className="flex flex-col space-y-2 min-w-0">
249+ <p className="font-bold">{pod.podcast}</p>
250+ <p className="min-w-0 min-h-0 leading-5 ">
253+ <p className="text-wall-400">
254+ {formatDate(generateDisplayDate(pod.date))}
326−function SpotlightArchive({ posts, search }) {
327− const post = {
262+const Articles = ({ dir }) => {
328− title: "Spotlight Archive",
263+ return dir.map((article) => (
329− description: "The archive of ecosystem spotlights.",
264+ <Link href={`/articles/${article.slug}`}>
334− <title>Archive • Spotlight • Urbit</title>
337− <IntraNav ourSite="https://urbit.org" search={search} />
339− <Header search={search} />
341− <div className="measure">
345− <Section className="flex">
347− <EcosystemSidebar />
350− <h3 className="mb-12">Spotlight Archive</h3>
351− {posts.map((post) => {
353− <div key={post.slug} className="mb-24 cursor-pointer">
265+ <div className="flex cursor-pointer space-x-4 items-center hover:opacity-90">
354− <Link href={`/ecosystem/spotlight/${post.slug}`}>
266+ <img className="w-28" src={article.image} />
355− <div>
267+ <div className="flex flex-col space-y-2 min-w-0">
268+ <p className="font-bold">{article.publication}</p>
269+ <p className="min-w-0 min-h-0 leading-5 ">
356− <h3 className="text-green-400">{post.title}</h3>
272+ <p className="text-wall-400">
357− <div className="type-ui mt-2">
273+ {formatDate(generateDisplayDate(article.date))}
358− {["featured-1", "featured-2", "featured-3"].map(
274+ </p>
359− (feat, i) => {
275+ </div>
360− if (post?.[feat]) {
276+ </div>
361− return (
277+ </Link>
364− <span>{post[feat].title}</span>
384−export async function getStaticProps({ }) {
282+export async function getStaticProps() {
385 const posts = getAllPosts(
283 const posts = getAllPosts(
386 ["title", "date", "slug", "featured-1", "featured-2", "featured-3"],
284 ["title", "date", "slug", "featured-1", "featured-2", "featured-3"],
387 "ecosystem/spotlight",
285 "ecosystem/spotlight",
390− let post = matchEcosystemPost(getAllPosts(
288+ const post = matchEcosystemPost(getAllPosts(
391 ["title", "date", "featured-1", "featured-2", "featured-3"],
289 ["title", "date", "featured-1", "featured-2", "featured-3"],
392 "ecosystem/spotlight",
290 "ecosystem/spotlight",