How to Create a Book Rating App with Strapi Ratings Plugin and Cloudinary
In this tutorial, we will create a Book Ratings application using Strapi Server API and Next.js. We will add policy, middleware, custom controllers, and routes to the Strapi Server API. We will also upload images to Cloudinary and utilize Strapi's built-in Ratings plugin. To get started, you need to have Node.js installed on your machine. You can download it from https://nodejs.org/en/. After installing Node.js, follow these steps: 1. Create a new project using the following command: ```bash npx create-strapi-app book-ratings --quickstart ``` 2. Install the required dependencies for Next.js and Strapi Server API by running the following commands: ```bash cd book-ratings yarn install ``` 3. Start the development server for both Next.js and Strapi Server API using the following command: ```bash yarn develop ``` 4. Open your browser and navigate to http://localhost:1337/admin to access the Strapi admin panel. Login with the default credentials (email: `[email protected]`, password: `strapi`) and create a new Content-Type called "Book" with the following fields: - Title (text) - Info (rich text) - Image (media) 5. Create another Content-Type called "Review" with the following fields: - Comment (text) - Rating (number) - Book (relationship) 6. Add a new policy to Strapi Server API by creating a file named `isAuthenticated.js` in the `./src/extensions/policies` directory. This policy will check if the user is authenticated before accessing certain routes: ```javascript module.exports = async (context, next) => { const authToken = context.request.headers['authorization']; if (!authToken) { throw new Error('Missing authentication token.'); } try { await strapi.plugins['users-permissions'].services.jwt.verify(authToken); } catch (error) { throw new Error('Invalid or expired authentication token.'); } return next(); }; ``` 7. Add a new middleware to Strapi Server API by creating a file named `requireAuth.js` in the `./src/extensions/middlewares` directory. This middleware will redirect unauthenticated users to the login page: ```javascript module.exports = async (config, { strapi }) => { return async (context) => { const authToken = context.request.headers['authorization']; if (!authToken) { throw new Error('Missing authentication token.'); } try { await strapi.plugins['users-permissions'].services.jwt.verify(authToken); } catch (error) { context.url = '/login'; return Promise.resolve(); } }; }; ``` 8. Add a new custom controller to Strapi Server API by creating a file named `book.js` in the `./src/api/book/controllers` directory. This controller will handle requests for creating, updating, and deleting books: ```javascript module.exports = { async create(ctx) { const { info, title } = ctx.request.body; const book = await strapi.services.book.create({ info, title }); return book; }, async update(ctx) { const { id } = ctx.params; const { info, title } = ctx.request.body; const updatedBook = await strapi.services.book.update({ id }, { info, title }); return updatedBook; }, async delete(ctx) { const { id } = ctx.params; await strapi.services.book.delete({ id }); return { message: 'Book deleted successfully.' }; }, }; ``` 9. Add a new custom route to Strapi Server API by creating a file named `create-book.js` in the `./src/api/book/routes` directory. This route will handle requests for uploading images and creating books: ```javascript const { createCoreRouter } = require('@strapi/strapi').factories; module.exports = createCoreRouter('api::book', ({ strapi }) => ({ async post(ctx) { const parser = new DatauriParser(); const { authToken } = ctx.request.headers; const image = ctx.request.files.image; try { const base64Image = await parser.format(path.extname(image.name).toString(), image.data); const uploadedImgRes = await strapi.plugins['upload'].services.uploader.upload(base64Image.content, 'ratings', { resource_type: 'image' }); const imageUrl = uploadedImgRes.url; const imageId = uploadedImgRes.public_id; const { data } = await strapi.plugins['book'].services.book.create({ info: ctx.request.body.info, title: ctx.request.body.title, imageUrl, imageId }, { headers: { Authorization: `Bearer ${authToken}` } }); return data; } catch (error) { ctx.status = 500; return error; } }, })); ``` 10. Create a new file named `fileValidation.js` in the `./src/utils` directory and add the following code: ```javascript export const validateSize = (file) => { if (!file) return; // if greater than 5MB if (file.size > 5000000) { return true; } return false; }; const getExtension = (filename) => { const parts = filename.split('.'); return parts[parts.length - 1]; }; export const isImage = (filename) => { const ext = getExtension(filename); switch (ext.toLowerCase()) { case 'jpg': case 'gif': case 'bmp': case 'png': case 'jpeg': return true; default: return false; } }; ``` 11. Create a new file named `editor.js` in the `./src/utils` directory and add the following code: ```javascript export const author_modules = { toolbar: [ [{ header: [1, 2, false] }], ['bold', 'italic', 'underline', 'strike', 'blockquote'], [ { list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }, ], ], }; export const author_formats = [ 'header', 'bold', 'italic', 'underline', 'strike', 'blockquote', ]; export const reviewer_modules = { toolbar: [ [{ header: [1, 2, false] }], ['bold', 'italic', 'underline', 'strike', 'blockquote'], [ { list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }, ], ['link', 'image'], ], }; export const reviewer_formats = [ 'header', 'bold', 'italic', 'underline', 'strike', 'blockquote', 'list', 'bullet', 'indent', 'link', 'image', ]; ``` 12. Create a new file named `cloudinary.js` in the `./src/utils` directory and add the following code: ```javascript import cloudinary from 'cloudinary'; cloudinary.v2.config({ cloud_name: process.env.CLOUDINARY_NAME, api_key: process.env.CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET, }); export default cloudinary; ``` 13. Create a new file named `appContext.js` in the `./src/utils` directory and add the following code: ```javascript import { createContext } from 'react'; const AppContext = createContext({}); export default AppContext; ``` 14. Create a new folder named `pages` inside the `book-ratings` project directory and create the following files: - `create.js` - `edit.js` - `single-book-and-review.js` - `signup.js` - `login.js` 15. Create a new folder named `components` inside the `book-ratings` project directory and create the following files: - `navigationBar.js` - `BookForm.js` - `ReviewForm.js` 16. Update the `create.js`, `edit.js`, `single-book-and-review.js`, `signup.js`, and `login.js` files with the appropriate code for each page. 17. Update the `NavigationBar.js`, `BookForm.js`, and `ReviewForm.js` components with the appropriate code for each component. 18. Add the following environment variables to your `.env.local` file: ``` CLOUDINARY_NAME=<your_cloudinary_name> CLOUDINARY_API_KEY=<your_api_key> CLOUDINARY_API_SECRET=<your_api_secret> ``` 19. Run the following command to start your application: ```bash yarn dev ``` 20. Open your browser and navigate to http://localhost:3000 to access your Book Ratings application. That's it! You have successfully created a Book Ratings application using Strapi Server API and Next.js. You can now create, update, delete books, add reviews, and rate books in your application.
Company
Strapi
Date published
Jan. 10, 2023
Author(s)
Theodore Kelechukwu Onyejiaku
Word count
4819
Language
English
Hacker News points
None found.