Build a Video Blog in Svelte

Banner for a MediaJam post

Idris Olubisi

Sharing tutorials, concepts, events, etc., with video blogs is entertaining and engaging. Additionally, blog posts that contain videos receive more inbound links and views than those that don't.

In this post, we will learn how to build a video blog in Svelte using Cloudinary as our video hosting service.

Sandbox

We completed this project in a CodeSandbox. Fork and run it to get started quickly.

GitHub repository

https://github.com/Olanetsoft/Build-a-video-blog-in-Svelte

Prerequisites

To follow along, you’ll need the following:

  • Basic knowledge of JavaScript
  • A Cloudinary account for storing and delivering our images and video (Create a free account here)
  • A Node.js installation on your machine

Getting started with Svelte

Svelte is a revolutionary new method for creating user interfaces. Svelte puts that work into a compile stage when we build our app, as opposed to standard frameworks like React and Vue, which perform most of their work in the browser.

Project setup and installation

To create a new project, use the command below to scaffold a new project:

1npm init svelte@next <project-name>

A series of prompts will appear as a result of the command. Here are the defaults we recommend:

Build a video blog in Svelte - Project Setup and Installation

The command creates a Svelte project called video-blog-in-svelte.

Next, we need to navigate into the project directory, install some additional packages we will use later in this article and start the development server using the command below.

1cd video-blog-in-svelte && npm i && npm i glob front-matter remark remark-html @mapbox/rehype-prism rehype && npm run dev

The additional packages we installed are explained below:

1glob # To import multiple files with a * syntax
2
3 front-matter # To extract frontmatter and body from markdown
4
5 remark remark-html @mapbox/rehype-prism rehype # For HTML parsing

Svelte will start a development environment accessible by default at http://localhost:3000

Build a video blog in Svelte - default page

Building the video blog

In this section, we’ll go over building a video blog. First, we need to define our project structure and create some directories and files as indicated below:

1src/components/ -> // Svelte Components directory
2 src/components/post-card.svelte -> // Post card component
3
4 src/lib/ -> // Directory for building our pages from markdown
5 src/lib/handle-markdown.js -> // File to handle markdown
6
7 src/posts/ -> // Directory for Markdown post files
8 src/posts/first-post.md -> // markdown for first post
9 src/posts/second-post.md -> // markdown for second post
10
11 src/routes/ -> // Router with all available pages
12 src/routes/posts -> // Endpoints and pages for the route /posts/
13
14 src/routes/api.js // File to implement the functionality to retrieve post dynamically
15
16 src/routes/__Layout.svelte -> // A layout design file for all our pages

After creating the directories and files, we should have something similar to what is shown below:

Build a video blog in Svelte

Next, update the __layout.svelte with the following code snippet.

1<header>
2 <h1><a href="/">Home</a></h1>
3 </header>
4 <slot />
5
6 <style>
7 header {
8 display: flex;
9 justify-content: space-between;
10 border-bottom: 1px solid lightgray;
11 padding-left: 4vw;
12 padding-right: 4vw;
13 }
14
15 h1 {
16 margin: 5;
17 font-weight: 400;
18 font-size: 25px;
19 }
20 </style>

Let’s update index.svelte with the following code snippet.

1<svelte:head>
2 <title>Build a video blog in Svelte</title>
3 <meta name="description" content="Build a video blog in Svelte!" />
4 </svelte:head>
5
6 <main>
7 <h1>Build a video blog in Svelte</h1>
8 </main>
9
10 <style>
11 main {
12 display: flex;
13 flex-direction: column;
14 align-items: center;
15 justify-content: center;
16 margin-top: 20px;
17 }
18
19 /* card style */
20
21 .post {
22 display: flex;
23 flex-direction: column;
24 align-items: center;
25 justify-content: center;
26 margin-top: 20px;
27 }
28 </style>

Build a video blog in Svelte

As shown above, we have completely set up our layout and can now implement the blog retrieval functionality in the following step.

Let’s update the handle-markdown.js file inside the components directory with the following code snippet.

1//handle-markdown.js
2
3 import fs from 'fs';
4 import glob from "glob";
5 import fm from "front-matter";
6 import {remark} from "remark";
7 import html from "remark-html";
8 import rehypePrism from "@mapbox/rehype-prism";
9 import {rehype} from "rehype";
10
11 /**
12 * import all markdown files in the specified path, extract front matter and convert to HTML
13 * @param {string} markdownPath path to folder containing the markdown files (ends on /)
14 * @returns [{path, attributes, body}]
15 */
16 export function importMarkdowns(markdownPath) {
17 let fileNames = glob.sync(`${markdownPath}*.md`);
18 return fileNames.map((path) => convertMarkdown(path))
19 }
20
21 /**
22 * convert markdown to object with attributes and HTML
23 * @param {string} path path to file
24 * @returns
25 */
26 export function convertMarkdown(path) {
27 let file = fs.readFileSync(path, 'utf8');
28
29 let { attributes, body } = fm(file);
30 let result = remark().use(html).processSync(body).value
31 result = rehype().use(rehypePrism).processSync(result).value
32 const retValue = { path, attributes, html: result};
33 return retValue
34 }
35 export function convertToPostPreview(object) {
36 const url = object.path.replace(".md","").replace("src/", "");
37 return {...object.attributes, url};
38 }

The code snippet above will be used to find all posts, extract the frontmatter, and parse the body to HTML.

Next, update the post-card.js inside the components directory with the following code snippet.

1<script>
2 // src/components/post-card.svelte
3 export let title;
4 export let description;
5
6 export let url;
7 </script>
8
9 <a href={url}>
10 <article>
11 <h1>{title}</h1>
12 <p>{description}</p>
13 </article>
14 </a>
15
16 <style>
17 article {
18 padding: 2vw;
19 border-radius: 15px;
20 background-color: rgb(186, 186, 186);
21 box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
22 margin-bottom: 2vw;
23 }
24 article:hover {
25 box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
26 }
27
28 article:first-child {
29 margin-top: 2vw;
30 }
31
32 article:last-child {
33 margin-bottom: 2vw;
34 }
35
36 :global(a) {
37 text-decoration: none;
38 color: inherit;
39 }
40 </style>

In the code snippet above, the post-card contains a title and description that we can find in the frontmatter of the Markdown file. It also needs a URL redirecting the user to the right path upon clicking.

Retrieve all posts

In this section, we will retrieve all posts on the browser. We can proceed to update first-post.md and second-post.md with their respective code snippets below.

src/posts/first-post.md

1---
2 title: Creating first post on how to build video blog in Svelte
3 description: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard.
4 ---
5
6 The idea is to create first post on how to build video blog in Svelte.

src/posts/second-post.md

1---
2 title: Creating second post on how to build video blog in Svelte
3 description: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard.
4 ---
5
6 The idea is to create second post on how to build video blog in Svelte.

Update index.svelte with the following code snippet.

1<script context="module">
2 ///src/routes/index.svelte
3 export async function load({ fetch }) {
4 const posts = await fetch("/api").then((r) => r.json());
5 return {
6 props: { posts },
7 };
8 }
9 </script>
10
11 <script>
12 import PostCard from "/src/components/post-card.svelte";
13 export let posts;
14 </script>
15
16 //...
17
18 <main>
19 <h1>Build a video blog in Svelte</h1>
20 <div class="post">
21 {#each posts as post}
22 <PostCard {...post} />
23 {/each}
24 </div>
25 </main>
26
27 //...

Next, restart the server to reflect new changes, as shown below.

Build a video blog in Svelte

Create routes and load posts dynamically

We'll read the written post in this section. We must develop a dynamic route that loads a post to do so.

Update the api.js file under the src/routes directory with the following snippet.

1// src/routes/api.js
2 import { importMarkdowns, convertToPostPreview } from "$lib/handle-markdown"
3
4 export function GET() {
5 let postFiles = importMarkdowns("src/posts/")
6
7 let o_posts = postFiles.map((file) => convertToPostPreview(file))
8
9 let body = JSON.stringify(o_posts);
10
11 return {body}
12 }

Next, we will create a dynamic page with [url].svelte and [url].json.js in the src/routes/posts directory. The url variable is to request the needed file and display the content in the HTML of the page.

Let’s update [url].svelte with the following code snippet.

1<script context="module">
2 // src/routes/posts/[url].svelte
3 export const load = async ({ fetch, params, url }) => {
4 const post = await fetch(`/posts/${params.url}.json`).then((r) => r.json());
5 console;
6 return { props: { post } };
7 };
8 </script>
9
10 <script>
11 export let post;
12 </script>
13
14 <svelte:head>
15 <title>{post.attributes.title}</title>
16 <meta name="description" content={post.attributes.description} />
17 </svelte:head>
18
19 <article>
20 <h1 class="section-header">{post.attributes.title}</h1>
21
22 {@html post.html}
23 </article>
24
25 <style>
26 :global(article) {
27 padding: 4vw;
28 }
29 </style>

Now, update [url].json.js with the following code snippet.

1import { convertMarkdown } from "$lib/handle-markdown"
2
3 export async function GET({ params }) {
4 const {url} = params;
5 const post = await convertMarkdown(`src/posts/${url}.md`)
6 let body = JSON.stringify(post);
7 return { headers: { 'Content-Type': 'application/json' },body}
8 }

We should be able to preview individual posts, as shown below.

Build a video blog in Svelte - demo

Add a video from Cloudinary

Let's log in to our Cloudinary account on our browser to upload new videos and retrieve the video URL for the videos uploaded.

https://res.cloudinary.com/olanetsoft/video/upload/v1554336421/samples/sea-turtle.mp4 https://res.cloudinary.com/olanetsoft/video/upload/v1554336425/samples/elephants.mp4

We will update the first-post.md and second-post.md with the following code snippets.

Update first-post.md

1---
2 //..
3 video: https://res.cloudinary.com/olanetsoft/video/upload/v1554336421/samples/sea-turtle.mp4
4 ---
5
6 The idea is to create first post on how to build video blog in Svelte.

Update second-post.md

1---
2 //...
3 video: https://res.cloudinary.com/olanetsoft/video/upload/v1554336425/samples/elephants.mp4
4 ---
5
6 The idea is to create second post on how to build video blog in Svelte.

Next, we’ll update [url].svelte to preview individual video on our blog post.

1<article>
2 <h1 class="section-header">{post.attributes.title}</h1>
3
4 {@html post.html}
5
6 <!-- svelte-ignore a11y-media-has-caption -->
7 <video
8 src={post.attributes.video}
9 height="400"
10 width="600"
11 controls
12 autoplay
13 />
14 </article>
15
16 //..

Now, let’s restart the server and test our application.

Conclusion

This post demonstrates how to build a video blog in Svelte.

Resources

Idris Olubisi

Software Engineer & Technical Writer

A Software Engineer & Technical Writer with immense knowledge and a passionate speaker about open source, blockchain, software products, and serverless technologies.