···11+import BaseLayout from "@/components/BaseLayout";
22+import BookCard from "@/components/pageContent/books/BookCard";
33+import { importCSVDataAsJson } from "@/lib/sheetsConnector";
44+import type Book from "@/types/Book";
55+import Link from "next/link";
66+77+export const revalidate = 60;
88+99+export default async function Page(): Promise<React.ReactElement> {
1010+ const books: Array<Book> = await getBooks().then((bookList) =>
1111+ bookList.data
1212+ .sort((a: Book, b: Book) => {
1313+ // Sorting by read date, newest --> oldest
1414+ return Date.parse(b.dateRead) - Date.parse(a.dateRead);
1515+ })
1616+ .slice(0, 15)
1717+ );
1818+1919+ return (
2020+ <BaseLayout>
2121+ <div className="mx-auto flex flex-col gap-6">
2222+ <section className="mx-auto max-w-2xl mb-0 sm:mb-4">
2323+ <h1>Books</h1>
2424+ <div className="prose prose-stone dark:prose-invert">
2525+ <p>
2626+ I love reading. Lots of fantasy, some scifi, occasionally
2727+ non-fiction (I usually enjoy it, it's just not what I'm drawn to).
2828+ I was a heavy reader as a kid, fell off during high school when
2929+ reading was a requirement for class (common story), and then came
3030+ back to it when I moved to Singapore just before the pandemic.
3131+ </p>
3232+ <p>
3333+ I believe <em>owning things</em> also means{" "}
3434+ <em>taking on the responsibility of taking care of them</em>.
3535+ Between not wanting this responsibility and harboring deep
3636+ feelings of anti-consumerism, I choose to primarily read ebooks
3737+ instead of owning physical books.
3838+ </p>
3939+ <p>
4040+ I check out books from one of the many libraries I have a card for
4141+ (
4242+ <Link href={"/library-cards"}>
4343+ check out my library card collection!
4444+ </Link>
4545+ ), using{" "}
4646+ <a href="https://libbyapp.com/" target="_blank">
4747+ the Libby app
4848+ </a>
4949+ , and read them on my Kindle. I've searched for solid non-Amazon
5050+ ereader alternatives, but none of them seem to have the right
5151+ compatibility with Libby to allow me to use multiple library
5252+ cards. If you don't suffer from this inane, self-inflicted
5353+ constraint, I highly recommend{" "}
5454+ <a
5555+ href="https://us.kobobooks.com/collections/ereaders"
5656+ target="_blank"
5757+ >
5858+ Kobo ereaders
5959+ </a>
6060+ .
6161+ </p>
6262+ </div>
6363+ <hr className="mt-4 border-stone-400 dark:border-stone-500 sm:hidden" />
6464+ </section>
6565+ <section>
6666+ <h2>What I've been reading</h2>
6767+ <p className="prose prose-stone dark:prose-invert">
6868+ These are my most recent reads. See more on{" "}
6969+ <a
7070+ href="https://app.thestorygraph.com/profile/bk610"
7171+ target="_blank"
7272+ className=""
7373+ >
7474+ The StoryGraph
7575+ </a>
7676+ .
7777+ </p>
7878+ <div className="py-5 grid grid-cols-1 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-5">
7979+ {books.map((book: Book) => {
8080+ return <BookCard book={book} />;
8181+ })}
8282+ </div>
8383+ </section>
8484+ <section className="prose prose-stone dark:prose-invert max-w-none">
8585+ <p className="text-sm">
8686+ Book cover image data comes from the{" "}
8787+ <a
8888+ href="https://openlibrary.org/dev/docs/api/covers?ref=baileykane.co"
8989+ target="_blank"
9090+ >
9191+ Open Library Covers API
9292+ </a>
9393+ .
9494+ </p>
9595+ </section>
9696+ </div>
9797+ </BaseLayout>
9898+ );
9999+}
100100+101101+async function getBooks(): Promise<{
102102+ data: Array<Book>;
103103+}> {
104104+ const booksList = await importCSVDataAsJson(
105105+ process.env.NEXT_PUBLIC_BOOKS_DATA_URL
106106+ );
107107+108108+ return booksList;
109109+}