diff --git a/public/images/bookmarks/a-beautiful-mind.jpg b/public/images/bookmarks/a-beautiful-mind.jpg new file mode 100644 index 0000000..8e85fce Binary files /dev/null and b/public/images/bookmarks/a-beautiful-mind.jpg differ diff --git a/public/images/bookmarks/attack-on-titan.jpg b/public/images/bookmarks/attack-on-titan.jpg new file mode 100644 index 0000000..fcd1de4 Binary files /dev/null and b/public/images/bookmarks/attack-on-titan.jpg differ diff --git a/public/images/bookmarks/blue-eye-samurai.jpg b/public/images/bookmarks/blue-eye-samurai.jpg new file mode 100644 index 0000000..f5d6974 Binary files /dev/null and b/public/images/bookmarks/blue-eye-samurai.jpg differ diff --git a/public/images/bookmarks/bumblebee.jpg b/public/images/bookmarks/bumblebee.jpg new file mode 100644 index 0000000..3775fd6 Binary files /dev/null and b/public/images/bookmarks/bumblebee.jpg differ diff --git a/public/images/bookmarks/chainsaw-man-the-movie-reze-arc.jpg b/public/images/bookmarks/chainsaw-man-the-movie-reze-arc.jpg new file mode 100644 index 0000000..b7968d4 Binary files /dev/null and b/public/images/bookmarks/chainsaw-man-the-movie-reze-arc.jpg differ diff --git a/public/images/bookmarks/clean-code.jpg b/public/images/bookmarks/clean-code.jpg new file mode 100644 index 0000000..7889e2f Binary files /dev/null and b/public/images/bookmarks/clean-code.jpg differ diff --git a/public/images/bookmarks/death-note.jpg b/public/images/bookmarks/death-note.jpg new file mode 100644 index 0000000..9079408 Binary files /dev/null and b/public/images/bookmarks/death-note.jpg differ diff --git a/public/images/bookmarks/demon-slayer.jpg b/public/images/bookmarks/demon-slayer.jpg new file mode 100644 index 0000000..2e885af Binary files /dev/null and b/public/images/bookmarks/demon-slayer.jpg differ diff --git a/public/images/bookmarks/designing-data-intensive-applications.jpg b/public/images/bookmarks/designing-data-intensive-applications.jpg new file mode 100644 index 0000000..a1a4f43 Binary files /dev/null and b/public/images/bookmarks/designing-data-intensive-applications.jpg differ diff --git a/public/images/bookmarks/drishyam-2.jpg b/public/images/bookmarks/drishyam-2.jpg new file mode 100644 index 0000000..85b7aab Binary files /dev/null and b/public/images/bookmarks/drishyam-2.jpg differ diff --git a/public/images/bookmarks/drishyam.jpg b/public/images/bookmarks/drishyam.jpg new file mode 100644 index 0000000..0559cf9 Binary files /dev/null and b/public/images/bookmarks/drishyam.jpg differ diff --git a/public/images/bookmarks/einstein-and-eddington.jpg b/public/images/bookmarks/einstein-and-eddington.jpg new file mode 100644 index 0000000..8cee469 Binary files /dev/null and b/public/images/bookmarks/einstein-and-eddington.jpg differ diff --git a/public/images/bookmarks/erin-brockovich.jpg b/public/images/bookmarks/erin-brockovich.jpg new file mode 100644 index 0000000..9edbb41 Binary files /dev/null and b/public/images/bookmarks/erin-brockovich.jpg differ diff --git a/public/images/bookmarks/forrest-gump.jpg b/public/images/bookmarks/forrest-gump.jpg new file mode 100644 index 0000000..75ba6df Binary files /dev/null and b/public/images/bookmarks/forrest-gump.jpg differ diff --git a/public/images/bookmarks/green-book.jpg b/public/images/bookmarks/green-book.jpg new file mode 100644 index 0000000..1ae4af4 Binary files /dev/null and b/public/images/bookmarks/green-book.jpg differ diff --git a/public/images/bookmarks/hachi-a-dog-s-tale.jpg b/public/images/bookmarks/hachi-a-dog-s-tale.jpg new file mode 100644 index 0000000..35a47ae Binary files /dev/null and b/public/images/bookmarks/hachi-a-dog-s-tale.jpg differ diff --git a/public/images/bookmarks/interstellar.jpg b/public/images/bookmarks/interstellar.jpg new file mode 100644 index 0000000..273654e Binary files /dev/null and b/public/images/bookmarks/interstellar.jpg differ diff --git a/public/images/bookmarks/joker.jpg b/public/images/bookmarks/joker.jpg new file mode 100644 index 0000000..c431c24 Binary files /dev/null and b/public/images/bookmarks/joker.jpg differ diff --git a/public/images/bookmarks/l-on-the-professional.jpg b/public/images/bookmarks/l-on-the-professional.jpg new file mode 100644 index 0000000..d67753f Binary files /dev/null and b/public/images/bookmarks/l-on-the-professional.jpg differ diff --git a/public/images/bookmarks/masters-of-the-air.jpg b/public/images/bookmarks/masters-of-the-air.jpg new file mode 100644 index 0000000..7b78418 Binary files /dev/null and b/public/images/bookmarks/masters-of-the-air.jpg differ diff --git a/public/images/bookmarks/midnight-diner.jpg b/public/images/bookmarks/midnight-diner.jpg new file mode 100644 index 0000000..d8a6e22 Binary files /dev/null and b/public/images/bookmarks/midnight-diner.jpg differ diff --git a/public/images/bookmarks/mr-robot.jpg b/public/images/bookmarks/mr-robot.jpg new file mode 100644 index 0000000..57d9f9c Binary files /dev/null and b/public/images/bookmarks/mr-robot.jpg differ diff --git a/public/images/bookmarks/my-love-from-the-star.jpg b/public/images/bookmarks/my-love-from-the-star.jpg new file mode 100644 index 0000000..d52cf39 Binary files /dev/null and b/public/images/bookmarks/my-love-from-the-star.jpg differ diff --git a/public/images/bookmarks/now-you-see-me.jpg b/public/images/bookmarks/now-you-see-me.jpg new file mode 100644 index 0000000..9872aca Binary files /dev/null and b/public/images/bookmarks/now-you-see-me.jpg differ diff --git a/public/images/bookmarks/nuremberg.jpg b/public/images/bookmarks/nuremberg.jpg new file mode 100644 index 0000000..351850e Binary files /dev/null and b/public/images/bookmarks/nuremberg.jpg differ diff --git a/public/images/bookmarks/one-punch-man.jpg b/public/images/bookmarks/one-punch-man.jpg new file mode 100644 index 0000000..bede690 Binary files /dev/null and b/public/images/bookmarks/one-punch-man.jpg differ diff --git a/public/images/bookmarks/oppenheimer.jpg b/public/images/bookmarks/oppenheimer.jpg new file mode 100644 index 0000000..72d9db1 Binary files /dev/null and b/public/images/bookmarks/oppenheimer.jpg differ diff --git a/public/images/bookmarks/orb-on-the-movements-of-the-earth.jpg b/public/images/bookmarks/orb-on-the-movements-of-the-earth.jpg new file mode 100644 index 0000000..0cae381 Binary files /dev/null and b/public/images/bookmarks/orb-on-the-movements-of-the-earth.jpg differ diff --git a/public/images/bookmarks/panchayat.jpg b/public/images/bookmarks/panchayat.jpg new file mode 100644 index 0000000..08ef283 Binary files /dev/null and b/public/images/bookmarks/panchayat.jpg differ diff --git a/public/images/bookmarks/sakamoto-days.jpg b/public/images/bookmarks/sakamoto-days.jpg new file mode 100644 index 0000000..9b75881 Binary files /dev/null and b/public/images/bookmarks/sakamoto-days.jpg differ diff --git a/public/images/bookmarks/schindlers-list.jpg b/public/images/bookmarks/schindlers-list.jpg new file mode 100644 index 0000000..04797de Binary files /dev/null and b/public/images/bookmarks/schindlers-list.jpg differ diff --git a/public/images/bookmarks/silicon-valley.jpg b/public/images/bookmarks/silicon-valley.jpg new file mode 100644 index 0000000..6408037 Binary files /dev/null and b/public/images/bookmarks/silicon-valley.jpg differ diff --git a/public/images/bookmarks/solo-leveling.jpg b/public/images/bookmarks/solo-leveling.jpg new file mode 100644 index 0000000..1ccf883 Binary files /dev/null and b/public/images/bookmarks/solo-leveling.jpg differ diff --git a/public/images/bookmarks/special-26.jpg b/public/images/bookmarks/special-26.jpg new file mode 100644 index 0000000..859b29c Binary files /dev/null and b/public/images/bookmarks/special-26.jpg differ diff --git a/public/images/bookmarks/the-aviator.jpg b/public/images/bookmarks/the-aviator.jpg new file mode 100644 index 0000000..8a3b46c Binary files /dev/null and b/public/images/bookmarks/the-aviator.jpg differ diff --git a/public/images/bookmarks/the-fast-and-the-furious.jpg b/public/images/bookmarks/the-fast-and-the-furious.jpg new file mode 100644 index 0000000..1d4891e Binary files /dev/null and b/public/images/bookmarks/the-fast-and-the-furious.jpg differ diff --git a/public/images/bookmarks/the-grand-budapest-hotel.jpg b/public/images/bookmarks/the-grand-budapest-hotel.jpg new file mode 100644 index 0000000..53a46b7 Binary files /dev/null and b/public/images/bookmarks/the-grand-budapest-hotel.jpg differ diff --git a/public/images/bookmarks/the-green-mile.jpg b/public/images/bookmarks/the-green-mile.jpg new file mode 100644 index 0000000..accc58e Binary files /dev/null and b/public/images/bookmarks/the-green-mile.jpg differ diff --git a/public/images/bookmarks/the-ministry-of-ungentlemanly-warfare.jpg b/public/images/bookmarks/the-ministry-of-ungentlemanly-warfare.jpg new file mode 100644 index 0000000..7707096 Binary files /dev/null and b/public/images/bookmarks/the-ministry-of-ungentlemanly-warfare.jpg differ diff --git a/public/images/bookmarks/the-pragmatic-programmer.jpg b/public/images/bookmarks/the-pragmatic-programmer.jpg new file mode 100644 index 0000000..98edd60 Binary files /dev/null and b/public/images/bookmarks/the-pragmatic-programmer.jpg differ diff --git a/public/images/bookmarks/the-raid-2.jpg b/public/images/bookmarks/the-raid-2.jpg new file mode 100644 index 0000000..dca1aed Binary files /dev/null and b/public/images/bookmarks/the-raid-2.jpg differ diff --git a/public/images/bookmarks/the-raid.jpg b/public/images/bookmarks/the-raid.jpg new file mode 100644 index 0000000..ea335d4 Binary files /dev/null and b/public/images/bookmarks/the-raid.jpg differ diff --git a/public/images/bookmarks/the-shawshank-redemption.jpg b/public/images/bookmarks/the-shawshank-redemption.jpg new file mode 100644 index 0000000..2805cd1 Binary files /dev/null and b/public/images/bookmarks/the-shawshank-redemption.jpg differ diff --git a/public/images/bookmarks/the-social-network.jpg b/public/images/bookmarks/the-social-network.jpg new file mode 100644 index 0000000..aa4558d Binary files /dev/null and b/public/images/bookmarks/the-social-network.jpg differ diff --git a/public/images/bookmarks/the-terminator.jpg b/public/images/bookmarks/the-terminator.jpg new file mode 100644 index 0000000..36b02af Binary files /dev/null and b/public/images/bookmarks/the-terminator.jpg differ diff --git a/public/images/bookmarks/the-truman-show.jpg b/public/images/bookmarks/the-truman-show.jpg new file mode 100644 index 0000000..bfa9908 Binary files /dev/null and b/public/images/bookmarks/the-truman-show.jpg differ diff --git a/public/images/bookmarks/wall-e.jpg b/public/images/bookmarks/wall-e.jpg new file mode 100644 index 0000000..b8832bc Binary files /dev/null and b/public/images/bookmarks/wall-e.jpg differ diff --git a/public/images/bookmarks/when-life-gives-you-tangerines.jpg b/public/images/bookmarks/when-life-gives-you-tangerines.jpg new file mode 100644 index 0000000..008ff7b Binary files /dev/null and b/public/images/bookmarks/when-life-gives-you-tangerines.jpg differ diff --git a/public/images/bookmarks/x-men-first-class.jpg b/public/images/bookmarks/x-men-first-class.jpg new file mode 100644 index 0000000..a545545 Binary files /dev/null and b/public/images/bookmarks/x-men-first-class.jpg differ diff --git a/scripts/fetch-bookmark-images.mjs b/scripts/fetch-bookmark-images.mjs new file mode 100755 index 0000000..15ef760 --- /dev/null +++ b/scripts/fetch-bookmark-images.mjs @@ -0,0 +1,131 @@ +#!/usr/bin/env node +import fs from "fs"; +import https from "https"; +import http from "http"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const root = path.resolve(__dirname, ".."); +const jsonPath = path.join(root, "src/data/bookmarks.json"); +const imgDir = path.join(root, "public/images/bookmarks"); + +fs.mkdirSync(imgDir, { recursive: true }); + +function slugify(title) { + return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""); +} + +function httpGet(url, options = {}) { + return new Promise((resolve, reject) => { + const proto = url.startsWith("https") ? https : http; + proto.get(url, options, resolve).on("error", reject); + }); +} + +function download(url, dest, redirects = 5) { + return new Promise((resolve, reject) => { + if (redirects <= 0) return reject(new Error("Too many redirects")); + const proto = url.startsWith("https") ? https : http; + proto + .get(url, { headers: { "User-Agent": "Mozilla/5.0" } }, (res) => { + if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { + const next = new URL(res.headers.location, url).href; + download(next, dest, redirects - 1).then(resolve).catch(reject); + return; + } + if (res.statusCode !== 200) { + reject(new Error(`HTTP ${res.statusCode}`)); + return; + } + const ct = res.headers["content-type"] || ""; + const ext = ct.includes("png") ? ".png" : ct.includes("webp") ? ".webp" : ".jpg"; + const finalDest = dest + ext; + const ws = fs.createWriteStream(finalDest); + res.pipe(ws); + ws.on("finish", () => { + ws.close(); + resolve("/images/bookmarks/" + path.basename(finalDest)); + }); + ws.on("error", reject); + }) + .on("error", reject); + }); +} + +async function fetchPosterFromOMDB(title, year) { + const query = encodeURIComponent(title); + const url = `https://www.omdbapi.com/?t=${query}&y=${year}&apikey=trilogy`; + try { + const res = await httpGet(url); + let body = ""; + for await (const chunk of res) body += chunk; + const data = JSON.parse(body); + if (data.Poster && data.Poster !== "N/A") return data.Poster; + } catch {} + return null; +} + +function delay(ms) { + return new Promise((r) => setTimeout(r, ms)); +} + +async function main() { + const data = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + let fetched = 0; + let skipped = 0; + let failed = 0; + + for (const item of data) { + const slug = slugify(item.title); + const existing = fs.readdirSync(imgDir).find((f) => f.startsWith(slug + ".")); + if (existing) { + item.image = "/images/bookmarks/" + existing; + skipped++; + continue; + } + + if (item.image && item.image.startsWith("/images/")) { + skipped++; + continue; + } + + let imageUrl = item.image; + if (!imageUrl || imageUrl.startsWith("http")) { + const omdbUrl = await fetchPosterFromOMDB(item.title, item.year); + if (omdbUrl) imageUrl = omdbUrl; + await delay(200); + } + + if (!imageUrl) { + console.error(` SKIP ${item.title}: no image URL found`); + failed++; + continue; + } + + try { + const localPath = await download(imageUrl, path.join(imgDir, slug)); + console.log(` OK ${item.title} -> ${localPath}`); + item.image = localPath; + fetched++; + } catch (e) { + const omdbUrl = await fetchPosterFromOMDB(item.title, item.year); + if (omdbUrl) { + try { + const localPath = await download(omdbUrl, path.join(imgDir, slug)); + console.log(` OK ${item.title} -> ${localPath} (via OMDB fallback)`); + item.image = localPath; + fetched++; + continue; + } catch {} + } + console.error(` FAIL ${item.title}: ${e.message}`); + failed++; + } + } + + fs.writeFileSync(jsonPath, JSON.stringify(data, null, 2) + "\n"); + console.log(`\nDone. Fetched: ${fetched}, Skipped: ${skipped}, Failed: ${failed}`); +} + +main(); diff --git a/src/data/bookmarks.json b/src/data/bookmarks.json new file mode 100644 index 0000000..edf475e --- /dev/null +++ b/src/data/bookmarks.json @@ -0,0 +1,390 @@ +[ + { + "title": "The Pragmatic Programmer", + "author": "David Thomas, Andrew Hunt", + "type": "book", + "year": 2019, + "url": "https://www.goodreads.com/book/show/4099.The_Pragmatic_Programmer", + "image": "/images/bookmarks/the-pragmatic-programmer.jpg" + }, + { + "title": "Designing Data-Intensive Applications", + "author": "Martin Kleppmann", + "type": "book", + "year": 2017, + "url": "https://www.goodreads.com/book/show/23463279-designing-data-intensive-applications", + "image": "/images/bookmarks/designing-data-intensive-applications.jpg" + }, + { + "title": "Clean Code", + "author": "Robert C. Martin", + "type": "book", + "year": 2008, + "url": "https://www.goodreads.com/book/show/3735293-clean-code", + "image": "/images/bookmarks/clean-code.jpg" + }, + { + "title": "The Shawshank Redemption", + "author": "Frank Darabont", + "type": "movie", + "year": 1994, + "url": "https://www.imdb.com/title/tt0111161/", + "image": "/images/bookmarks/the-shawshank-redemption.jpg" + }, + { + "title": "Schindler's List", + "author": "Steven Spielberg", + "type": "movie", + "year": 1993, + "url": "https://www.imdb.com/title/tt0108052/", + "image": "/images/bookmarks/schindlers-list.jpg" + }, + { + "title": "Forrest Gump", + "author": "Robert Zemeckis", + "type": "movie", + "year": 1994, + "url": "https://www.imdb.com/title/tt0109830/", + "image": "/images/bookmarks/forrest-gump.jpg" + }, + { + "title": "The Green Mile", + "author": "Frank Darabont", + "type": "movie", + "year": 1999, + "url": "https://www.imdb.com/title/tt0120689/", + "image": "/images/bookmarks/the-green-mile.jpg" + }, + { + "title": "Interstellar", + "author": "Christopher Nolan", + "type": "movie", + "year": 2014, + "url": "https://www.imdb.com/title/tt0816692/", + "image": "/images/bookmarks/interstellar.jpg" + }, + { + "title": "Oppenheimer", + "author": "Christopher Nolan", + "type": "movie", + "year": 2023, + "url": "https://www.imdb.com/title/tt15398776/", + "image": "/images/bookmarks/oppenheimer.jpg" + }, + { + "title": "The Social Network", + "author": "David Fincher", + "type": "movie", + "year": 2010, + "url": "https://www.imdb.com/title/tt1285016/", + "image": "/images/bookmarks/the-social-network.jpg" + }, + { + "title": "A Beautiful Mind", + "author": "Ron Howard", + "type": "movie", + "year": 2001, + "url": "https://www.imdb.com/title/tt0268978/", + "image": "/images/bookmarks/a-beautiful-mind.jpg" + }, + { + "title": "The Truman Show", + "author": "Peter Weir", + "type": "movie", + "year": 1998, + "url": "https://www.imdb.com/title/tt0120382/", + "image": "/images/bookmarks/the-truman-show.jpg" + }, + { + "title": "The Grand Budapest Hotel", + "author": "Wes Anderson", + "type": "movie", + "year": 2014, + "url": "https://www.imdb.com/title/tt2278388/", + "image": "/images/bookmarks/the-grand-budapest-hotel.jpg" + }, + { + "title": "Joker", + "author": "Todd Phillips", + "type": "movie", + "year": 2019, + "url": "https://www.imdb.com/title/tt7286456/", + "image": "/images/bookmarks/joker.jpg" + }, + { + "title": "WALL-E", + "author": "Andrew Stanton", + "type": "movie", + "year": 2008, + "url": "https://www.imdb.com/title/tt0910970/", + "image": "/images/bookmarks/wall-e.jpg" + }, + { + "title": "The Aviator", + "author": "Martin Scorsese", + "type": "movie", + "year": 2004, + "url": "https://www.imdb.com/title/tt0338751/", + "image": "/images/bookmarks/the-aviator.jpg" + }, + { + "title": "Erin Brockovich", + "author": "Steven Soderbergh", + "type": "movie", + "year": 2000, + "url": "https://www.imdb.com/title/tt0195685/", + "image": "/images/bookmarks/erin-brockovich.jpg" + }, + { + "title": "Green Book", + "author": "Peter Farrelly", + "type": "movie", + "year": 2018, + "url": "https://www.imdb.com/title/tt6966692/", + "image": "/images/bookmarks/green-book.jpg" + }, + { + "title": "Hachi: A Dog's Tale", + "author": "Lasse Hallström", + "type": "movie", + "year": 2009, + "url": "https://www.imdb.com/title/tt1028532/", + "image": "/images/bookmarks/hachi-a-dog-s-tale.jpg" + }, + { + "title": "Léon: The Professional", + "author": "Luc Besson", + "type": "movie", + "year": 1994, + "url": "https://www.imdb.com/title/tt0110413/", + "image": "/images/bookmarks/l-on-the-professional.jpg" + }, + { + "title": "The Terminator", + "author": "James Cameron", + "type": "movie", + "year": 1984, + "url": "https://www.imdb.com/title/tt0088247/", + "image": "/images/bookmarks/the-terminator.jpg" + }, + { + "title": "X-Men: First Class", + "author": "Matthew Vaughn", + "type": "movie", + "year": 2011, + "url": "https://www.imdb.com/title/tt1270798/", + "image": "/images/bookmarks/x-men-first-class.jpg" + }, + { + "title": "Now You See Me", + "author": "Louis Leterrier", + "type": "movie", + "year": 2013, + "url": "https://www.imdb.com/title/tt1670345/", + "image": "/images/bookmarks/now-you-see-me.jpg" + }, + { + "title": "Special 26", + "author": "Neeraj Pandey", + "type": "movie", + "year": 2013, + "url": "https://www.imdb.com/title/tt2377938/", + "image": "/images/bookmarks/special-26.jpg" + }, + { + "title": "Drishyam", + "author": "Nishikant Kamat", + "type": "movie", + "year": 2015, + "url": "https://www.imdb.com/title/tt4430212/", + "image": "/images/bookmarks/drishyam.jpg" + }, + { + "title": "Drishyam 2", + "author": "Abhishek Pathak", + "type": "movie", + "year": 2022, + "url": "https://www.imdb.com/title/tt15501640/", + "image": "/images/bookmarks/drishyam-2.jpg" + }, + { + "title": "Bumblebee", + "author": "Travis Knight", + "type": "movie", + "year": 2018, + "url": "https://www.imdb.com/title/tt4701182/", + "image": "/images/bookmarks/bumblebee.jpg" + }, + { + "title": "The Ministry of Ungentlemanly Warfare", + "author": "Guy Ritchie", + "type": "movie", + "year": 2024, + "url": "https://www.imdb.com/title/tt14128670/", + "image": "/images/bookmarks/the-ministry-of-ungentlemanly-warfare.jpg" + }, + { + "title": "The Raid", + "author": "Gareth Evans", + "type": "movie", + "year": 2011, + "url": "https://www.imdb.com/title/tt1899353/", + "image": "/images/bookmarks/the-raid.jpg" + }, + { + "title": "The Raid 2", + "author": "Gareth Evans", + "type": "movie", + "year": 2014, + "url": "https://www.imdb.com/title/tt2265171/", + "image": "/images/bookmarks/the-raid-2.jpg" + }, + { + "title": "Einstein and Eddington", + "author": "Philip Martin", + "type": "movie", + "year": 2008, + "url": "https://www.imdb.com/title/tt0995036/", + "image": "/images/bookmarks/einstein-and-eddington.jpg" + }, + { + "title": "Nuremberg", + "author": "Yves Simoneau", + "type": "movie", + "year": 2000, + "url": "https://www.imdb.com/title/tt0208629/", + "image": "/images/bookmarks/nuremberg.jpg" + }, + { + "title": "The Fast and the Furious", + "author": "Rob Cohen", + "type": "movie", + "year": 2001, + "url": "https://www.imdb.com/title/tt0232500/", + "image": "/images/bookmarks/the-fast-and-the-furious.jpg" + }, + { + "title": "Chainsaw Man the Movie: Reze Arc", + "author": "MAPPA", + "type": "anime", + "year": 2025, + "image": "/images/bookmarks/chainsaw-man-the-movie-reze-arc.jpg" + }, + { + "title": "Mr. Robot", + "author": "Sam Esmail", + "type": "show", + "year": 2015, + "url": "https://www.imdb.com/title/tt4158110/", + "image": "/images/bookmarks/mr-robot.jpg" + }, + { + "title": "Silicon Valley", + "author": "Mike Judge", + "type": "show", + "year": 2014, + "url": "https://www.imdb.com/title/tt2575988/", + "image": "/images/bookmarks/silicon-valley.jpg" + }, + { + "title": "Masters of the Air", + "author": "John Shiban, John Orloff", + "type": "show", + "year": 2024, + "url": "https://www.imdb.com/title/tt2640044/", + "image": "/images/bookmarks/masters-of-the-air.jpg" + }, + { + "title": "Blue Eye Samurai", + "author": "Amber Noizumi, Michael Green", + "type": "anime", + "year": 2023, + "url": "https://www.imdb.com/title/tt13309742/", + "image": "/images/bookmarks/blue-eye-samurai.jpg" + }, + { + "title": "My Love from the Star", + "author": "Jang Tae-yoo", + "type": "show", + "year": 2013, + "url": "https://www.imdb.com/title/tt3199438/", + "image": "/images/bookmarks/my-love-from-the-star.jpg" + }, + { + "title": "When Life Gives You Tangerines", + "author": "Im Hyun-wook", + "type": "show", + "year": 2025, + "image": "/images/bookmarks/when-life-gives-you-tangerines.jpg" + }, + { + "title": "Midnight Diner", + "author": "Joji Matsuoka", + "type": "show", + "year": 2009, + "url": "https://www.imdb.com/title/tt5765544/", + "image": "/images/bookmarks/midnight-diner.jpg" + }, + { + "title": "Panchayat", + "author": "Deepak Kumar Mishra", + "type": "show", + "year": 2020, + "url": "https://www.imdb.com/title/tt11247028/", + "image": "/images/bookmarks/panchayat.jpg" + }, + { + "title": "Attack on Titan", + "author": "Hajime Isayama", + "type": "anime", + "year": 2013, + "url": "https://www.imdb.com/title/tt2560140/", + "image": "/images/bookmarks/attack-on-titan.jpg" + }, + { + "title": "Death Note", + "author": "Tsugumi Ohba, Takeshi Obata", + "type": "anime", + "year": 2006, + "url": "https://www.imdb.com/title/tt0877057/", + "image": "/images/bookmarks/death-note.jpg" + }, + { + "title": "Demon Slayer", + "author": "Koyoharu Gotouge", + "type": "anime", + "year": 2019, + "url": "https://www.imdb.com/title/tt9335498/", + "image": "/images/bookmarks/demon-slayer.jpg" + }, + { + "title": "Solo Leveling", + "author": "Chugong", + "type": "anime", + "year": 2024, + "url": "https://www.imdb.com/title/tt21209876/", + "image": "/images/bookmarks/solo-leveling.jpg" + }, + { + "title": "Sakamoto Days", + "author": "Yuto Suzuki", + "type": "anime", + "year": 2025, + "image": "/images/bookmarks/sakamoto-days.jpg" + }, + { + "title": "One Punch Man", + "author": "ONE", + "type": "anime", + "year": 2015, + "url": "https://www.imdb.com/title/tt4508902/", + "image": "/images/bookmarks/one-punch-man.jpg" + }, + { + "title": "Orb: On the Movements of the Earth", + "author": "Uoto", + "type": "anime", + "year": 2024, + "image": "/images/bookmarks/orb-on-the-movements-of-the-earth.jpg" + } +] diff --git a/src/pages/bookmarks.astro b/src/pages/bookmarks.astro new file mode 100644 index 0000000..647ada9 --- /dev/null +++ b/src/pages/bookmarks.astro @@ -0,0 +1,327 @@ +--- +import BaseLayout from "@/layouts/BaseLayout.astro"; +import bookmarksData from "@/data/bookmarks.json"; + +interface Bookmark { + title: string; + author: string; + type: "book" | "movie" | "show" | "anime"; + year: number; + url?: string; + image?: string; + note?: string; + favorite?: boolean; +} + +const bookmarks = (bookmarksData as Bookmark[]).sort((a, b) => b.year - a.year); + +const typeLabels: Record = { + book: "Books", + movie: "Movies", + show: "Shows", + anime: "Anime", +}; + +const types = ["book", "movie", "show", "anime"] as const; + +const bookCount = bookmarks.filter((b) => b.type === "book").length; +const movieCount = bookmarks.filter((b) => b.type === "movie").length; +const showCount = bookmarks.filter((b) => b.type === "show").length; +const animeCount = bookmarks.filter((b) => b.type === "anime").length; +--- + + +
+
+

Bookmarks

+

+ Books, movies, shows, and anime I think are worth your time. Starred entries are personal favorites. +

+
+ +
+ + + + + +
+ + +
+
+ + + +