React
-TypeScript
- - +Svelte
- - +NextJS
- - +Remix
- - +GraphQL
- - +Prisma
- - +Gatsby
- - +Docker
- + clazz="center" + icon={Docker} + />- Currently traveling around the world! + Living it up in Mountain View
Traveling around
+Mountain View
Bringing these two cats, Turnip and Taco, along for the ride.
+Hanging out with these two cats, Turnip and Taco.
Turnip
Turnip
{itemText}
+ + + diff --git a/src/routes/about/course.json b/src/routes/about/course.json new file mode 100644 index 0000000..3014bf9 --- /dev/null +++ b/src/routes/about/course.json @@ -0,0 +1,88 @@ +{ + "courses": [ + { + "name": "Wes Bos", + "externalLinks": [ + { + "ariaLabel": "Wes Bos Courses", + "href": "https://wesbos.com/courses", + "showIcon": true, + "text": "Wes Bos" + } + ], + "tags": ["React", "GraphQL", "Gatsby", "JavaScript"] + }, + { + "name": "Scott Tolinski", + "externalLinks": [ + { + "ariaLabel": "Scott Tolinski", + "href": "https://www.scotttolinski.com", + "showIcon": true, + "text": "Scott Tolinski" + }, + { + "ariaLabel": "Levelup Tutorials", + "href": "https://levelup.video", + "showIcon": true, + "text": "Levelup Tutorials" + } + ], + "tags": ["React", "TypeScript", "Svelte Kit", "Remix", "Figma", "Design Systems"] + }, + { + "name": "Josh Comeau", + "externalLinks": [ + { + "ariaLabel": "Josh Comeau", + "href": "https://www.joshwcomeau.com", + "showIcon": true, + "text": "Josh Comeau" + }, + { + "ariaLabel": "The Joy of React", + "href": "https://www.joyofreact.com/", + "showIcon": true, + "text": "The Joy of React" + } + ], + "tags": ["Full Stack React", "NextJS"] + }, + { + "name": "Amy Kapernick", + "externalLinks": [ + { + "ariaLabel": "Amy Kapernick", + "href": "https://www.amyskapers.dev/", + "showIcon": true, + "text": "Amy Kapernick" + } + ], + "tags": ["Accessibility for Everyone"] + }, + { + "name": "Andrew Mead", + "externalLinks": [ + { + "ariaLabel": "Andrew Mead on Udemy", + "href": "https://www.udemy.com/user/andrewmead/", + "showIcon": true, + "text": "Andrew Mead" + } + ], + "tags": ["GraphQL", "Apollo", "Prisma"] + }, + { + "name": "Steven Grider", + "externalLinks": [ + { + "ariaLabel": "Steven Grider on Udemy", + "href": "https://www.udemy.com/user/sgslo/", + "showIcon": true, + "text": "Steven Grider" + } + ], + "tags": ["React", "Redux", "Docker", "GraphQL", "CSS", "HTML", "JavaScript"] + } + ] +} diff --git a/src/routes/api.ts b/src/routes/api.ts index 1a133cd..5d9ecc2 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -10,7 +10,7 @@ import { USE_REDIS_CACHE } from '$env/static/private'; import intersect from 'just-intersect'; -import type { Article, WallabagArticle } from '$lib/types/article'; +import type { Article, ArticlePageLoad, WallabagArticle } from '$lib/types/article'; import { ArticleTag } from '$lib/types/articleTag'; import type { PageQuery } from '$lib/types/pageQuery'; import { URLSearchParams } from 'url'; @@ -38,14 +38,12 @@ export async function fetchArticlesApi( since: `${pageQuery.since}`, page: `${pageQuery.page}` }); - // console.log(`Entries params: ${entriesQueryParams}`); if (USE_REDIS_CACHE) { const cached = await redis.get(entriesQueryParams.toString()); if (cached) { const response = JSON.parse(cached); - // console.log('Cache hit!'); const ttl = await redis.ttl(entriesQueryParams.toString()); return { ...response, cacheControl: `max-age=${ttl}` }; @@ -79,19 +77,12 @@ export async function fetchArticlesApi( throw new Error(pageResponse.statusText); } - const cacheControl = pageResponse.headers.get('cache-control'); + const cacheControl = pageResponse.headers.get('cache-control') || 'no-cache'; const { _embedded, page, pages, total, limit } = await pageResponse.json(); const articles: Article[] = []; - // do { - // nbEntries += entries._embedded.items.length; - // console.log(`number of articles fetched: ${_embedded.items.length}`); _embedded.items.forEach((article: WallabagArticle) => { - // if (articles?.length === +WALLABAG_MAX_ARTICLES) { - // console.log('Reached 30 articles'); - // return; - // } const rawTags = article?.tags?.map((tag) => tag.slug); if (intersect(rawTags, Object.values(ArticleTag))?.length > 0) { const tags = rawTags.map((rawTag) => rawTag as unknown as ArticleTag); @@ -110,7 +101,7 @@ export async function fetchArticlesApi( } }); - const responseData = { + const responseData: ArticlePageLoad = { articles, currentPage: page, totalPages: pages > +WALLABAG_MAX_PAGES ? +WALLABAG_MAX_PAGES : pages, diff --git a/src/routes/api/articles/+server.ts b/src/routes/api/articles/+server.ts index ea8c1f0..ad6de07 100644 --- a/src/routes/api/articles/+server.ts +++ b/src/routes/api/articles/+server.ts @@ -1,14 +1,14 @@ import { json, error } from '@sveltejs/kit'; import { WALLABAG_MAX_PAGES } from '$env/static/private'; -import type { RequestHandler, RequestEvent } from './$types'; import { fetchArticlesApi } from '$root/routes/api'; -export const GET: RequestHandler = async ({ setHeaders, url }: RequestEvent) => { +export async function GET({ setHeaders, url }) { + const page = url?.searchParams?.get('page') || '1'; + if (+page > +WALLABAG_MAX_PAGES) { + error(404, 'Page does not exist'); + } + try { - const page = url?.searchParams?.get('page') || '1'; - if (+page > +WALLABAG_MAX_PAGES) { - throw new Error('Page does not exist'); - } const response = await fetchArticlesApi('get', `fetchArticles`, { page, limit: url?.searchParams?.get('limit') || '6' @@ -27,11 +27,10 @@ export const GET: RequestHandler = async ({ setHeaders, url }: RequestEvent) => } } - // console.log(`API response ${JSON.stringify(response)}`); return json(response); } } catch (e) { console.error(e); - throw error(404, 'Page does not exist'); + error(404, 'Page does not exist'); } }; diff --git a/src/routes/articles/+page.ts b/src/routes/articles/+page.ts index 4f6aabd..3ff96b5 100644 --- a/src/routes/articles/+page.ts +++ b/src/routes/articles/+page.ts @@ -1,6 +1,5 @@ import { redirect } from '@sveltejs/kit'; -import type { PageServerLoad } from './$types'; export const load = async () => { - throw redirect(302, '/articles/1'); + redirect(302, '/articles/1'); }; diff --git a/src/routes/articles/[page]/+page.server.ts b/src/routes/articles/[page]/+page.server.ts index 585ba4b..ccd8a50 100644 --- a/src/routes/articles/[page]/+page.server.ts +++ b/src/routes/articles/[page]/+page.server.ts @@ -2,23 +2,15 @@ import { error } from '@sveltejs/kit'; import type { PageServerLoad } from './$types'; import { WALLABAG_MAX_PAGES } from '$env/static/private'; import { PUBLIC_SITE_URL } from '$env/static/public'; -import type { Article } from '$lib/types/article'; - -export type ArticlePageLoad = { - articles: Article[]; - currentPage: number; - totalPages: number; - limit: number; - totalArticles: number; - cacheControl: string; -}; +import type { ArticlePageLoad } from '$lib/types/article'; +import type { MetaTagsProps } from 'svelte-meta-tags'; export const load: PageServerLoad = async ({ fetch, params, setHeaders, url }) => { const { page } = params; if (+page > +WALLABAG_MAX_PAGES) { - throw error(404, { - message: 'Not found' - }); + error(404, { + message: 'Not found' + }); } const resp = await fetch(`/api/articles?page=${page}`); const { articles, currentPage, totalPages, limit, totalArticles, cacheControl }: ArticlePageLoad = diff --git a/src/routes/og/+server.ts b/src/routes/og/+server.ts index 76eaa60..56ec447 100644 --- a/src/routes/og/+server.ts +++ b/src/routes/og/+server.ts @@ -1,16 +1,10 @@ -import type { RequestHandler } from '@sveltejs/kit'; -import satori from 'satori'; -import { Resvg } from '@resvg/resvg-js'; -import { html as toReactNode } from 'satori-html'; -import FiraSansSemiBold from '$lib/fonts/FiraSans-SemiBold.ttf'; import SocialImageCard from '$lib/components/socialImageCard.svelte'; -import { dev } from '$app/environment'; import { componentToPng } from '$root/lib/renderImage'; const height = 630; const width = 1200; -export const GET: RequestHandler = async ({ url }) => { +export async function GET({ url }) { try { const ogImage = `${new URL(url.origin).href}/b_shell_nut_favicon.png`; const header = url.searchParams.get('header') ?? undefined; @@ -22,11 +16,11 @@ export const GET: RequestHandler = async ({ url }) => { page, content, image: ogImage, - width, - height, + width: `${width}`, + height: `${height}`, url: new URL(url.origin).href }, height, width); } catch (e) { console.error(e); } -}; +} diff --git a/svelte.config.js b/svelte.config.js index 777a581..abfc5c2 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,5 +1,5 @@ import adapter from '@sveltejs/adapter-vercel'; -import { vitePreprocess } from '@sveltejs/kit/vite'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; import { preprocessMeltUI } from '@melt-ui/pp'; import { mdsvex } from 'mdsvex'; import mdsvexConfig from './mdsvex.config.js';