josh-collinsworth / joco-sveltekit

The home of my static SvelteKit site.
https://joshcollinsworth.com
70 stars 14 forks source link

blog/build-static-sveltekit-markdown-blog #9

Open utterances-bot opened 2 years ago

utterances-bot commented 2 years ago

Let's learn SvelteKit by building a static Markdown blog from scratch - Josh Collinsworth blog

Learn the fundamentals of SvelteKit by building a statically generated blog from scratch, with Markdown support, Sass, an API, and an RSS feed.

https://joshcollinsworth.com/blog/build-static-sveltekit-markdown-blog

sleepykew commented 1 year ago

Great post! I followed along before the breaking changes and I'm now using this post to understand the svelteKit updates better(along with your other recent post on the topic) - its going well, thank you for this content!

Since the update, I noticed the transitions don't seem to have the same behavior. Example: You can see the footer flickering when switching between the 'About' and 'Contact' page on your demo (zoom out depending on screen size). Previously this sort of flickering didn't happen. I have a similar svelteKit app that I'm trying to manually convert and the animation jank is more noticeable.

Curious if you have any input, or if this is a svelteKit issue. Cheers!

josh-collinsworth commented 1 year ago

@seepeekew The only browser I see the issue in is Safari, so I would guess it must be a Svelte issue that needs to be addressed in Webkit specifically. (Or…just a Safari issue. But there's probably a way to fix it in Svelte, I'd guess.)

aquacalc commented 1 year ago

Very useful contribution, Josh. Thanks for putting in the time & effort to update your original tutorial to account for the most recent breaking changes -- that has saved me a lot of time.

aquacalc commented 1 year ago

With dynamic routing (Approach 2), Svelte components imported into a post’s .md file are not reactive.

e.g., I put the simple “Bindings / Text inputs” example in a Svelte component, imported it in a post .md file, and used it as <TestComponent />.

That component is displayed and its input element is enabled, but values entered in the input element do not update the reactive variable (wrapped in an <h1>).

I assume this is owed to the load function in src/routes/blog/[posts]/+page.server.js, the PostContent of which, post.default.render().html, is returned to +page.svelte as static html.

As the same Svelte component works as expected in .md files structured as individual posts (Approach 1), I’m going with that bulkier solution for now.

But is there a way to modify the load function to use dynamic routing without losing an imported Svelte component’s reactive behavior?

ajbajbajb commented 1 year ago

Does anyone notice an issue with the 'date' sorting function?

My api throws an error of 'Cannot read properties of undefined (reading 'date')', even if I can read all the dates in the api and as console.logs.

It's the only thing wrong now...

pjebs commented 1 year ago

How would this work with SEO?

ebnsina commented 1 year ago

How do I get actual content of this?

export async function load({ params }) {
    const post = await import(`../${params.slug}.md`);
    const { title, date } = post.metadata;
    const content = post.default;

    console.log(content);

    return {
        title,
        date,
        content
    };
}
brentdanley commented 1 year ago

This is an excellent post. Well-written; very clear. Thank you!

jessycormier commented 1 year ago

Hey Josh, it looks like Vite Process CSS handles sass/scss so no need for some of the steps written in the blog post about it.}

For others, you can read more about it here: https://vitejs.dev/guide/features.html#css-pre-processors

TLDR; just install the style preprocessor you want to use npm add -D sass and vitePreprocess will take care of the rest.

(this was tested in v1.0.0 of svelte kit)

ChristerNilsson commented 1 year ago

I compared the volume increase of some markdown files. My 23 files went from 41kB .md to 405kB .js files, a tenfold increase! Prolly unnecessary as .md can be expanded by the client, on the fly. Using adapter-static. As .html is not used, I predict there will be issues, adding ten yo legacy .html files, with very lax syntax.

xenogew commented 1 year ago

prefetch and prefetchRoutes might be changed in latest version.

https://kit.svelte.dev/docs/migrating#pages-and-layouts-imports

wrex commented 1 year ago

Just wanted to add my thanks to the crowd. Awesome post. Extremely helpful and thanks for updating!

I initially went with option 2 for markdown content and then realized I had to import any components I used in the +page.svelte as well as the mdsvex source itself. Just sucking everything into {@html ...} felt wrong somehow, anyway (I used a server load so couldn't use svelte:component).

Then I realized I like to keep source images in the same folder as my markdown anyway (and preprocess with vite-imagetools). So option 1 made more sense anyway!

Zielak commented 1 year ago

Thanks a lot for that post, It helped me get started with migrating a blog from Gatsby to SvelteKit!

One thing I found missing was ability to present excerpt of a post in blog listing, eg. by marking <!--more--> in post content. I got used to it from way back with Wordpress and found a lib in Gatsby, but couldn't find anything similar in Svelte world.

So I made the lib :) : https://github.com/Zielak/mdsvex-excerpt

Honestly, I'm wondering if people still do excerpt on their blogs.

szymonhernik commented 1 year ago

How do I get the actual content of the post displayed on the page with listed posts?

lakebayagency commented 1 year ago

This is an awesome project! Thanks for making it available to all!

dmorgorg commented 1 year ago

Just revisited the site after a while; still as helpful as ever! And thanks for keeping it updated.

I had to install prismic-themes for any styling of code blocks

Thanks again; this is my favourite Sveltekit tutorial and it has taught me a lot! :)

harunzafer commented 1 year ago

How can we escape angle brackets in markdown files? I've tried tried < > and other options but each gave me a parsing error like "Unexpected token". < works but looks like code :)

taffarel55 commented 1 year ago

Awesome!! :smiley:

connectedblue commented 1 year ago

Just a fabulous article Josh. This is exactly what I need for my project, so I'm going to go through it again with my actual site and content to build a prototype

zmccj commented 1 year ago

This is AWESOME !!! Thank you Josh!

fabriziofeitosa commented 1 year ago

I really enjoyed the content! I learned a lot.

Does anyone have an example of how to apply pagination?

kerbless commented 1 year ago

Absolutely loved the tutorial, I'm a newbie and I'm trying to understand the index.js used to import the MD files, I played around with the code and ended up with this:

var MDs = new Object;
    for (const [path, importFunc] of Object.entries(import.meta.glob(`/src/routes/diaryof/*.md`))) { // The `...` is a template literal, how cool!
        let data = await importFunc()
        MDs[path.slice(11, -3)] = data.metadata
    }

is this a valid alternative to the mapping function or do I have to study promises better?

burkekbur commented 1 year ago

I have a build problem after importing a static adapter.

@sveltejs/adapter-static: all routes must be fully prerenderable, but found the following routes that are dynamic:

Is your guide complete? Works that static adapter with approach 2?

git-no commented 1 year ago

@josh-collinsworth FYI With Contentlayer implementation and handling of markdown files is much easier.

Maratzz commented 1 year ago

Thank you so much for this article Josh, it helped me figure out some SvelteKit concepts, it's an amazing tool! Do you mind if I translate your article in French, with full credits and link here of course? The ressources outside the English environment are quite lacking to say the least.

There's something I couldn't wrap my head around using the API endpoint and filtering. I wanted to create a single API endpoint listing all the posts regardless of where they are by modifying const allPostFiles = import.meta.glob('/src/routes/blog/*.md') to const allPostFiles = import.meta.glob('/src/routes/*/*.md') and from then using some kind of filtering to display them in their correct routes according to the categories, but I can't figure out how or where I should do that. Can you point me in the right direction?

EDIT: I figured it out, I was trying to apply filter() before receiving the response.json().

josh-collinsworth commented 1 year ago

@Maratzz Glad you were able to figure it out. :) And yes, you're welcome to translate content with attribution. Thanks!

kapitalisman commented 1 year ago

Hi Josh, thank you so much for this tutorial. I am trying to use an alias for dynamic routing:

const post = await import(`$posts/${params.slug}.md`)

where I configured $posts in svelte.config.js as $posts: './src/posts'. This avoids a relative path like ./../../../posts. However, this doesn't seem to be working. Can you help me out here?

kapitalisman commented 1 year ago

Hi Josh, another question. I tried adding the scss :where(h2, h3, h4, h5, h6) code block to a <style lang="scss"> tag inside +page.svelte in the /blog/[slug] folder. Can't we do this? Does it have to be inside $lib/styles/style.scss?

BarbarianTarkus commented 12 months ago

This is Incredible, thank you very much

leokolt commented 11 months ago

Is super content. Thanks

leokolt commented 11 months ago

Hi. Can you tell me how to make articles that have the draft: true parameter added to the frontmetter do not appear at all. I added this to the api/posts/server.js and articles are not displayed in the blog, but the article itself is available by url

import { getMarkdownPosts } from '$lib/utils/getPosts'
import { json } from '@sveltejs/kit'

export const GET = async () => {
  const allPosts = await getMarkdownPosts()

  const notDraftPosts = allPosts.filter(post => post.meta.draft === false)

  const sortedPosts = notDraftPosts.sort((a, b) => {
    return new Date(b.meta.date) - new Date(a.meta.date)
  })

  return json(sortedPosts)
}
rogerpence commented 11 months ago

This is a great post. Thank you very much! It is very helpful.

Mellifico commented 10 months ago

Thank you so much, this is so useful ! But, I just can't understand how "resolver" works ; "resolve" exists in the doc but not "resolver". Could you explain that to a brave neophyte like me, please ?

torb-no commented 10 months ago

Sorry if this is a very novice question (it's been a while since I've used Node). You save all of npm packages to devDependencies (as opposed to just dependencies). Is this because SvelteKit generates what should run in production for you? Reason I ask is that I always want to understand the why of everything I'm doing.

Thanks for a great and detail guide! I'm using it to get my blog on to SvelteKit (and learn it in the process). I really appreciate that you explain why and how you are doing things, making it possible for me to use that understanding to solve things the way I want and not blindly follow the tutorial.

josh-collinsworth commented 9 months ago

@leokolt You can see how I handle hiding post drafts here: josh-collinsworth/joco-sveltekit/src/lib/assets/js/utils/fetchPosts.ts


@Mellifico "Resolver" is just my own word. When you import a markdown file, you get an object where the key is the path to the file, and the value is a function that generates its content, something like this:

{
  '/blog/my-post.md': asyncFunctionThatGetsThisPostsContent()
}

I just call that function "resolver" because you have to assign it a name when looping over the entries. You could call it whatever you want. It's just a function that runs asynchronously and (eventually) returns all of the details of the post for you.


@torb-no My understanding is: devDependencies is for things that are required to either help with development (like eslint, prettier, a dev server), or things that help with building and compilation. These are dependencies that, in other words, help the site get built, but not that actually run on the production site.

Sass is a good example; Sass does not run on the live website, since by the time you get the code to production, all the Sass code has been compiled away to pure CSS. So setting something as a devDependency signals to the build step that the package is not needed in production.

josean-dev commented 9 months ago

Such a good article!

jason-johnson commented 8 months ago

I'm trying to follow through the tutorial and I've run into an issue: after I install mdsvex and modify svelte.config.js, I created a +page.md file as instructed but now it fails with this error:

Files prefixed with + are reserved (saw src/routes/uses/+pages.md)

I'm using vitePreprocess (seems to come default that way now) but I switched to sveltePreprocess to check and it didn't change anything. I've stopped the server (it restarts automatically when it sees the config change, but just to be sure) and started it again but that doesn't fix it.

kaiwen-wang commented 6 months ago

Assuming you're starting from scratch, #1 seems useful if you want to colocate markdown files with images. But it can be annoying since you have to name the path and the file title. In #2 you'd have to name the .md file and the title which might as well be the same as naming the folder and title. So you end up naming two things either way.

kaiwen-wang commented 6 months ago

btw: think

If you followed approach #1 above and have every post inside its own individual folder, you'll need to change the import path to end /blog/*/.md, to go one level deeper.

should be: /blog/**/*.md

RIGIK93 commented 3 days ago

I Loved it! Your tutorial really helped with my blog, thank you!