├── README.md ├── backend ├── api │ └── blog │ │ ├── config │ │ └── routes.json │ │ ├── controllers │ │ └── blog.js │ │ ├── models │ │ ├── blog.js │ │ └── blog.settings.json │ │ └── services │ │ └── blog.js ├── config │ ├── database.js │ ├── functions │ │ ├── bootstrap.js │ │ ├── cron.js │ │ └── responses │ │ │ └── 404.js │ └── server.js ├── extensions │ └── users-permissions │ │ └── config │ │ └── jwt.js ├── favicon.ico ├── package-lock.json ├── package.json └── public │ └── robots.txt ├── frontend ├── craco.config.js ├── data │ └── db.json ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── AddBlog.js │ ├── App.js │ ├── BlogDetails.js │ ├── BlogList.js │ ├── Home.js │ ├── Navbar.js │ ├── index.css │ ├── index.js │ └── useFetch.js └── tailwind.config.js └── screenshots ├── Detail.png └── Home.png /README.md: -------------------------------------------------------------------------------- 1 | ## WriteUp 2 | A blog website used to add blogs to and show blogs from json server built with React, JavaScript, and Tailwind CSS. 3 | 4 | ### Project Demo 5 | 6 | 7 | 8 | 1. Home 9 |  10 | --- 11 | 1. Blog detail page 12 |  13 | 14 | ### Features 15 | - List all blogs 16 | - View detail page 17 | - Love/Unlove blog 18 | - Search blogs 19 | - Delete blog 20 | 21 | ### Installation and Setup Instructions 22 | 23 | Clone down this repository. You will need `node` and `npm` installed globally on your machine. 24 | 25 | Installation: 26 | 27 | `npm install` 28 | 29 | To Start Server: 30 | 31 | `npm start` 32 | 33 | To Visit App: 34 | 35 | `localhost:3000` 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /backend/api/blog/config/routes.json: -------------------------------------------------------------------------------- 1 | { 2 | "routes": [ 3 | { 4 | "method": "GET", 5 | "path": "/blogs", 6 | "handler": "blog.find", 7 | "config": { 8 | "policies": [] 9 | } 10 | }, 11 | { 12 | "method": "GET", 13 | "path": "/blogs/count", 14 | "handler": "blog.count", 15 | "config": { 16 | "policies": [] 17 | } 18 | }, 19 | { 20 | "method": "GET", 21 | "path": "/blogs/:id", 22 | "handler": "blog.findOne", 23 | "config": { 24 | "policies": [] 25 | } 26 | }, 27 | { 28 | "method": "POST", 29 | "path": "/blogs", 30 | "handler": "blog.create", 31 | "config": { 32 | "policies": [] 33 | } 34 | }, 35 | { 36 | "method": "PUT", 37 | "path": "/blogs/:id", 38 | "handler": "blog.update", 39 | "config": { 40 | "policies": [] 41 | } 42 | }, 43 | { 44 | "method": "DELETE", 45 | "path": "/blogs/:id", 46 | "handler": "blog.delete", 47 | "config": { 48 | "policies": [] 49 | } 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /backend/api/blog/controllers/blog.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers) 5 | * to customize this controller 6 | */ 7 | 8 | module.exports = {}; 9 | -------------------------------------------------------------------------------- /backend/api/blog/models/blog.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#lifecycle-hooks) 5 | * to customize this model 6 | */ 7 | 8 | module.exports = {}; 9 | -------------------------------------------------------------------------------- /backend/api/blog/models/blog.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "collectionType", 3 | "collectionName": "blogs", 4 | "info": { 5 | "name": "Blog", 6 | "description": "" 7 | }, 8 | "options": { 9 | "increments": true, 10 | "timestamps": true, 11 | "draftAndPublish": true 12 | }, 13 | "pluginOptions": {}, 14 | "attributes": { 15 | "title": { 16 | "type": "string" 17 | }, 18 | "body": { 19 | "type": "richtext" 20 | }, 21 | "blogImage": { 22 | "model": "file", 23 | "via": "related", 24 | "allowedTypes": [ 25 | "images", 26 | "files", 27 | "videos" 28 | ], 29 | "plugin": "upload", 30 | "required": false, 31 | "pluginOptions": {} 32 | }, 33 | "author": { 34 | "type": "enumeration", 35 | "enum": [ 36 | "Tasfia", 37 | "Mansura", 38 | "Nubayra", 39 | "Ahmed" 40 | ] 41 | }, 42 | "category": { 43 | "type": "enumeration", 44 | "enum": [ 45 | "technology", 46 | "beauty", 47 | "health", 48 | "sports", 49 | "travel" 50 | ] 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /backend/api/blog/services/blog.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-services) 5 | * to customize this service 6 | */ 7 | 8 | module.exports = {}; 9 | -------------------------------------------------------------------------------- /backend/config/database.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ env }) => ({ 2 | defaultConnection: 'default', 3 | connections: { 4 | default: { 5 | connector: 'mongoose', 6 | settings: { 7 | host: env('DATABASE_HOST', '127.0.0.1'), 8 | srv: env.bool('DATABASE_SRV', false), 9 | port: env.int('DATABASE_PORT', 27017), 10 | database: env('DATABASE_NAME', 'backend'), 11 | username: env('DATABASE_USERNAME', null), 12 | password: env('DATABASE_PASSWORD', null), 13 | }, 14 | options: { 15 | authenticationDatabase: env('AUTHENTICATION_DATABASE', null), 16 | ssl: env.bool('DATABASE_SSL', false), 17 | }, 18 | }, 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /backend/config/functions/bootstrap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * An asynchronous bootstrap function that runs before 5 | * your application gets started. 6 | * 7 | * This gives you an opportunity to set up your data model, 8 | * run jobs, or perform some special logic. 9 | * 10 | * See more details here: https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/configurations.html#bootstrap 11 | */ 12 | 13 | module.exports = () => {}; 14 | -------------------------------------------------------------------------------- /backend/config/functions/cron.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Cron config that gives you an opportunity 5 | * to run scheduled jobs. 6 | * 7 | * The cron format consists of: 8 | * [SECOND (optional)] [MINUTE] [HOUR] [DAY OF MONTH] [MONTH OF YEAR] [DAY OF WEEK] 9 | * 10 | * See more details here: https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/configurations.html#cron-tasks 11 | */ 12 | 13 | module.exports = { 14 | /** 15 | * Simple example. 16 | * Every monday at 1am. 17 | */ 18 | // '0 1 * * 1': () => { 19 | // 20 | // } 21 | }; 22 | -------------------------------------------------------------------------------- /backend/config/functions/responses/404.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = async (/* ctx */) => { 4 | // return ctx.notFound('My custom message 404'); 5 | }; 6 | -------------------------------------------------------------------------------- /backend/config/server.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ env }) => ({ 2 | host: env('HOST', '0.0.0.0'), 3 | port: env.int('PORT', 1337), 4 | admin: { 5 | auth: { 6 | secret: env('ADMIN_JWT_SECRET', 'c6178d130657d821d6cce54b612f14dd'), 7 | }, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /backend/extensions/users-permissions/config/jwt.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | jwtSecret: process.env.JWT_SECRET || '6f00943e-dced-483b-a803-fcf615b4339f' 3 | }; -------------------------------------------------------------------------------- /backend/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/annarihu/blog-app-in-reactjs/8449dd2749827a1fdcc2293cda058858f9f81980/backend/favicon.ico -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "private": true, 4 | "version": "0.1.0", 5 | "description": "A Strapi application", 6 | "scripts": { 7 | "develop": "strapi develop", 8 | "start": "strapi start", 9 | "build": "strapi build", 10 | "strapi": "strapi" 11 | }, 12 | "devDependencies": {}, 13 | "dependencies": { 14 | "strapi": "3.6.6", 15 | "strapi-admin": "3.6.6", 16 | "strapi-connector-mongoose": "3.6.6", 17 | "strapi-plugin-content-manager": "3.6.6", 18 | "strapi-plugin-content-type-builder": "3.6.6", 19 | "strapi-plugin-email": "3.6.6", 20 | "strapi-plugin-graphql": "^3.6.6", 21 | "strapi-plugin-i18n": "3.6.6", 22 | "strapi-plugin-upload": "3.6.6", 23 | "strapi-plugin-users-permissions": "3.6.6", 24 | "strapi-utils": "3.6.6" 25 | }, 26 | "author": { 27 | "name": "A Strapi developer" 28 | }, 29 | "strapi": { 30 | "uuid": "9c18de21-5f2a-4215-ac85-1e28f03d2720" 31 | }, 32 | "engines": { 33 | "node": ">=10.16.0 <=14.x.x", 34 | "npm": "^6.0.0" 35 | }, 36 | "license": "MIT" 37 | } 38 | -------------------------------------------------------------------------------- /backend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # To prevent search engines from seeing the site altogether, uncomment the next two lines: 2 | # User-Agent: * 3 | # Disallow: / 4 | -------------------------------------------------------------------------------- /frontend/craco.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | style: { 3 | postcss: { 4 | plugins: [ 5 | require('tailwindcss'), 6 | require('autoprefixer'), 7 | ], 8 | }, 9 | }, 10 | } -------------------------------------------------------------------------------- /frontend/data/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "blogs": [ 3 | { 4 | "title": "Bolt-On Security the Linux Way", 5 | "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 6 | "author": "Tasfia", 7 | "blogImage": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUco6ODT7I-8aMCRmK-tRGDZ7LjWyuCt2W_g&usqp=CAU", 8 | "category": "technology", 9 | "id": 1 10 | }, 11 | { 12 | "title": "Japanese Food: A Culinary Travel Guide", 13 | "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 14 | "author": "Mansura", 15 | "blogImage": "https://media.istockphoto.com/photos/sushi-set-nigiri-and-sashimi-with-tea-picture-id508032520?k=6&m=508032520&s=612x612&w=0&h=JXr7IfjX1uMolwhKsTUCyRm_tcPFEGmsnAXJTMgWN_M=", 16 | "category": "travel", 17 | "id": 2 18 | }, 19 | { 20 | "title": "Michael Laudrup - The best of a generation", 21 | "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 22 | "author": "Nubayra", 23 | "blogImage": "https://cdn.swanseacity.com/sites/default/files/archive/Laudrup%20cup%2016x9.jpg", 24 | "category": "sports", 25 | "id": 3 26 | }, 27 | { 28 | "title": "The Best Plant-Based Foods To Build Collagen Naturally", 29 | "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 30 | "author": "Nubayra", 31 | "blogImage": "https://i0.wp.com/images-prod.healthline.com/hlcmsresource/images/AN_images/healthy-eating-ingredients-1296x728-header.jpg?w=1155&h=1528", 32 | "category": "beauty", 33 | "id": 4 34 | }, 35 | { 36 | "title": "Exfoliate + Moisturize With These Homemade Scrub Bars", 37 | "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 38 | "author": "Nubayra", 39 | "blogImage": "https://static.toiimg.com/photo/79066201.cms", 40 | "category": "beauty", 41 | "id": 5 42 | }, 43 | { 44 | "title": "6 Effective Digital Marketing Strategies for Startup in 2021", 45 | "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", 46 | "author": "Tasfia", 47 | "blogImage": "https://siit.com.bd/wp-content/uploads/2019/12/digital-markting.jpg", 48 | "category": "technology", 49 | "id": 6 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-blog", 3 | "homepage": "http://tasfiaislam.github.io/react-blog", 4 | "version": "0.1.0", 5 | "private": true, 6 | "dependencies": { 7 | "@apollo/client": "^3.4.7", 8 | "@craco/craco": "^6.2.0", 9 | "@testing-library/jest-dom": "^5.14.1", 10 | "@testing-library/react": "^11.2.7", 11 | "@testing-library/user-event": "^12.8.3", 12 | "graphql": "^15.5.1", 13 | "image-upload-react": "^1.4.9", 14 | "react": "^17.0.2", 15 | "react-dom": "^17.0.2", 16 | "react-router-dom": "^5.2.0", 17 | "react-scripts": "4.0.3", 18 | "web-vitals": "^1.1.2" 19 | }, 20 | "scripts": { 21 | "start": "craco start", 22 | "start-server": "npx json-server --watch data/db.json --port=3001", 23 | "predeploy": "npm run build", 24 | "deploy": "gh-pages -d build", 25 | "build": "craco build", 26 | "test": "craco test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "react-app", 32 | "react-app/jest" 33 | ] 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.2%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 1 chrome version", 43 | "last 1 firefox version", 44 | "last 1 safari version" 45 | ] 46 | }, 47 | "devDependencies": { 48 | "autoprefixer": "^9.8.6", 49 | "gh-pages": "^3.2.3", 50 | "postcss": "^7.0.36", 51 | "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.4" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/annarihu/blog-app-in-reactjs/8449dd2749827a1fdcc2293cda058858f9f81980/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 |Written by { data.blog.author }
62 |{ data.blog.body }
65 |Written by { blog.author }
59 |{ blog.body.slice(0,100) }Read More.....
60 | #{blog.category} 61 |