Create a folder for components and a file in for the posts:
# make components folder
mkdir src/lib/components
# create the component file
touch src/lib/components/post-card.svelte
All the contents of the each
block can be abstracted out into it’s own component for reuse in the project.
<section>
<img alt={post.title} src={post.coverImage.url} />
<a href={`/posts/${post.slug}`}>
<div>
<h2>{post.title}</h2>
{#if post.tags}
{#each post.tags as tag}
<span>{tag}</span>
{/each}
{/if}
<p>{post.excerpt.slice(0, 80)}...</p>
</div>
</a>
</section>
The component will need to have a prop passed to it for the post, the inferred types have been changed from any
to string
:
<script>
/**
* @type {{ title: string; coverImage: { url: string; }; slug: string; tags: string[]; excerpt: string | unknown[]; }}
*/
export let post;
</script>
<section>
<img alt={post.title} src={post.coverImage.url} />
<a href={`/posts/${post.slug}`}>
<div>
<h2>{post.title}</h2>
{#if post.tags}
{#each post.tags as tag}
<span>{tag}</span>
{/each}
{/if}
<p>{post.excerpt.slice(0, 80)}...</p>
</div>
</a>
</section>
Import the PostCard
component into the src/routes/+page.svelte
file:
<script>
import PostCard from '$components/post-card.svelte';
/**
* @type {import('./$types').PageData}
*/
export let data;
let { posts } = data;
</script>
{#each posts as post}
<PostCard {post} />
{/each}
+lauout.svelte
fileAdd a constrained layout to the project, applying this to the src/routes/__layout.svelte
file will apply it to all routes below it:
<main class="container max-w-3xl mx-auto px-4">
<slot />
</main>