├── client ├── components │ ├── blog │ │ ├── Card │ │ │ ├── index.js │ │ │ └── Card.js │ │ ├── Search │ │ │ ├── index.js │ │ │ └── Search.js │ │ └── SmallCard │ │ │ ├── index.js │ │ │ └── SmallCard.js │ ├── Layout.js │ ├── authentication │ │ ├── PrivateRoute.js │ │ ├── Admin.js │ │ ├── Register.js │ │ └── LoginAuth.js │ ├── LandingPage │ │ ├── Layout.js │ │ ├── Navbar.js │ │ └── Footer.js │ ├── update │ │ ├── ReadNewBlog.js │ │ ├── Category.js │ │ ├── Tag.js │ │ ├── NewBlog.js │ │ └── UpdateNewBlog.js │ └── Header.js ├── static │ ├── assets │ │ ├── 27263.jpg │ │ ├── favicon.ico │ │ ├── Blog-Post.png │ │ ├── blackback.jpg │ │ ├── svg │ │ │ ├── Octocat.png │ │ │ ├── github.svg │ │ │ ├── tweet.svg │ │ │ └── developer.svg │ │ ├── blogNavbarIcon.png │ │ ├── coding.svg │ │ ├── Lantern.svg │ │ └── freelancing.svg │ └── img │ │ ├── blogscroll.gif │ │ ├── code.svg │ │ └── terminal.svg ├── hooks │ └── useLoaded.js ├── pages │ ├── userDashboard │ │ └── index.js │ ├── login.js │ ├── signup.js │ ├── adminDashboard │ │ ├── update │ │ │ ├── [slug].js │ │ │ ├── blog.js │ │ │ ├── category-tag.js │ │ │ └── editBlog.js │ │ └── index.js │ ├── profile │ │ └── [username].js │ ├── _document.js │ ├── taglists │ │ └── [slug].js │ ├── categories │ │ └── [slug].js │ ├── blogs │ │ ├── index.js │ │ └── [slug].js │ └── index.js ├── config.js ├── actions │ ├── user.js │ ├── tag.js │ ├── category.js │ ├── authentication.js │ └── blog.js ├── helpers │ └── ReactQuill.js ├── package.json └── .gitignore └── server ├── validators ├── tag.js ├── category.js ├── index.js └── auth.js ├── helpers ├── excerptTrim.js └── databaseErrorHandler.js ├── routes ├── user.js ├── auth.js ├── tag.js ├── category.js └── blog.js ├── models ├── tagSchema.js ├── categorySchema.js ├── blogSchema.js └── user.js ├── package.json ├── controllers ├── user.js ├── tag.js ├── category.js ├── userAuthentication.js └── blog.js ├── server.js └── .gitignore /client/components/blog/Card/index.js: -------------------------------------------------------------------------------- 1 | import Card from "./Card"; 2 | 3 | export default Card; -------------------------------------------------------------------------------- /client/components/blog/Search/index.js: -------------------------------------------------------------------------------- 1 | import Search from "./Search"; 2 | 3 | export default Search; -------------------------------------------------------------------------------- /client/components/blog/SmallCard/index.js: -------------------------------------------------------------------------------- 1 | import SmallCard from "./SmallCard"; 2 | 3 | export default SmallCard; -------------------------------------------------------------------------------- /client/static/assets/27263.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/assets/27263.jpg -------------------------------------------------------------------------------- /client/static/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/assets/favicon.ico -------------------------------------------------------------------------------- /client/static/img/blogscroll.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/img/blogscroll.gif -------------------------------------------------------------------------------- /client/static/assets/Blog-Post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/assets/Blog-Post.png -------------------------------------------------------------------------------- /client/static/assets/blackback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/assets/blackback.jpg -------------------------------------------------------------------------------- /client/static/assets/svg/Octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/assets/svg/Octocat.png -------------------------------------------------------------------------------- /client/static/assets/blogNavbarIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pramit-marattha/MongoDB-React-Express-Node-Fullstack-TechBlogsite/HEAD/client/static/assets/blogNavbarIcon.png -------------------------------------------------------------------------------- /server/validators/tag.js: -------------------------------------------------------------------------------- 1 | const {check} = require("express-validator"); 2 | 3 | exports.createTagValidator = [ 4 | check('name').not().isEmpty().withMessage("hold up!! Name is required") 5 | ]; -------------------------------------------------------------------------------- /server/validators/category.js: -------------------------------------------------------------------------------- 1 | const {check} = require("express-validator"); 2 | 3 | exports.createCategoryValidator = [ 4 | check('name').not().isEmpty().withMessage("hold up!! Name is required") 5 | ]; -------------------------------------------------------------------------------- /client/hooks/useLoaded.js: -------------------------------------------------------------------------------- 1 | import React,{useState,useEffect} from 'react' 2 | 3 | export const useLoaded = () => { 4 | const [loaded, setLoaded] = useState(false); 5 | useEffect(() => setLoaded(true), []); 6 | return loaded; 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /client/static/img/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/static/img/terminal.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/validators/index.js: -------------------------------------------------------------------------------- 1 | const {validationResult} = require("express-validator"); 2 | 3 | // middlewares 4 | exports.runValidation = (req,res,next) =>{ 5 | const errors = validationResult(req); 6 | if (!errors.isEmpty()){ 7 | return res.status(422).json({error:errors.array()[0].msg}) 8 | } 9 | next(); 10 | }; 11 | -------------------------------------------------------------------------------- /client/components/Layout.js: -------------------------------------------------------------------------------- 1 | import React,{useState,useEffect} from "react"; 2 | import Header from "./Header"; 3 | 4 | 5 | const Layout = ({children}) =>{ 6 | 7 | return ( 8 | <> 9 |
10 | {children} 11 | {/*

footer

*/} 12 | 13 | ) 14 | }; 15 | 16 | export default Layout; -------------------------------------------------------------------------------- /server/helpers/excerptTrim.js: -------------------------------------------------------------------------------- 1 | exports.excerptTrim = (str, length, delim, appendix) => { 2 | if (str.length <= length) return str; 3 | var trimmedString = str.substr(0, length + delim.length); 4 | var lastDelimIndex = trimmedString.lastIndexOf(delim); 5 | if (lastDelimIndex >= 0) trimmedString = trimmedString.substr(0, lastDelimIndex); 6 | if (trimmedString) trimmedString += appendix; 7 | return trimmedString; 8 | }; -------------------------------------------------------------------------------- /client/pages/userDashboard/index.js: -------------------------------------------------------------------------------- 1 | import Layout from "../../components/Layout"; 2 | import PrivateRoute from "../../components/authentication/PrivateRoute"; 3 | import Link from "next/link"; 4 | 5 | 6 | const UserIndex =() =>{ 7 | return( 8 | 9 | 10 |

User Dashboard

11 |
12 |
13 | ) 14 | } 15 | 16 | export default UserIndex; -------------------------------------------------------------------------------- /client/config.js: -------------------------------------------------------------------------------- 1 | import getConfig from "next/config"; 2 | 3 | const {publicRuntimeConfig} = getConfig(); 4 | export const API = publicRuntimeConfig.PRODUCTION ? publicRuntimeConfig.PRODUCTION_SITE : publicRuntimeConfig.DEVELOPMENT_SITE ; 5 | export const APP_NAME = publicRuntimeConfig.APP_NAME; 6 | 7 | 8 | export const DOMAIN = publicRuntimeConfig.PRODUCTION ? publicRuntimeConfig.DOMAIN_PRODUCTION : publicRuntimeConfig.DOMAIN_DEVELOPMENT ; 9 | -------------------------------------------------------------------------------- /server/routes/user.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router(); 3 | const {requireLogin,authenticationMiddleware} = require("../controllers/userAuthentication.js") 4 | const {profileReadRequest,publicProfileReadRequest} = require("../controllers/user.js") 5 | 6 | router.get('/profile',requireLogin,authenticationMiddleware,profileReadRequest); 7 | router.get('/user/:username',publicProfileReadRequest); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /client/actions/user.js: -------------------------------------------------------------------------------- 1 | import fetch from "isomorphic-fetch"; 2 | import { API } from "../config.js"; 3 | 4 | export const userPublicProfile = (username) => { 5 | return fetch(`${API}/api/user/${username}`, { 6 | method: 'GET', 7 | headers: { 8 | Accept: 'application/json', 9 | 10 | } 11 | }) 12 | .then(response => { 13 | return response.json(); 14 | }) 15 | .catch(error => console.log(error)); 16 | }; -------------------------------------------------------------------------------- /server/models/tagSchema.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const TagSchema = new mongoose.Schema( 4 | { 5 | name: { 6 | type: String, 7 | trim: true, 8 | required: true, 9 | max: 32 10 | }, 11 | slug: { 12 | type: String, 13 | unique: true, 14 | index: true 15 | } 16 | }, 17 | { timestamps: true } 18 | ); 19 | 20 | module.exports = mongoose.model("Tag", TagSchema); -------------------------------------------------------------------------------- /client/components/authentication/PrivateRoute.js: -------------------------------------------------------------------------------- 1 | import React ,{useState,useEffect} from "react"; 2 | import Router from "next/router"; 3 | import {isAuthenticated} from "../../actions/authentication"; 4 | 5 | const PrivateRoute = ({children})=>{ 6 | 7 | 8 | useEffect(()=>{ 9 | if(!isAuthenticated()){ 10 | Router.push(`/login`) 11 | } 12 | },[]) 13 | 14 | return ( 15 | <> 16 | {children} 17 | 18 | ) 19 | 20 | } 21 | 22 | export default PrivateRoute; -------------------------------------------------------------------------------- /server/models/categorySchema.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const CategorySchema = new mongoose.Schema( 4 | { 5 | name: { 6 | type: String, 7 | trim: true, 8 | required: true, 9 | max: 32 10 | }, 11 | slug: { 12 | type: String, 13 | unique: true, 14 | index: true 15 | } 16 | }, 17 | { timestamps: true } 18 | ); 19 | 20 | module.exports = mongoose.model("Category", CategorySchema); -------------------------------------------------------------------------------- /client/pages/login.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import LoginAuth from "../components/authentication/LoginAuth"; 4 | import Link from "next/link"; 5 | 6 | const Login =() =>{ 7 | return( 8 | 9 |

Login

10 |
11 |
12 | 13 |
14 |
15 |
16 | ) 17 | } 18 | 19 | export default Login; -------------------------------------------------------------------------------- /client/pages/signup.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Layout from "../components/Layout"; 3 | import Register from "../components/authentication/Register"; 4 | import Link from "next/link"; 5 | 6 | const Signup =() =>{ 7 | return( 8 | 9 |

Register New Account

10 |
11 |
12 | 13 |
14 |
15 |
16 | ) 17 | } 18 | 19 | export default Signup; -------------------------------------------------------------------------------- /client/components/authentication/Admin.js: -------------------------------------------------------------------------------- 1 | import React ,{useState,useEffect} from "react"; 2 | import Router from "next/router"; 3 | import {isAuthenticated} from "../../actions/authentication"; 4 | 5 | const Admin = ({children})=>{ 6 | 7 | 8 | useEffect(()=>{ 9 | if(!isAuthenticated()){ 10 | Router.push(`/login`); 11 | }else if (isAuthenticated().role !== 1){ 12 | Router.push(`/`); 13 | } 14 | },[]) 15 | 16 | return ( 17 | <> 18 | {children} 19 | 20 | ) 21 | 22 | } 23 | 24 | export default Admin; -------------------------------------------------------------------------------- /server/routes/auth.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router(); 3 | const {signup,login,logout} = require("../controllers/userAuthentication.js") 4 | // const {signin} = require("../controllers") 5 | // importing validators 6 | const {runValidation} = require("../validators") 7 | const {userSignupValidator,userLoginValidator} = require("../validators/auth") 8 | 9 | router.post('/signup',userSignupValidator,runValidation,signup); 10 | router.post('/login',userLoginValidator,runValidation,login); 11 | router.get('/logout',logout); 12 | 13 | module.exports = router; 14 | -------------------------------------------------------------------------------- /server/validators/auth.js: -------------------------------------------------------------------------------- 1 | const {check} = require("express-validator"); 2 | 3 | exports.userSignupValidator = [ 4 | check('name').not().isEmpty().withMessage("hold up!! Name is required"), 5 | check('email').isEmail().withMessage("Please enter valid email address"), 6 | check('password').isLength({min:6}).withMessage("password must be 6 characters"), 7 | ]; 8 | 9 | exports.userLoginValidator = [ 10 | check('email').isEmail().withMessage("Please enter valid email address"), 11 | check('password').isLength({min:6}).withMessage("password must be 6 characters"), 12 | ]; 13 | 14 | -------------------------------------------------------------------------------- /server/routes/tag.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router(); 3 | const {create,list,read,remove} = require("../controllers/tag.js") 4 | const {requireLogin,adminAuthenticationMiddleware} = require("../controllers/userAuthentication.js") 5 | 6 | const {runValidation} = require("../validators") 7 | const {createTagValidator} = require("../validators/Tag") 8 | 9 | router.post('/tag',createTagValidator,runValidation,requireLogin,adminAuthenticationMiddleware,create); 10 | router.get('/taglists',list) 11 | router.get('/tag/:slug',read) 12 | router.delete('/tag/:slug',requireLogin,adminAuthenticationMiddleware,remove) 13 | 14 | module.exports = router; 15 | -------------------------------------------------------------------------------- /client/components/LandingPage/Layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Navbar from './Navbar' 3 | import Footer from './Footer' 4 | import Head from 'next/head' 5 | 6 | const Layout = (props) => { 7 | return ( 8 | 9 | 10 | 14 | 15 | Tech BlogSite{props.title} 16 | 17 | 18 | 19 | {props.children} 20 |