Svelte-strapi-tutorial

By Quadrisheriff

Svelte-strapi-tutorial Alternatives

Similar projects and alternatives to Svelte-strapi-tutorial

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a better Svelte-strapi-tutorial alternative or higher similarity.

Svelte-strapi-tutorial reviews and mentions

Posts with mentions or reviews of Svelte-strapi-tutorial. We have used some of these posts to build our list of alternatives and similar projects. The last one was on 2022-05-10.
  • How to Create a Blog with SvelteKit and Strapi
    8 projects | dev.to | 10 May 2022
    Title Description Content
    Submit
    label { @apply font-bold block mb-1; } input { @apply bg-white w-full border border-gray-500 rounded outline-none py-2 px-4; } textarea { @apply bg-white w-full border border-gray-500 rounded outline-none py-2 px-4 resize-y; } .submit { @apply bg-blue-500 text-white border-transparent rounded px-4 py-2; }
    Enter fullscreen mode Exit fullscreen mode

    `

    Don't try this out yet, since there's currently no way to determine the Author of the PostPost. We need to code that in Strapi explicitly.

    Let's create custom controllers for the Post content type. Here, we'll make it so that the Author of a post will be the currently logged-in User.

    Edit api/post/controllers/post.js in the Strapi project.

    `

    'use strict';
    /**
     *  post controller
     */
    const { createCoreController } = require('@strapi/strapi').factories;
    const { parseMultipartData, sanitizeEntity } = require("strapi-utils");
    /**
     * Read the documentation (https://docs.strapi.io/developer-docs/latest/development/backend-customization.html#core-controllers)
     * to customize this controller
     */
    module.exports = {
        async create(ctx) {
            let entity;
            if (ctx.is("multipart")) {
                const { data, files } = parseMultipartData(ctx);
                data.author = ctx.state.user.id;
                entity = await strapi.services.post.create(data, { files });
            } else {
                ctx.request.body.author = ctx.state.user.id;
                entity = await strapi.services.post.create(ctx.request.body);
            }
            return sanitizeEntity(entity, { model: strapi.models.post });
        },
        async update(ctx) {
            const { id } = ctx.params;
            let entity;
            const [article] = await strapi.services.post.find({
                id: ctx.params.id,
                "author.id": ctx.state.user.id,
            });
            if (!article) {
                return ctx.unauthorized(`You can't update this entry`);
            }
            if (ctx.is("multipart")) {
                const { data, files } = parseMultipartData(ctx);
                entity = await strapi.services.post.update({ id }, data, {
                    files,
                });
            } else {
                entity = await strapi.services.post.update({ id }, ctx.request.body);
            }
            return sanitizeEntity(entity, { model: strapi.models.post });
        },
        async delete(ctx) {
            const { id } = ctx.params;
            let entity;
            const [article] = await strapi.services.post.find({
                id: ctx.params.id,
                "author.id": ctx.state.user.id,
            });
            if (!article) {
                return ctx.unauthorized(`You can't delete this entry`);
            }
            await strapi.services.post.delete({ id });
            return { ok: true };
        },
    };
    module.exports = createCoreController('api::post.post');
    
    Enter fullscreen mode Exit fullscreen mode

    `

    If you get confused, checkout the Strapi Documentation

    Install strapi-utils with the following command.
    bash
    npm install strapi-utils

    And now, you should be able to create and update posts all from one route. Let's make the update process easier. Change src/routes/blog/[id].svelte to the code below:

    `js


    import type { Load } from '@sveltejs/kit';
    export const load: Load = async ({ params, fetch }) => {

            // Now, we'll fetch the blog post from Strapi
            const res = await fetch(`http://localhost:1337/api/posts/${params.id}?populate=*`);
            // A 404 status means "NOT FOUND"
            if (res.status === 404) {
                // We can create a custom error and return it.
                // SvelteKit will automatically show us an error page that we'll learn to customise later on.
                const error = new Error(`The post with ID ${params.id} was not found`);
                return { status: 404, error };
            } else {
                const response = await res.json();
                return { props: { post: response.data.attributes } };
            }
        };
    
    
            import type { Post } from '$lib/types';
            import { onMount } from 'svelte';
            import { goto } from '$app/navigation';
            import user from '$lib/user';
        export let post: Post;
        let content = post.content;
        onMount(async () => {
            // Install the marked package first!
            // Run this command: npm i marked
            // We're using this style of importing because "marked" uses require, which won't work when we import it with SvelteKit.
            // Check the "How do I use a client-side only library" in the FAQ: https://kit.svelte.dev/faq
            const marked = (await import('marked')).default;
            content = marked(post.content);
        });
        async function deletePost() {
                // TODO
            }
    
    

    {post.title}

    By: {post.author.data.attributes.username}

    {#if $user && post.author.id === $user.id}

    goto('/new?edit=' + post.id)}>Update post Delete post

    {/if}
    {@html content}

    `

    Now, when the Author visits their PostPost, they'll see two buttons to Update and Delete the PostPost, respectively.

    Don't try this out yet, since there's currently no way to determine the Author of the PostPost. We need to code that in Strapi explicitly.
    Let's create custom controllers for the Post content type. Here, we'll make it so that the Author of a post will be the currently logged-in User.
    Edit api/post/controllers/post.js in the Strapi project.

    `

        "use strict";
    
        const { parseMultipartData, sanitizeEntity } = require("strapi-utils");
    
        /**
         * Read the documentation (https://docs.strapi.io/developer-docs/latest/development/backend-customization.html#core-controllers)
         * to customize this controller
         */
    
        module.exports = {
          async create(ctx) {
            let entity;
    
            if (ctx.is("multipart")) {
              const { data, files } = parseMultipartData(ctx);
              data.author = ctx.state.user.id;
              entity = await strapi.services.post.create(data, { files });
            } else {
              ctx.request.body.author = ctx.state.user.id;
              entity = await strapi.services.post.create(ctx.request.body);
            }
    
            return sanitizeEntity(entity, { model: strapi.models.post });
          },
    
          async update(ctx) {
            const { id } = ctx.params;
    
            let entity;
    
            const [article] = await strapi.services.post.find({
              id: ctx.params.id,
              "author.id": ctx.state.user.id,
            });
    
            if (!article) {
              return ctx.unauthorized(`You can't update this entry`);
            }
    
            if (ctx.is("multipart")) {
              const { data, files } = parseMultipartData(ctx);
              entity = await strapi.services.post.update({ id }, data, {
                files,
              });
            } else {
              entity = await strapi.services.post.update({ id }, ctx.request.body);
            }
    
            return sanitizeEntity(entity, { model: strapi.models.post });
          },
        };
    

    `

    If you get confused, checkout the Strapi Documentation

    And now, you should be able to create and update posts all from one route. Let's make the update process easier. Change src/routes/blog/[slug].svelte to the code below:

    `

    
        
            import type { Load } from '@sveltejs/kit';
    
            export const load: Load = async ({ page: { params }, fetch }) => {
                // The params object will contain all of the parameters in the route.
                const { slug } = params;
    
                // Now, we'll fetch the blog post from Strapi
                const res = await fetch('http://localhost:1337/posts/' + slug);
    
                // A 404 status means "NOT FOUND"
                if (res.status === 404) {
                    // We can create a custom error and return it.
                    // SvelteKit will automatically show us an error page that we'll learn to customise later on.
                    const error = new Error(`The post with ID ${slug} was not found`);
                    return { status: 404, error };
                } else {
                    const data = await res.json();
                    return { props: { post: data } };
                }
            };
        
    
        
            import type { Post } from '$lib/types';
            import { onMount } from 'svelte';
            import { goto } from '$app/navigation';
            import user from '$lib/user';
    
            export let post: Post;
            let content = post.content;
    
            onMount(async () => {
                // Install the marked package first!
                // Run this command: npm i marked
    
                // We're using this style of importing because "marked" uses require, which won't work when we import it with SvelteKit.
                // Check the "How do I use a client-side only library" in the FAQ: https://kit.svelte.dev/faq
                const marked = (await import('marked')).default;
                content = marked(post.content);
            });
    
            async function deletePost() {
                // TODO
            }
        
    
        

    {post.title}

    By: {post.author.username}

    {#if $user && post.author.id === $user.id}

    goto('/new?edit=' + post.id)}>Update post Delete post

    {/if}
    {@html content}

    `

    Now, when the Author visits their PostPost, they'll see two buttons to Update and Delete the PostPost, respectively.

    Deleting Posts

    Let's add functionality to the Delete Post button. Edit the deletePost() function in the file we just modified (src/routes/blog/[id].svelte) and change it to this:

    `

        async function deletePost() {
            if (!localStorage.getItem('token')) {
                goto('/login');
                return;
            }
            const res = await fetch('http://localhost:1337/api/posts/' + post.id, {
                method: 'DELETE',
                headers: { Authorization: 'Bearer ' + localStorage.getItem('token') }
            });
            if (res.ok) {
                goto('/');
            } else {
                const data: { message: { messages: { message: string }[] }[] } = await res.json();
                if (data?.message?.[0]?.messages?.[0]?.message) {
                    alert(data.message[0].messages[0].message);
                }
            }
        }
    

    `
    Now, obviously, we don't want anybody to delete a post by someone else. Let's add another method in api/post/controllers/post.js in our Strapi App.

    This is how your code should look now:

    `

    'use strict';
    /**
     *  post controller
     */
    const { createCoreController } = require('@strapi/strapi').factories;
    const { parseMultipartData, sanitizeEntity } = require("strapi-utils");
    /**
     * Read the documentation (https://docs.strapi.io/developer-docs/latest/development/backend-customization.html#core-controllers)
     * to customize this controller
     */
    module.exports = {
        async create(ctx) {
            let entity;
            if (ctx.is("multipart")) {
                const { data, files } = parseMultipartData(ctx);
                data.author = ctx.state.user.id;
                entity = await strapi.services.post.create(data, { files });
            } else {
                ctx.request.body.author = ctx.state.user.id;
                entity = await strapi.services.post.create(ctx.request.body);
            }
            return sanitizeEntity(entity, { model: strapi.models.post });
        },
        async update(ctx) {
            const { id } = ctx.params;
            let entity;
            const [article] = await strapi.services.post.find({
                id: ctx.params.id,
                "author.id": ctx.state.user.id,
            });
            if (!article) {
                return ctx.unauthorized(`You can't update this entry`);
            }
            if (ctx.is("multipart")) {
                const { data, files } = parseMultipartData(ctx);
                entity = await strapi.services.post.update({ id }, data, {
                    files,
                });
            } else {
                entity = await strapi.services.post.update({ id }, ctx.request.body);
            }
            return sanitizeEntity(entity, { model: strapi.models.post });
        },
        async delete(ctx) {
            const { id } = ctx.params;
            let entity;
            const [article] = await strapi.services.post.find({
                id: ctx.params.id,
                "author.id": ctx.state.user.id,
            });
            if (!article) {
                return ctx.unauthorized(`You can't delete this entry`);
            }
            await strapi.services.post.delete({ id });
            return { ok: true };
        },
    };
    module.exports = createCoreController('api::post.post');
    

    `

    And now, the author should be able to delete posts.

    Custom Error Page

    You may have noticed that the 404 page looks terrible. It has almost no styling. With SvelteKit, we're allowed to create a custom error page. So we need to name this file __error.svelte and place it in src/routes.

    `

    
    
        import type { ErrorLoad } from '@sveltejs/kit';
        export type { ErrorLoad } from '@sveltejs/kit';
        export const load: ErrorLoad = ({ error, status }) => {
            return { props: { error, status } };
        };
    
    
        export let error: Error;
        export let status: number;
    
    

    {status}

    {error.message}

    `

    Here's how our error page will look like when you search for a blog post with wrong id.

    The Error Page

    Much better right?

    Now, obviously, we don't want anybody to delete a post by someone else. Let's add another method in
    api/post/controllers/post.js in our Strapi App.
    This is how your code should look now:

    `
    // api/post/controllers/post.js
    "use strict";

        const { parseMultipartData, sanitizeEntity } = require("strapi-utils");
    
        /**
         * Read the documentation (https://docs.strapi.io/developer-docs/latest/development/backend-customization.html#core-controllers)
         * to customize this controller
         */
    
        module.exports = {
          async create(ctx) {
            let entity;
    
            if (ctx.is("multipart")) {
              const { data, files } = parseMultipartData(ctx);
              data.author = ctx.state.user.id;
              entity = await strapi.services.post.create(data, { files });
            } else {
              ctx.request.body.author = ctx.state.user.id;
              entity = await strapi.services.post.create(ctx.request.body);
            }
    
            return sanitizeEntity(entity, { model: strapi.models.post });
          },
    
          async update(ctx) {
            const { id } = ctx.params;
    
            let entity;
    
            const [article] = await strapi.services.post.find({
              id: ctx.params.id,
              "author.id": ctx.state.user.id,
            });
    
            if (!article) {
              return ctx.unauthorized(`You can't update this entry`);
            }
    
            if (ctx.is("multipart")) {
              const { data, files } = parseMultipartData(ctx);
              entity = await strapi.services.post.update({ id }, data, {
                files,
              });
            } else {
              entity = await strapi.services.post.update({ id }, ctx.request.body);
            }
    
            return sanitizeEntity(entity, { model: strapi.models.post });
          },
    
          async delete(ctx) {
            const { id } = ctx.params;
    
            let entity;
    
            const [article] = await strapi.services.post.find({
              id: ctx.params.id,
              "author.id": ctx.state.user.id,
            });
    
            if (!article) {
              return ctx.unauthorized(`You can't delete this entry`);
            }
    
            await strapi.services.post.delete({ id });
    
            return { ok: true };
          },
        };
    

    `

    And now, the author should be able to delete posts.

    Conclusion & Resources

    And there you have it! Your blog website is made with SvelteKit and Strapi. If you got stuck anywhere, be sure to check the SvelteKit Docs, the Strapi Docs, and the source code on Github.

Stats

Basic Svelte-strapi-tutorial repo stats
1
7
10.0
almost 2 years ago

Sponsored
SaaSHub - Software Alternatives and Reviews
SaaSHub helps you find the best software and product alternatives
www.saashub.com