Skip to content

Build a Video Blog in Svelte

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.

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

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

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

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.

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

    npm init svelte@next <project-name>
Code language: HTML, XML (xml)

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.

    cd video-blog-in-svelte && npm i && npm i glob front-matter remark remark-html @mapbox/rehype-prism rehype && npm run dev
Code language: CSS (css)

The additional packages we installed are explained below:

    glob # To import multiple files with a * syntax
    
    front-matter # To extract frontmatter and body from markdown
    
    remark remark-html @mapbox/rehype-prism rehype # For HTML parsing
Code language: PHP (php)

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

Build a video blog in Svelte - default page

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:

    src/components/ -> // Svelte Components directory
        src/components/post-card.svelte  -> // Post card component 
    
    src/lib/ -> // Directory for building our pages from markdown
        src/lib/handle-markdown.js -> // File to handle markdown
    
    src/posts/ -> // Directory for Markdown post files
        src/posts/first-post.md -> // markdown for first post
        src/posts/second-post.md -> // markdown for second post
    
    src/routes/ -> // Router with all available pages
        src/routes/posts -> // Endpoints and pages for the route /posts/
    
    src/routes/api.js // File to implement the functionality to retrieve post dynamically
    
    src/routes/__Layout.svelte -> // A layout design file for all our pages
Code language: PHP (php)

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.

    <header>
      <h1><a href="/">Home</a></h1>
    </header>
    <slot />
    
    <style>
      header {
        display: flex;
        justify-content: space-between;
        border-bottom: 1px solid lightgray;
        padding-left: 4vw;
        padding-right: 4vw;
      }
    
      h1 {
        margin: 5;
        font-weight: 400;
        font-size: 25px;
      }
    </style>
Code language: HTML, XML (xml)

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

    <svelte:head>
      <title>Build a video blog in Svelte</title>
      <meta name="description" content="Build a video blog in Svelte!" />
    </svelte:head>
    
    <main>
      <h1>Build a video blog in Svelte</h1>
    </main>
    
    <style>
      main {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        margin-top: 20px;
      }
    
      /* card style */
    
      .post {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        margin-top: 20px;
      }
    </style>
Code language: HTML, XML (xml)

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.

    //handle-markdown.js
    
    import fs from 'fs';
    import glob from "glob";
    import fm from "front-matter";
    import {remark} from "remark";
    import html from "remark-html";
    import rehypePrism from "@mapbox/rehype-prism";
    import {rehype} from "rehype";
    
    /**
     * import all markdown files in the specified path, extract front matter and convert to HTML
     * @param {string} markdownPath path to folder containing the markdown files (ends on /)
     * @returns [{path, attributes, body}]
     */
    export function importMarkdowns(markdownPath) {
        let fileNames = glob.sync(`${markdownPath}*.md`);
        return fileNames.map((path) => convertMarkdown(path))
    }
    
    /**
     * convert markdown to object with attributes and HTML
     * @param {string} path path to file
     * @returns 
     */
    export function convertMarkdown(path) {
        let file = fs.readFileSync(path, 'utf8');
    
        let { attributes, body } = fm(file);
        let result = remark().use(html).processSync(body).value
        result = rehype().use(rehypePrism).processSync(result).value
        const retValue =  { path, attributes, html: result};
        return retValue
    }
    export function convertToPostPreview(object) {
        const url = object.path.replace(".md","").replace("src/", "");
        return {...object.attributes, url};
    }
Code language: JavaScript (javascript)

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.

    <script>
      // src/components/post-card.svelte
      export let title;
      export let description;
    
      export let url;
    </script>
    
    <a href={url}>
      <article>
        <h1>{title}</h1>
        <p>{description}</p>
      </article>
    </a>
    
    <style>
      article {
        padding: 2vw;
        border-radius: 15px;
        background-color: rgb(186, 186, 186);
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        margin-bottom: 2vw;
      }
      article:hover {
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
      }
    
      article:first-child {
        margin-top: 2vw;
      }
    
      article:last-child {
        margin-bottom: 2vw;
      }
    
      :global(a) {
        text-decoration: none;
        color: inherit;
      }
    </style>
Code language: HTML, XML (xml)

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.

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

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

src/posts/second-post.md

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

Update index.svelte with the following code snippet.

    <script context="module">
      ///src/routes/index.svelte
      export async function load({ fetch }) {
        const posts = await fetch("/api").then((r) => r.json());
        return {
          props: { posts },
        };
      }
    </script>
    
    <script>
      import PostCard from "/src/components/post-card.svelte";
      export let posts;
    </script>
    
    //...
    
    <main>
      <h1>Build a video blog in Svelte</h1>
      <div class="post">
        {#each posts as post}
          <PostCard {...post} />
        {/each}
      </div>
    </main>
    
    //...
Code language: HTML, XML (xml)

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

Build a video blog in Svelte

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.

    // src/routes/api.js
    import { importMarkdowns, convertToPostPreview } from "$lib/handle-markdown"
    
    export function GET() {
        let postFiles = importMarkdowns("src/posts/")
    
        let o_posts = postFiles.map((file) => convertToPostPreview(file))
    
        let body = JSON.stringify(o_posts);
    
        return {body}
    }
Code language: JavaScript (javascript)

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.

    <script context="module">
      // src/routes/posts/[url].svelte
      export const load = async ({ fetch, params, url }) => {
        const post = await fetch(`/posts/${params.url}.json`).then((r) => r.json());
        console;
        return { props: { post } };
      };
    </script>
    
    <script>
      export let post;
    </script>
    
    <svelte:head>
      <title>{post.attributes.title}</title>
      <meta name="description" content={post.attributes.description} />
    </svelte:head>
    
    <article>
      <h1 class="section-header">{post.attributes.title}</h1>
    
      {@html post.html}
    </article>
    
    <style>
      :global(article) {
        padding: 4vw;
      }
    </style>
Code language: HTML, XML (xml)

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

    import { convertMarkdown } from "$lib/handle-markdown"
    
    export async function GET({ params }) {
        const {url} = params;
        const post = await convertMarkdown(`src/posts/${url}.md`)
        let body = JSON.stringify(post);
        return { headers: { 'Content-Type': 'application/json' },body}
    }
Code language: JavaScript (javascript)

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

Build a video blog in Svelte - demo

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

    ---
    //..
    video: https://res.cloudinary.com/olanetsoft/video/upload/v1554336421/samples/sea-turtle.mp4
    ---
    
    The idea is to create first post on how to build video blog in Svelte.
Code language: JavaScript (javascript)

Update second-post.md

    ---
    //...
    video: https://res.cloudinary.com/olanetsoft/video/upload/v1554336425/samples/elephants.mp4
    ---
    
    The idea is to create second post on how to build video blog in Svelte.
Code language: JavaScript (javascript)

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

    <article>
      <h1 class="section-header">{post.attributes.title}</h1>
    
      {@html post.html}
    
      <!-- svelte-ignore a11y-media-has-caption -->
      <video
        src={post.attributes.video}
        height="400"
        width="600"
        controls
        autoplay
      />
    </article>
    
    //..
Code language: HTML, XML (xml)

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

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

Back to top

Featured Post