this repo has no description www.baileykane.co/
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Convert to typescript. Update imports

BK610 aec559ab 235c5395

+295 -195
+2 -4
pages/_app.js pages/_app.tsx
··· 1 - import "../styles/globals.css"; 1 + import "@/styles/globals.css"; 2 2 import { useEffect } from "react"; 3 3 import { Router } from "next/router"; 4 4 import posthog from "posthog-js"; ··· 16 16 // }); 17 17 // } 18 18 19 - function MyApp({ Component, pageProps }) { 19 + export default function MyApp({ Component, pageProps }): React.ReactElement { 20 20 useEffect(() => { 21 21 posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { 22 22 api_host: ··· 42 42 </PostHogProvider> 43 43 ); 44 44 } 45 - 46 - export default MyApp;
+1 -3
pages/_document.js pages/_document.tsx
··· 1 1 import Document, { Html, Head, Main, NextScript } from "next/document"; 2 2 3 - class MyDocument extends Document { 3 + export default class MyDocument extends Document { 4 4 render() { 5 5 return ( 6 6 <Html> ··· 90 90 ); 91 91 } 92 92 } 93 - 94 - export default MyDocument;
-24
pages/_offline.js
··· 1 - import Head from "next/head"; 2 - import { Component } from "react"; 3 - import BaseLayout from "../components/BaseLayout"; 4 - 5 - export default class OfflineFallback extends Component { 6 - render() { 7 - return ( 8 - <> 9 - <Head> 10 - <title>Bailey Kane</title> 11 - </Head> 12 - <BaseLayout navbarVisible={false}> 13 - <div className="w-full flex flex-col items-center"> 14 - <div className="w-full max-w-md space-y-4"> 15 - <div className="text-xl"> 16 - <h2>Looks like you're offline, my dude. Sad 😕</h2> 17 - </div> 18 - </div> 19 - </div> 20 - </BaseLayout> 21 - </> 22 - ); 23 - } 24 - }
+21
pages/_offline.tsx
··· 1 + import Head from "next/head"; 2 + import BaseLayout from "@/components/BaseLayout"; 3 + 4 + export default function OfflineFallback(): React.ReactElement { 5 + return ( 6 + <> 7 + <Head> 8 + <title>Bailey Kane</title> 9 + </Head> 10 + <BaseLayout navbarVisible={false}> 11 + <div className="w-full flex flex-col items-center"> 12 + <div className="w-full max-w-md space-y-4"> 13 + <div className="text-xl"> 14 + <h2>Looks like you're offline, my dude. Sad 😕</h2> 15 + </div> 16 + </div> 17 + </div> 18 + </BaseLayout> 19 + </> 20 + ); 21 + }
+3 -3
pages/about.js pages/about.tsx
··· 1 - import BaseLayout from "../components/BaseLayout"; 1 + import BaseLayout from "@/components/BaseLayout"; 2 2 import Link from "next/link"; 3 3 4 - export default function About({}) { 4 + export default function About(): React.ReactElement { 5 5 return ( 6 6 <BaseLayout titleText={"About"}> 7 7 <div className="max-w-2xl mx-auto"> ··· 60 60 problems with fun people. I've jumped industries and roles in nearly 61 61 every job I've had, and have embraced my nature as an enthusiastic 62 62 generalist. 63 - <p>I now spend my time:</p> 64 63 </p> 64 + <p>I now spend my time:</p> 65 65 <ul> 66 66 <li> 67 67 Supporting small business owners by ugprading their businesses
pages/api/garden.js

This is a binary file and will not be displayed.

+32
pages/api/garden.ts
··· 1 + // pages/api/party.js - PartyKit API Route for Next.js Pages Router 2 + import { NextApiRequest, NextApiResponse } from "next"; 3 + import { Server } from "partykit/server"; 4 + 5 + const flowers = []; 6 + 7 + export default function handler(req: NextApiRequest, res: NextApiResponse) { 8 + if (req.method === "GET") { 9 + // Clean up old flowers (older than 24 hours) 10 + const now = Date.now(); 11 + while (flowers.length && now - flowers[0].createdAt > 86400000) { 12 + flowers.shift(); 13 + } 14 + res.status(200).json({ flowers }); 15 + } else if (req.method === "POST") { 16 + const newFlower = { 17 + id: Date.now(), 18 + createdAt: Date.now(), 19 + color: getRandomColor(), 20 + }; 21 + flowers.push(newFlower); 22 + res.status(201).json(newFlower); 23 + } else { 24 + res.setHeader("Allow", ["GET", "POST"]); 25 + res.status(405).end(`Method ${req.method} Not Allowed`); 26 + } 27 + } 28 + 29 + function getRandomColor(): string { 30 + const colors = ["#FF69B4", "#FFD700", "#8A2BE2", "#FF4500", "#00FF7F"]; 31 + return colors[Math.floor(Math.random() * colors.length)]; 32 + }
+13 -7
pages/feed.js pages/feed.tsx
··· 1 - import BaseLayout from "../components/BaseLayout"; 2 - import BlueskyPost from "../components/BlueskyFeed/BlueskyPost"; 3 - import { agent } from "../lib/bskyApi"; 1 + import type { Key } from "react"; 2 + import BaseLayout from "@/components/BaseLayout"; 3 + import BlueskyPost from "@/components/BlueskyFeed/BlueskyPost"; 4 + import { agent } from "@/lib/bskyApi"; 5 + import type { GetStaticProps } from "next"; 4 6 5 - export default function Feed({ feed }) { 7 + interface FeedProps { 8 + feed: Array<Object>; 9 + } 10 + 11 + export default function Feed({ feed }: FeedProps): React.ReactElement { 6 12 return ( 7 13 <BaseLayout titleText={"Feed"}> 8 14 <div className="max-w-2xl mx-auto"> ··· 17 23 </a> 18 24 </p> 19 25 <div className="col-span-2 sm:col-span-1"> 20 - {feed.map((post_data, k) => ( 26 + {feed.map((post_data, k: Key) => ( 21 27 <BlueskyPost post_data={post_data} key={k} /> 22 28 ))} 23 29 </div> ··· 26 32 ); 27 33 } 28 34 29 - export async function getStaticProps() { 35 + export const getStaticProps = (async () => { 30 36 const did = await fetch( 31 37 "https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=baileykane.co" 32 38 ) ··· 43 49 props: { feed: JSON.parse(JSON.stringify(feed)) }, 44 50 revalidate: 60, 45 51 }; 46 - } 52 + }) satisfies GetStaticProps<FeedProps>;
-9
pages/garden.js
··· 1 - import BaseLayout from "../components/BaseLayout"; 2 - 3 - export default function Garden() { 4 - return ( 5 - <BaseLayout> 6 - <div>Coming soon!</div> 7 - </BaseLayout> 8 - ); 9 - }
+9
pages/garden.tsx
··· 1 + import BaseLayout from "@/components/BaseLayout"; 2 + 3 + export default function Garden(): React.ReactElement { 4 + return ( 5 + <BaseLayout> 6 + <div>Coming soon!</div> 7 + </BaseLayout> 8 + ); 9 + }
+26 -12
pages/index.js pages/index.tsx
··· 1 - import HomeSectionItem from "../components/HomeSectionItem"; 2 - import BaseLayout from "../components/BaseLayout"; 3 - import SectionList from "../components/SectionList"; 4 - import SocialLink from "../components/SocialLink"; 5 - import { importCSVDataAsJson } from "../lib/sheetsConnector"; 1 + import HomeSectionItem from "@/components/HomeSectionItem"; 2 + import BaseLayout from "@/components/BaseLayout"; 3 + import SectionList from "@/components/SectionList"; 4 + import SocialLink from "@/components/SocialLink"; 5 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 6 6 import Link from "next/link"; 7 + import type { GetStaticProps } from "next"; 8 + import type { Key } from "react"; 7 9 8 - export default function Home({ sectionsList }) { 10 + interface HomeProps { 11 + sectionsList: { 12 + data: Array<HomeSection>; 13 + }; 14 + } 15 + 16 + interface HomeSection { 17 + name: string; 18 + link: string; 19 + description: string; 20 + emoji: string; 21 + } 22 + 23 + export default function Home({ sectionsList }: HomeProps): React.ReactElement { 9 24 return ( 10 - <BaseLayout navbarVisible={false} className=""> 25 + <BaseLayout navbarVisible={false}> 11 26 <div className="max-w-5xl mx-auto w-full grid grid-cols-1 sm:grid-cols-2 gap-6"> 12 27 <div> 13 28 <h1 className="mb-2">Hello hello, this is Bailey speaking.</h1> ··· 29 44 <p>Some things I do:</p> 30 45 <ul className="list-disc"> 31 46 <li> 32 - <b>Build websites</b> for marketing, portfolios, or other 33 - information 47 + <b>Build websites</b> for businesses, portfolios, or for fun 34 48 </li> 35 49 <li> 36 50 <b>Create bespoke tools</b> and systems to work more efficiently ··· 96 110 </h3> 97 111 <div className="h-full w-full items-center"> 98 112 <SectionList className="item-list flex flex-col"> 99 - {sectionsList.data.map((section, k) => ( 113 + {sectionsList.data.map((section: HomeSection, k: Key) => ( 100 114 <HomeSectionItem 101 115 link={ 102 116 section.link ? section.link : section.name.toLowerCase() ··· 116 130 } 117 131 118 132 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 119 - export async function getStaticProps() { 133 + export const getStaticProps = (async () => { 120 134 const sectionsList = await importCSVDataAsJson( 121 135 process.env.NEXT_PUBLIC_HOME_DATA_URL 122 136 ); ··· 127 141 }, 128 142 revalidate: 60, 129 143 }; 130 - } 144 + }) satisfies GetStaticProps<HomeProps>;
-91
pages/library-cards.js
··· 1 - import { useEffect, useState } from "react"; 2 - import { importCSVDataAsJson } from "../lib/sheetsConnector"; 3 - import BaseLayout from "../components/BaseLayout"; 4 - import SectionList from "../components/SectionList"; 5 - import LibraryCard from "../components/LibraryCard"; 6 - 7 - export default function LibraryCards({ libraryCardsList }) { 8 - const [allCards, setAllCards] = useState([]); 9 - const [selectedCard, setSelectedCard] = useState(null); 10 - 11 - const setSelected = (element) => { 12 - if (selectedCard == element) { 13 - setSelectedCard(null); 14 - } else { 15 - setSelectedCard(element); 16 - } 17 - }; 18 - 19 - useEffect(() => { 20 - setAllCards(document.querySelectorAll(".library-card")); 21 - 22 - if (allCards) { 23 - allCards.forEach((element) => { 24 - element.classList.remove("library-card-selected"); 25 - }); 26 - } 27 - 28 - if (selectedCard) { 29 - selectedCard.classList.add("library-card-selected"); 30 - } 31 - }, [selectedCard, libraryCardsList]); 32 - 33 - return ( 34 - <BaseLayout titleText={"Library Cards"}> 35 - {selectedCard && ( 36 - <div className="fixed backdrop-blur-2xl transition inset-0 bg-black/50 z-40" /> 37 - )} 38 - <div className="max-w-4xl mx-auto space-y-4"> 39 - <h1>Library Cards</h1> 40 - <div className="prose prose-stone dark:prose-invert max-w-none"> 41 - <p> 42 - I collect library cards when I travel! Here's the current 43 - collection. 44 - </p> 45 - <p> 46 - <a 47 - href="https://everyday-reading.com/where-you-can-get-a-non-resident-library-card/" 48 - target="_blank" 49 - > 50 - Many libraries 51 - </a>{" "} 52 - offer library cards to non-residents for a fee, and sometimes for 53 - free. I visit libraries, sign up for cards if I can, and use them 54 - for ebook access when I go back home. 55 - </p> 56 - <p> 57 - <i>PS: You can drag the cards around, just for fun.</i> 58 - </p> 59 - </div> 60 - <SectionList className="grid grid-cols-1 md:grid-cols-2"> 61 - {libraryCardsList.data 62 - .sort((a, b) => { 63 - // Sorting by date, newest --> oldest 64 - return Date.parse(b.acquiredDate) - Date.parse(a.acquiredDate); 65 - }) 66 - .map((libraryCard, k) => ( 67 - <LibraryCard 68 - libraryCard={libraryCard} 69 - key={k} 70 - onClick={(event) => setSelected(event.currentTarget)} 71 - /> 72 - ))} 73 - </SectionList> 74 - </div> 75 - </BaseLayout> 76 - ); 77 - } 78 - 79 - // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 80 - export async function getStaticProps() { 81 - const libraryCardsList = await importCSVDataAsJson( 82 - process.env.NEXT_PUBLIC_LIBRARY_CARDS_DATA_URL 83 - ); 84 - 85 - return { 86 - props: { 87 - libraryCardsList, 88 - }, 89 - revalidate: 60, 90 - }; 91 - }
+103
pages/library-cards.tsx
··· 1 + import { Key, useEffect, useState } from "react"; 2 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 3 + import BaseLayout from "@/components/BaseLayout"; 4 + import SectionList from "@/components/SectionList"; 5 + import LibraryCardItem from "@/components/LibraryCardItem"; 6 + import type { GetStaticProps } from "next"; 7 + import type LibraryCard from "@/types/LibraryCard"; 8 + 9 + interface LibraryCardsProps { 10 + libraryCardsList: { 11 + data: Array<LibraryCard>; 12 + }; 13 + } 14 + 15 + export default function LibraryCards({ 16 + libraryCardsList, 17 + }: LibraryCardsProps): React.ReactElement { 18 + const [allCards, setAllCards] = useState(null); 19 + const [selectedCard, setSelectedCard] = useState(null); 20 + 21 + const setSelected = (element: React.ReactElement) => { 22 + if (selectedCard == element) { 23 + setSelectedCard(null); 24 + } else { 25 + setSelectedCard(element); 26 + } 27 + }; 28 + 29 + useEffect(() => { 30 + setAllCards(document.querySelectorAll(".library-card")); 31 + 32 + if (allCards) { 33 + allCards.forEach((element) => { 34 + element.classList.remove("library-card-selected"); 35 + }); 36 + } 37 + 38 + if (selectedCard) { 39 + selectedCard.classList.add("library-card-selected"); 40 + } 41 + }, [selectedCard, libraryCardsList]); 42 + 43 + return ( 44 + <BaseLayout titleText={"Library Cards"}> 45 + <> 46 + {selectedCard && ( 47 + <div className="fixed backdrop-blur-2xl transition inset-0 bg-black/50 z-40" /> 48 + )} 49 + <div className="max-w-4xl mx-auto space-y-4"> 50 + <h1>Library Cards</h1> 51 + <div className="prose prose-stone dark:prose-invert max-w-none"> 52 + <p> 53 + I collect library cards when I travel! Here's the current 54 + collection. 55 + </p> 56 + <p> 57 + <a 58 + href="https://everyday-reading.com/where-you-can-get-a-non-resident-library-card/" 59 + target="_blank" 60 + > 61 + Many libraries 62 + </a>{" "} 63 + offer library cards to non-residents for a fee, and sometimes for 64 + free. I visit libraries, sign up for cards if I can, and use them 65 + for ebook access when I go back home. 66 + </p> 67 + <p> 68 + <i>PS: You can drag the cards around, just for fun.</i> 69 + </p> 70 + </div> 71 + <SectionList className="grid grid-cols-1 md:grid-cols-2"> 72 + {libraryCardsList.data 73 + .sort((a: LibraryCard, b: LibraryCard) => { 74 + // Sorting by date, newest --> oldest 75 + return Date.parse(b.acquiredDate) - Date.parse(a.acquiredDate); 76 + }) 77 + .map((libraryCard: LibraryCard, k: Key) => ( 78 + <LibraryCardItem 79 + libraryCard={libraryCard} 80 + key={k} 81 + onClick={(event) => setSelected(event.currentTarget)} 82 + /> 83 + ))} 84 + </SectionList> 85 + </div> 86 + </> 87 + </BaseLayout> 88 + ); 89 + } 90 + 91 + // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 92 + export const getStaticProps = (async () => { 93 + const libraryCardsList = await importCSVDataAsJson( 94 + process.env.NEXT_PUBLIC_LIBRARY_CARDS_DATA_URL 95 + ); 96 + 97 + return { 98 + props: { 99 + libraryCardsList, 100 + }, 101 + revalidate: 60, 102 + }; 103 + }) satisfies GetStaticProps;
+16 -7
pages/music.js pages/music.tsx
··· 1 - import BaseLayout from "../components/BaseLayout"; 1 + import type { GetStaticProps } from "next"; 2 + import BaseLayout from "@/components/BaseLayout"; 2 3 import Head from "next/head"; 3 - import MusicItem from "../components/MusicItem"; 4 - import { importCSVDataAsJson } from "../lib/sheetsConnector"; 4 + import MusicItem from "@/components/MusicItem"; 5 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 6 + import type Music from "@/types/Music"; 7 + import type { Key } from "react"; 8 + 9 + interface MusicProps { 10 + musicList: { 11 + data: Array<Music>; 12 + }; 13 + } 5 14 6 - export default function Music({ musicList }) { 15 + export default function Music({ musicList }: MusicProps): React.ReactElement { 7 16 return ( 8 17 <> 9 18 <Head> ··· 16 25 <div className="w-full max-w-md space-y-4"> 17 26 <h2>Music</h2> 18 27 <div className="text-lg">Small moments of making music</div> 19 - {musicList.data.map((musicItem, k) => ( 28 + {musicList.data.map((musicItem: Music, k: Key) => ( 20 29 <MusicItem musicItem={musicItem} key={k} /> 21 30 ))} 22 31 </div> ··· 27 36 } 28 37 29 38 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 30 - export async function getStaticProps() { 39 + export const getStaticProps = (async () => { 31 40 const musicList = await importCSVDataAsJson( 32 41 process.env.NEXT_PUBLIC_MUSIC_DATA_URL 33 42 ); ··· 38 47 }, 39 48 revalidate: 60, 40 49 }; 41 - } 50 + }) satisfies GetStaticProps<MusicProps>;
+15 -9
pages/projects/[slug].js pages/projects/[slug].tsx
··· 1 - import BaseLayout from "../../components/BaseLayout"; 2 - import MissingContent from "../../components/MissingContent"; 3 - import ProjectContent from "../../components/ProjectContent"; 4 - import { importCSVDataAsJson } from "../../lib/sheetsConnector"; 1 + import BaseLayout from "@/components/BaseLayout"; 2 + import MissingContent from "@/components/MissingContent"; 3 + import ProjectContent from "@/components/ProjectContent"; 4 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 5 + import type Project from "@/types/Project"; 6 + import type { GetStaticProps, GetStaticPaths } from "next"; 5 7 6 - export default function Project({ project }) { 8 + interface ProjectProps { 9 + project: Project; 10 + } 11 + 12 + export default function Project({ project }: ProjectProps): React.ReactElement { 7 13 if (!project) { 8 14 return <MissingContent />; 9 15 } ··· 18 24 } 19 25 20 26 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 21 - export async function getStaticProps(context) { 27 + export const getStaticProps = (async (context) => { 22 28 const { slug } = context.params; 23 29 24 30 const projectsList = await importCSVDataAsJson( ··· 31 37 const project = projectsList.data.find((project) => project.slug === slug); 32 38 33 39 return { props: { project }, revalidate: 60 }; 34 - } 40 + }) satisfies GetStaticProps<ProjectProps>; 35 41 36 42 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-paths 37 - export async function getStaticPaths() { 43 + export const getStaticPaths = (async () => { 38 44 const projectsList = await importCSVDataAsJson( 39 45 process.env.NEXT_PUBLIC_PROJECTS_DATA_URL 40 46 ); ··· 44 50 })); 45 51 46 52 return { paths, fallback: false }; 47 - } 53 + }) satisfies GetStaticPaths;
+20 -9
pages/projects/index.js pages/projects/index.tsx
··· 1 - import ProjectSectionItem from "../../components/ProjectSectionItem"; 2 - import BaseLayout from "../../components/BaseLayout"; 3 - import SectionList from "../../components/SectionList"; 4 - import { importCSVDataAsJson } from "../../lib/sheetsConnector"; 1 + import ProjectSectionItem from "@/components/ProjectSectionItem"; 2 + import BaseLayout from "@/components/BaseLayout"; 3 + import SectionList from "@/components/SectionList"; 4 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 5 + import type Project from "@/types/Project"; 6 + import type { GetStaticProps } from "next"; 7 + import { Key } from "react"; 8 + 9 + interface ProjectsProps { 10 + projectsList: { 11 + data: Array<Project>; 12 + }; 13 + } 5 14 6 - export default function Projects({ projectsList }) { 15 + export default function Projects({ 16 + projectsList, 17 + }: ProjectsProps): React.ReactElement { 7 18 return ( 8 19 <BaseLayout titleText={"Projects"}> 9 20 <div className="w-full max-w-5xl mx-auto flex flex-col items-center relative z-10"> ··· 16 27 </div> 17 28 <SectionList className="item-list grid grid-cols-1 sm:grid-cols-2"> 18 29 {projectsList.data 19 - .sort((a, b) => { 30 + .sort((a: Project, b: Project) => { 20 31 // Sorting by date, newest --> oldest 21 32 return Date.parse(b.date) - Date.parse(a.date); 22 33 }) 23 - .map((project, k) => ( 34 + .map((project: Project, k: Key) => ( 24 35 <ProjectSectionItem project={project} key={k} /> 25 36 ))} 26 37 </SectionList> ··· 31 42 } 32 43 33 44 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 34 - export async function getStaticProps() { 45 + export const getStaticProps = (async () => { 35 46 const projectsList = await importCSVDataAsJson( 36 47 process.env.NEXT_PUBLIC_PROJECTS_DATA_URL 37 48 ); ··· 42 53 }, 43 54 revalidate: 60, 44 55 }; 45 - } 56 + }) satisfies GetStaticProps<ProjectsProps>;
+15 -9
pages/recipes/[slug].js pages/recipes/[slug].tsx
··· 1 - import MissingContent from "../../components/MissingContent"; 2 - import BaseLayout from "../../components/BaseLayout"; 3 - import RecipeContent from "../../components/RecipeContent"; 4 - import { importCSVDataAsJson } from "../../lib/sheetsConnector"; 1 + import MissingContent from "@/components/MissingContent"; 2 + import BaseLayout from "@/components/BaseLayout"; 3 + import RecipeContent from "@/components/RecipeContent"; 4 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 5 + import type Recipe from "@/types/Recipe"; 6 + import type { GetStaticProps, GetStaticPaths } from "next"; 5 7 6 - export default function Recipe({ recipe }) { 8 + interface RecipeProps { 9 + recipe: Recipe; 10 + } 11 + 12 + export default function Recipe({ recipe }: RecipeProps): React.ReactElement { 7 13 if (!recipe) { 8 14 return <MissingContent />; 9 15 } ··· 18 24 } 19 25 20 26 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 21 - export async function getStaticProps(context) { 27 + export const getStaticProps = (async (context) => { 22 28 const { slug } = context.params; 23 29 24 30 const recipesList = await importCSVDataAsJson( ··· 31 37 const recipe = recipesList.data.find((recipe) => recipe.slug === slug); 32 38 33 39 return { props: { recipe }, revalidate: 60 }; 34 - } 40 + }) satisfies GetStaticProps<RecipeProps>; 35 41 36 42 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-paths 37 - export async function getStaticPaths() { 43 + export const getStaticPaths = (async () => { 38 44 const recipesList = await importCSVDataAsJson( 39 45 process.env.NEXT_PUBLIC_RECIPES_DATA_URL 40 46 ); ··· 44 50 })); 45 51 46 52 return { paths, fallback: false }; 47 - } 53 + }) satisfies GetStaticPaths;
+19 -8
pages/recipes/index.js pages/recipes/index.tsx
··· 1 - import RecipeSectionItem from "../../components/RecipeSectionItem"; 2 - import BaseLayout from "../../components/BaseLayout"; 3 - import SectionList from "../../components/SectionList"; 4 - import { importCSVDataAsJson } from "../../lib/sheetsConnector"; 1 + import RecipeSectionItem from "@/components/RecipeSectionItem"; 2 + import BaseLayout from "@/components/BaseLayout"; 3 + import SectionList from "@/components/SectionList"; 4 + import { importCSVDataAsJson } from "@/lib/sheetsConnector"; 5 + import type Recipe from "@/types/Recipe"; 6 + import type { Key } from "react"; 7 + import type { GetStaticProps } from "next"; 8 + 9 + interface RecipesProps { 10 + recipesList: { 11 + data: Array<Recipe>; 12 + }; 13 + } 5 14 6 - export default function Recipes({ recipesList }) { 15 + export default function Recipes({ 16 + recipesList, 17 + }: RecipesProps): React.ReactElement { 7 18 return ( 8 19 <BaseLayout titleText={"Recipes"}> 9 20 <div className="w-full flex flex-col items-center"> ··· 11 22 <h2>Recipes</h2> 12 23 <div className="text-lg">Behold, my lovely recipes.</div> 13 24 <SectionList className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3"> 14 - {recipesList.data.map((recipe, k) => ( 25 + {recipesList.data.map((recipe: Recipe, k: Key) => ( 15 26 <RecipeSectionItem 16 27 link={"/recipes/" + recipe.slug} 17 28 name={recipe.title} ··· 28 39 } 29 40 30 41 // Reference: https://nextjs.org/docs/pages/building-your-application/data-fetching/get-static-props#using-getstaticprops-to-fetch-data-from-a-cms 31 - export async function getStaticProps() { 42 + export const getStaticProps = (async () => { 32 43 const recipesList = await importCSVDataAsJson( 33 44 process.env.NEXT_PUBLIC_RECIPES_DATA_URL 34 45 ); ··· 37 48 props: { recipesList }, 38 49 revalidate: 60, 39 50 }; 40 - } 51 + }) satisfies GetStaticProps<RecipesProps>;