From 66c3fdbf2359515481da4c8a34a2f5c444586c2b Mon Sep 17 00:00:00 2001 From: scosman Date: Wed, 28 Feb 2024 21:13:58 -0500 Subject: [PATCH 1/3] Cleanup blog engine: - Posts into typescript - Post type into non-global - Remove repeated date parsing code - Remove repeated sorting code - Proper 404 errors on bad urls --- README.md | 4 +- src/ambient.d.ts | 8 --- .../(marketing)/blog/(posts)/+layout.svelte | 20 +++---- src/routes/(marketing)/blog/+page.svelte | 20 +------ src/routes/(marketing)/blog/posts.json | 26 ---------- src/routes/(marketing)/blog/posts.ts | 52 +++++++++++++++++++ .../(marketing)/blog/rss.xml/+server.ts | 20 +------ 7 files changed, 64 insertions(+), 86 deletions(-) delete mode 100644 src/routes/(marketing)/blog/posts.json create mode 100644 src/routes/(marketing)/blog/posts.ts diff --git a/README.md b/README.md index b8ffac87..651cadbd 100644 --- a/README.md +++ b/README.md @@ -227,13 +227,13 @@ After the steps above, you’ll have a working version like the demo page. Howev - Content - Add actual content for marketing homepage - Add actual content for your blog (or delete the blog) - - Update all fields in `src/routes/(marketing)/blog/posts.json`, and replace the post pages under `src/routes/(marketing)/blog/posts` to align to the urls from posts.json. + - Update all fields in `src/routes/(marketing)/blog/posts.ts`, and replace the post pages under `src/routes/(marketing)/blog/posts` to align to the urls from `posts.ts`. - Alternatively remove the blog by removing the src/routes/(marketing)/blog directory, and remove any links to the blog in the header and footer. You can always bring it back later. - Add any pages you want on top of our boiler plate (about, terms of service, etc). Be sure to add links to them in the header, mobile menu header, and footer as appropriate (`src/routes/(marketing)/+layout.svelte`). - Note: if you add any dynamic content to the main marketing page, pricing page or blog, be sure to set `prerender = false` in the appropriate `+page.ts` file. These are currently pre-rendered and served as static assets for performance reasons, but that will break if you add server side rendering requirements. - Update SEO content - Update title and meta description tags for every public page. We include generic ones using your site name (PUBLIC_SITE_NAME), but the more specific these are the better. - - This done automatically for blog posts from `posts.json` metadata + - This done automatically for blog posts from `posts.ts` metadata - Style - Create a new DaisyUI Theme matching your brand or use one of the built in themes from DaisyUI (see `tailwind.config.js`) - Update the marketing page layout `src/routes/(marketing)/+layout.svelte`: customize design, delete unwanted pages from header and footer diff --git a/src/ambient.d.ts b/src/ambient.d.ts index 686ab845..a637375f 100644 --- a/src/ambient.d.ts +++ b/src/ambient.d.ts @@ -7,14 +7,6 @@ declare global { website?: string email?: string } - - type Post = { - link: string - date: string // date is a string 'YYYY-MM-DD' - title: string - description: string - parsedDate?: Date // Optional because it's added dynamically - } } export {} diff --git a/src/routes/(marketing)/blog/(posts)/+layout.svelte b/src/routes/(marketing)/blog/(posts)/+layout.svelte index 89c3ef5c..0f51551d 100644 --- a/src/routes/(marketing)/blog/(posts)/+layout.svelte +++ b/src/routes/(marketing)/blog/(posts)/+layout.svelte @@ -1,9 +1,10 @@ diff --git a/src/routes/(marketing)/blog/+page.svelte b/src/routes/(marketing)/blog/+page.svelte index f4b50ee1..0d973c40 100644 --- a/src/routes/(marketing)/blog/+page.svelte +++ b/src/routes/(marketing)/blog/+page.svelte @@ -1,21 +1,5 @@ @@ -42,7 +26,7 @@
A demo blog with sample content.
- {#each sortedPosts as post} + {#each sortedBlogPosts as post}
diff --git a/src/routes/(marketing)/blog/posts.json b/src/routes/(marketing)/blog/posts.json deleted file mode 100644 index 29e7895b..00000000 --- a/src/routes/(marketing)/blog/posts.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "blogInfo": { - "name": "SaaS Starter Blog", - "description": "A sample blog" - }, - "postList": [ - { - "title": "Example Blog Post 2", - "description": "Even more example content!", - "link": "/blog/awesome_post", - "date": "2022-9-23" - }, - { - "title": "How to build a SaaS Webpage in 12 easy steps", - "description": "A getting started guide for saas websites.", - "link": "/blog/how_to_build_saas_page", - "date": "2022-12-26" - }, - { - "title": "Example Blog Post", - "description": "A sample blog post, showing our blog engine", - "link": "/blog/example_blog_post", - "date": "2023-03-13" - } - ] -} diff --git a/src/routes/(marketing)/blog/posts.ts b/src/routes/(marketing)/blog/posts.ts new file mode 100644 index 00000000..064c93df --- /dev/null +++ b/src/routes/(marketing)/blog/posts.ts @@ -0,0 +1,52 @@ +export const blogInfo = { + name: "SaaS Starter Blog", + description: "A sample blog", +} + +export type BlogPost = { + link: string + date: string // date is a string 'YYYY-MM-DD' + title: string + description: string + parsedDate?: Date // Optional because it's added dynamically +} + +// Update this list with the actual blog post list +// Create a page in the "(posts)" directory for each entry +const blogPosts: BlogPost[] = [ + { + title: "Example Blog Post 2", + description: "Even more example content!", + link: "/blog/awesome_post", + date: "2022-9-23", + }, + { + title: "How to build a SaaS Webpage in 12 easy steps", + description: "A getting started guide for saas websites.", + link: "/blog/how_to_build_saas_page", + date: "2022-12-26", + }, + { + title: "Example Blog Post", + description: "A sample blog post, showing our blog engine", + link: "/blog/example_blog_post", + date: "2023-03-13", + }, +] + +// Parse post dates from strings to Date objects +for (const post of blogPosts) { + if (!post.parsedDate) { + const dateParts = post.date.split("-") + post.parsedDate = new Date( + parseInt(dateParts[0]), + parseInt(dateParts[1]) - 1, + parseInt(dateParts[2]), + ) // Note: months are 0-based + } +} + +export const sortedBlogPosts = blogPosts.sort( + (a: BlogPost, b: BlogPost) => + (b.parsedDate?.getTime() ?? 0) - (a.parsedDate?.getTime() ?? 0), +) diff --git a/src/routes/(marketing)/blog/rss.xml/+server.ts b/src/routes/(marketing)/blog/rss.xml/+server.ts index 96d3936d..82b77e4c 100644 --- a/src/routes/(marketing)/blog/rss.xml/+server.ts +++ b/src/routes/(marketing)/blog/rss.xml/+server.ts @@ -1,6 +1,4 @@ -import { postList, blogInfo } from "../posts.json" - -const typedPostList: Post[] = postList as Post[] +import { sortedBlogPosts, blogInfo } from "../posts" export const prerender = true @@ -25,21 +23,7 @@ export function GET({ url }) { ${url.origin}/blog ${blogInfo.description} ` - for (const post of typedPostList) { - const dateParts = post.date.split("-") - post.parsedDate = new Date( - parseInt(dateParts[0]), - parseInt(dateParts[1]) - 1, - parseInt(dateParts[2]), - ) // Note: months are 0-based - } - const sortedPosts = typedPostList.sort((a, b) => { - const parsedDateA = a.parsedDate || new Date(0) - const parsedDateB = b.parsedDate || new Date(0) - return parsedDateB.getTime() - parsedDateA.getTime() - }) - - for (const post of sortedPosts) { + for (const post of sortedBlogPosts) { body += ` ${encodeXML(post.title)} From d883254cfbd511b92f29765eaba3858722e6d350 Mon Sep 17 00:00:00 2001 From: scosman Date: Wed, 28 Feb 2024 21:15:17 -0500 Subject: [PATCH 2/3] Fix error page background color. --- src/routes/+error.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index 057731f1..872198cb 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -3,7 +3,7 @@ import { page } from "$app/stores" -
+

This is embarassing...

From d7fe7881c307b9645e9b80585309c5cdeab1f3e2 Mon Sep 17 00:00:00 2001 From: scosman Date: Wed, 28 Feb 2024 21:20:21 -0500 Subject: [PATCH 3/3] Don't pre-render the rss. Need the domain origin which isn't available at pre-render time. --- src/routes/(marketing)/blog/rss.xml/+server.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/routes/(marketing)/blog/rss.xml/+server.ts b/src/routes/(marketing)/blog/rss.xml/+server.ts index 82b77e4c..6a11fd12 100644 --- a/src/routes/(marketing)/blog/rss.xml/+server.ts +++ b/src/routes/(marketing)/blog/rss.xml/+server.ts @@ -1,7 +1,5 @@ import { sortedBlogPosts, blogInfo } from "../posts" -export const prerender = true - const encodeXML = (str: string) => str .replace(/&/g, "&")