├── .gitignore ├── LICENSE ├── README.md ├── READMETR.md ├── components ├── blog │ ├── Comment.js │ ├── comment.styles.css │ └── index.js ├── container.js ├── footer.js ├── header.js ├── index.js ├── profile-bar.js ├── reactions-bar.js └── reactions-bar.styles.css ├── config.js ├── next.config.js ├── now.json ├── package.json ├── pages ├── _app.js ├── blog │ ├── [...blog].js │ └── detail.scss ├── index.js └── tag │ └── [...tag].js ├── utils ├── ApiService.js └── index.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,react 3 | # Edit at https://www.gitignore.io/?templates=node,react 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional REPL history 62 | .node_repl_history 63 | 64 | # Output of 'npm pack' 65 | *.tgz 66 | 67 | # Yarn Integrity file 68 | .yarn-integrity 69 | 70 | # dotenv environment variables file 71 | .env 72 | .env.test 73 | 74 | # parcel-bundler cache (https://parceljs.org/) 75 | .cache 76 | 77 | # next.js build output 78 | .next 79 | 80 | # nuxt.js build output 81 | .nuxt 82 | 83 | # rollup.js default build output 84 | dist/ 85 | 86 | # Uncomment the public line if your project uses Gatsby 87 | # https://nextjs.org/blog/next-9-1#public-directory-support 88 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 89 | # public 90 | 91 | # Storybook build outputs 92 | .out 93 | .storybook-out 94 | 95 | # vuepress build output 96 | .vuepress/dist 97 | 98 | # Serverless directories 99 | .serverless/ 100 | 101 | # FuseBox cache 102 | .fusebox/ 103 | 104 | # DynamoDB Local files 105 | .dynamodb/ 106 | 107 | # Temporary folders 108 | tmp/ 109 | temp/ 110 | 111 | ### react ### 112 | .DS_* 113 | **/*.backup.* 114 | **/*.back.* 115 | 116 | node_modules 117 | 118 | *.sublime* 119 | 120 | psd 121 | thumb 122 | sketch 123 | 124 | # End of https://www.gitignore.io/api/node,react 125 | 126 | 127 | .now 128 | .vercel 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Faruk Oruç 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Welcome to github-blog 👋

2 |

3 | 4 | Version 5 | 6 | 7 | License: MIT 8 | 9 | 10 | Twitter: bufgix 11 | 12 |

13 | 14 | > A blog system that uses Github Issues 15 | 16 | ### 🏠 [Homepage](https://github-blog.now.sh/) 17 | 18 | ![banner](https://i.hizliresim.com/O5vCIe.png) 19 | 20 | [TURKÇE](https://github.com/bufgix/github-blog/blob/master/READMETR.md) 21 | 22 | The usual blog system. Except, all the backend is connected to Github. All blog posts are linked to the issues of a repo that you want. 23 | 24 | ## Installation 25 | 26 | Download the repo to your file system 27 | 28 | ```sh 29 | $ git clone https://github.com/bufgix/github-blog && cd github-blog 30 | ``` 31 | 32 | Install the required dependencies 33 | 34 | ```sh 35 | $ yarn 36 | # or 37 | $ npm install 38 | ``` 39 | 40 | then come to `config.js` and write your information 41 | 42 | ```javascript 43 | export default { 44 | // Github username 45 | username: "bufgix", 46 | // Repo name where you will write your blogs 47 | repoName: "bufgix.github.io", 48 | // If you want, you can automatically add a CV that based 49 | // on your github profile. It will appear on the homepage 50 | useGithubCv: true 51 | }; 52 | ``` 53 | 54 | Github-blog uses [Github API V4](https://developer.github.com/v4/), which uses graphql to pull data. That's why [Github access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) is needed. Create a token and give the following permissions 55 | 56 | - read:user 57 | - user:email 58 | - user:follow 59 | 60 | Copy the token and paste it into a `.env` file as follows 61 | 62 | ```env 63 | GITHUB_TOKEN=0f49a4540d7efc7272533bc5ba23243da8de8ecd 64 | ``` 65 | 66 | Then to run your blog locally 67 | 68 | ```sh 69 | yarn dev 70 | # or 71 | npm run dev 72 | ``` 73 | 74 | ## Publising Your Blog 75 | 76 | I use [zeit.co](https://zeit.co/), which is both easy and free. Download [Now CLI](https://zeit.co/download) to upload your blog to zeit. Then add the github token to the Now CLI 77 | 78 | ```sh 79 | $ now secrets add GITHUB_TOKEN 80 | ``` 81 | 82 | Publish your application with this command 83 | 84 | ```sh 85 | $ now deploy 86 | ``` 87 | 88 | After setting your project name, you can follow the application from zeit.co. 89 | 90 | ## Publishing Articles 91 | 92 | Submit a issue to the issues section of the repo that you specified in `config.json`. 93 | Then create a label named `Blog` and add it to your issue. Please note that issues without blog tag will not be shown. You can also create other tags and show what your post is about. 94 | 95 | --- 96 | 97 | I inspired the project from [this](https://github.com/saadpasta/react-blog-github) repo. Although basically doing the same, I made the project write with [Next.js](https://nextjs.org/) to be SEO friendly 98 | 99 | ## TODOS 100 | 101 | - ~~Footer~~ 102 | - ~~Social links~~ 103 | - ~~Comments implementation~~ 104 | - ~~Reaction implementation~~ 105 | - Pagination 106 | - ~~Error Handling~~ 107 | - ~~Add image viewer~~ 108 | - ~~[Github-CV](https://github.com/bufgix/github-cv) integration~~ 109 | - ~~Filter by tags~~ 110 | 111 | ## Author 112 | 113 | 👤 **bufgix** 114 | 115 | - Website: http://www.bufgix.space 116 | - Twitter: [@bufgix](https://twitter.com/bufgix) 117 | - Github: [@bufgix](https://github.com/bufgix) 118 | 119 | ## 🤝 Contributing 120 | 121 | Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/bufgix/github-blog/issues). 122 | 123 | ## Show your support 124 | 125 | Give a ⭐️ if this project helped you! 126 | 127 | ## 📝 License 128 | 129 | Copyright © 2020 [bufgix](https://github.com/bufgix).
130 | This project is [MIT](https://github.com/bufgix/github-blog/blob/master/LICENSE) licensed. 131 | 132 | --- 133 | 134 | _This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_ 135 | -------------------------------------------------------------------------------- /READMETR.md: -------------------------------------------------------------------------------- 1 |

Welcome to github-blog 👋

2 |

3 | 4 | Version 5 | 6 | 7 | License: MIT 8 | 9 | 10 | Twitter: bufgix 11 | 12 |

13 | 14 | > A blog system that using Github Issues 15 | 16 | ### 🏠 [Homepage](https://github-blog.now.sh/) 17 | 18 | ![banner](https://i.hizliresim.com/O5vCIe.png) 19 | 20 | Bildiğiniz blog sistemi fakat backendinin tamamı Github altyapısına bağlı. Tüm blog yazıları istediğiniz bir reponun issue'lerine bağlı. 21 | 22 | ## Yükleme 23 | 24 | Repoyu dosya sistemimize indirin 25 | 26 | ```sh 27 | $ git clone https://github.com/bufgix/github-blog && cd github-blog 28 | ``` 29 | 30 | Gerekli bağımlıkları yükleyin 31 | 32 | ```sh 33 | $ yarn 34 | # veya 35 | $ npm install 36 | ``` 37 | 38 | ardından `config.js` dosyasına gelip bilgilerinizi yazın 39 | 40 | ```javascript 41 | export default { 42 | // Github kullanıcı adınız 43 | username: "bufgix", 44 | // Profilinize bağlı ve bloglarınızı yazacağınız repo ismi 45 | repoName: "bufgix.github.io", 46 | // İsterseniz github profilinizi baz alarak otomatik olarak CV ekleyebilirsiniz. Anasayfada gözükecektir 47 | useGithubCv: true 48 | }; 49 | ``` 50 | 51 | Github-blog, verileri çekmek için graphql kullanan [Github API V4](https://developer.github.com/v4/)'ü kullanıyor. Bu yüzden [Github access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)'e ihtiyaç var. Bir token oluşturup; 52 | 53 | - read:user 54 | - user:email 55 | - user:follow 56 | 57 | izinlerini vemelisiniz. 58 | 59 | Token'i kopyalayın ve `.env` isminde bir dosya içine aşağıdaki gibi yapıştırın 60 | 61 | ```env 62 | GITHUB_TOKEN=0f49a4540d7efc7272533bc5ba23243da8de8ecd 63 | ``` 64 | 65 | Ardından blogunuzu localde çalıştırmak için 66 | 67 | ```sh 68 | yarn dev 69 | # veya 70 | npm run dev 71 | ``` 72 | 73 | ## Uygulamayı yayınlama 74 | 75 | Blogunuz istediğiniz bir VPS'de yayınlayabilceğiniz gibi, Ben hem kolay hem de ücretsiz olan [zeit.co](https://zeit.co/)'yu kullanıyoum. Blogunuzu zeit'e yüklemek için [Now CLI](https://zeit.co/download)'yi indirin. Ardından github tokeni, `Now CLI`'a ekleyin 76 | 77 | ```sh 78 | $ now secrets add GITHUB_TOKEN 79 | ``` 80 | 81 | Uygulamanızı şu komutla yayına alın 82 | 83 | ```sh 84 | $ now deploy 85 | ``` 86 | 87 | Proje isminizi kendinize göre ayarladıktan sonra [zeit.co](https://zeit.co) dan uygulamayı takip edebilirsiniz. 88 | 89 | ## Yazı Yayınlama 90 | 91 | `config.json` da belirtiğiniz reponun `issues` bölümüne bir issue açın. Ardından `Blog` isminde bir label yaratıp yazınıza ekleyin. Unutmayın `blog` tagı taşımayan issueler gösterilmiyecektir. Ayrıca başka başka tag'ler oluşturup yazınızın neyler ilgili oldugunu gösterebilirsiniz. 92 | 93 | --- 94 | 95 | Projeyi [bu](https://github.com/saadpasta/react-blog-github) repodan esinlendim. Temelde aynı şeyi yapıyor olsa da Projeyi [Next.js](https://nextjs.org/) ile yazarak SEO friendly olmasını sağladım. 96 | 97 | 98 | ## Author 99 | 100 | 👤 **bufgix** 101 | 102 | - Website: http://www.bufgix.space 103 | - Twitter: [@bufgix](https://twitter.com/bufgix) 104 | - Github: [@bufgix](https://github.com/bufgix) 105 | 106 | ## 🤝 Contributing 107 | 108 | Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/bufgix/github-blog/issues). 109 | 110 | ## Show your support 111 | 112 | Give a ⭐️ if this project helped you! 113 | 114 | ## 📝 License 115 | 116 | Copyright © 2020 [bufgix](https://github.com/bufgix).
117 | This project is [MIT](https://github.com/bufgix/github-blog/blob/master/LICENSE) licensed. 118 | 119 | --- 120 | 121 | _This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_ 122 | -------------------------------------------------------------------------------- /components/blog/Comment.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactionBar from "../reactions-bar"; 3 | import Markdown from "markdown-to-jsx"; 4 | import Moment from "moment"; 5 | import { ArticleLink, FullScreenImage } from "../index"; 6 | import styles from "./comment.styles.css"; 7 | 8 | function CommentList({ commentData }) { 9 | const { totalCount, nodes } = commentData; 10 | if (totalCount > 0) { 11 | return nodes.map((comment, index) => ( 12 | 13 | )); 14 | } 15 | return null 16 | } 17 | 18 | function Comment({ singleComment }) { 19 | const { 20 | author: { login, avatarUrl }, 21 | body, 22 | reactions, 23 | createdAt, 24 | lastEditedAt 25 | } = singleComment; 26 | return ( 27 |
28 |
29 | comment-profile-img 30 |
{login}
31 | 32 | {Moment(createdAt).fromNow()} {lastEditedAt ? "• Edited" : null} 33 | 34 |
35 |
36 | 49 | {body} 50 | 51 |
52 | 53 |
54 | ); 55 | } 56 | 57 | export default CommentList; 58 | -------------------------------------------------------------------------------- /components/blog/comment.styles.css: -------------------------------------------------------------------------------- 1 | .commentContainer { 2 | margin: 0 0 20px 0; 3 | width: 100%; 4 | border: 1px solid #e1e4e8; 5 | border-radius: 0.4em; 6 | } 7 | 8 | .commentHeader { 9 | padding: 5px; 10 | border-bottom: 1px solid #e1e4e8; 11 | position: relative; 12 | background-color: #f6f8fa; 13 | } 14 | .commentHeader::after { 15 | content: ""; 16 | position: absolute; 17 | left: 0; 18 | top: 50%; 19 | width: 0; 20 | height: 0; 21 | border: 7px solid transparent; 22 | border-right-color: #e1e4e8; 23 | border-left: 0; 24 | margin-top: -7px; 25 | margin-left: -7px; 26 | } 27 | 28 | .commentAuthor { 29 | display: inline; 30 | font-weight: 600; 31 | margin-left: 10px; 32 | margin-right: 5px; 33 | } 34 | .commentBody { 35 | padding: 12px 10px 12px 10px; 36 | } 37 | -------------------------------------------------------------------------------- /components/blog/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Link from "next/link"; 3 | import Moment from "moment"; 4 | import readingTime from "reading-time"; 5 | import elipsis from "text-ellipsis"; 6 | 7 | function BlogList({ data }) { 8 | return data.map((blog, index) => ( 9 | 10 | 11 |
12 |
13 | )); 14 | } 15 | 16 | function BlogCard({ data }) { 17 | return ( 18 |
19 | 20 |

21 | {data.title} 22 |

23 | 24 |
25 |
26 | {data.labels.nodes 27 | .filter(label => label.name !== "Blog") 28 | .map((label, index) => ( 29 | 30 | 37 | {label.name} 38 | 39 | 40 | ))} 41 |
42 |
43 | {Moment(data.createdAt).fromNow()} • {readingTime(data.bodyText).text} 44 |
45 |
46 |

{elipsis(data.bodyText, 300)}

47 | 48 | 49 |
Read more
50 | 51 |
52 | ); 53 | } 54 | 55 | import CommentList from "./Comment"; 56 | export { BlogList, CommentList }; 57 | -------------------------------------------------------------------------------- /components/container.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function Container({ children, className }) { 4 | return ( 5 |
6 | {children} 7 |
8 | ); 9 | } 10 | 11 | export default Container; 12 | -------------------------------------------------------------------------------- /components/footer.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import config from "../config"; 3 | 4 | function Footer() { 5 | return ( 6 | 7 | 37 | 38 | ); 39 | } 40 | 41 | export default Footer; 42 | -------------------------------------------------------------------------------- /components/header.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import config from "../config"; 3 | 4 | function Header({ profile }) { 5 | const [ready, setReady] = React.useState(false); 6 | 7 | // Most stupid solution. But it works 8 | React.useEffect(() => { 9 | setTimeout(() => { 10 | setReady(true); 11 | }, 0); 12 | }); 13 | 14 | return ( 15 |
16 | profile-pic 25 |

26 | {profile.name} 27 |

28 |

{profile.bio}

29 | {ready && ( 30 | 31 |
35 | {profile.email && ( 36 | 42 | )} 43 | {profile.websiteUrl && ( 44 | 50 | )} 51 | {profile.location && ( 52 |
53 | 54 | {profile.location} 55 |
56 | )} 57 | {profile.company && ( 58 |
59 | 60 | {profile.company} 61 |
62 | )} 63 |
64 | 65 | {config.useGithubCv && ( 66 | 74 | )} 75 |
76 | )} 77 |
78 | ); 79 | } 80 | 81 | export default Header; 82 | -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | import Container from "./container"; 2 | import Header from "./header"; 3 | import ProfileBar from "./profile-bar"; 4 | import ReactionsBar from "./reactions-bar"; 5 | import Footer from "./footer"; 6 | import ModalImage from "react-modal-image"; 7 | 8 | function FullScreenImage({ ...props }) { 9 | return ; 10 | } 11 | 12 | function ArticleLink({ children, ...props }) { 13 | return ( 14 | 15 | {children} 16 | 17 | ); 18 | } 19 | 20 | 21 | export { Container, Header, ProfileBar, ReactionsBar, Footer, FullScreenImage, ArticleLink }; 22 | -------------------------------------------------------------------------------- /components/profile-bar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { getUserData } from "../utils"; 3 | import ContentLoader from "react-content-loader"; 4 | import config from "../config"; 5 | 6 | const BarLoader = () => ( 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ); 22 | 23 | function ProfileBar({ className }) { 24 | // TODO: add loading 25 | const [profile, setProfile] = React.useState({}); 26 | const [loading, setLoading] = React.useState(true); 27 | 28 | React.useEffect(() => { 29 | async function fetchProfile() { 30 | const data = await getUserData(); 31 | setProfile(data); 32 | setLoading(false); 33 | } 34 | try { 35 | fetchProfile(); 36 | } catch (err) { 37 | console.log(err); 38 | } 39 | }, []); 40 | 41 | return ( 42 |
45 | {loading ? ( 46 | 47 | ) : ( 48 | 49 |
50 |
51 | profile-pic 57 |
58 | 59 |
60 |
61 | {profile.name} 62 | {" "} 63 | 64 | {config.username} 65 | 66 |
67 |

68 | {profile.bio} 69 |

70 |
71 |
72 |
76 | {profile.email && ( 77 | 83 | )} 84 | {profile.websiteUrl && ( 85 | 91 | )} 92 | {profile.location && ( 93 |
94 | 95 | {profile.location} 96 |
97 | )} 98 | {profile.company && ( 99 |
100 | 101 | {profile.company} 102 |
103 | )} 104 |
105 |
106 | )} 107 |
108 | ); 109 | } 110 | 111 | export default ProfileBar; 112 | -------------------------------------------------------------------------------- /components/reactions-bar.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from "./reactions-bar.styles.css"; 3 | 4 | function ReactionsBar({ reactionsData }) { 5 | const [reactions, setReactions] = React.useState({}); 6 | 7 | const prepareReactions = () => { 8 | let reactions = { 9 | THUMBS_DOWN: { content: "👎", count: 0, names: [] }, 10 | THUMBS_UP: { content: "👍", count: 0, names: [] }, 11 | HEART: { content: "❤️", count: 0, names: [] }, 12 | HOORAY: { content: "🎉", count: 0, names: [] }, 13 | LAUGH: { content: "🤣", count: 0, names: [] }, 14 | ROCKET: { content: "🚀", count: 0, names: [] }, 15 | CONFUSED: { content: "😕", count: 0, names: [] }, 16 | EYES: { content: "👀", count: 0, names: [] }, 17 | TOTAL_COUNT: reactionsData.totalCount 18 | }; 19 | if (reactions.TOTAL_COUNT) { 20 | reactionsData.nodes.forEach(reaction => { 21 | reactions[reaction.content].count += 1; 22 | reactions[reaction.content].names.push(reaction.user.login); 23 | }); 24 | } 25 | 26 | return reactions; 27 | }; 28 | 29 | React.useEffect(() => { 30 | setReactions(prepareReactions()); 31 | }, []); 32 | 33 | if (reactions.TOTAL_COUNT) { 34 | return ( 35 |
    36 | {Object.keys(reactions) 37 | .filter(reactionKey => reactions[reactionKey].count > 0) 38 | .map((reactionKey, index) => ( 39 |
  • 47 | {reactions[reactionKey].content} {reactions[reactionKey].count} 48 |
  • 49 | ))} 50 |
51 | ); 52 | } else { 53 | return null; 54 | } 55 | } 56 | 57 | export default ReactionsBar; 58 | -------------------------------------------------------------------------------- /components/reactions-bar.styles.css: -------------------------------------------------------------------------------- 1 | .reactionsList { 2 | width: 100%; 3 | border: 1px solid #e1e4e8; 4 | list-style-type: none; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | 9 | .reactionsListItem { 10 | display: inline-block; 11 | padding: 9px 15px 9px 15px; 12 | border-right: 1px solid #e1e4e8; 13 | } 14 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // Github username 3 | username: "bufgix", 4 | // Repo name where you will write your blogs 5 | repoName: "bufgix.github.io", 6 | // If you want, you can automatically add a CV that based 7 | // on your github profile. It will appear on the homepage 8 | useGithubCv: true 9 | }; 10 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const withSass = require("@zeit/next-sass"); 2 | const withCss = require("@zeit/next-css"); 3 | 4 | require("dotenv").config(); 5 | 6 | module.exports = withSass(withCss({ 7 | cssModules: true, 8 | env: { 9 | GITHUB_TOKEN: process.env.GITHUB_TOKEN 10 | } 11 | })); -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "env": { 4 | "GITHUB_TOKEN": "@github_token" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bufgix-blog-frontend", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "dev": "next", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@zeit/next-sass": "^1.0.1", 15 | "axios": "^0.21.1", 16 | "dotenv": "^8.2.0", 17 | "highlight.js": "^10.4.1", 18 | "markdown-to-jsx": "^6.11.4", 19 | "moment": "^2.24.0", 20 | "next": "^9.3.2", 21 | "node-sass": "^4.13.1", 22 | "react": "^16.13.0", 23 | "react-content-loader": "^5.0.2", 24 | "react-dom": "^16.13.0", 25 | "react-modal-image": "^2.5.0", 26 | "reading-time": "^1.2.0", 27 | "sweetalert2": "^9.10.3", 28 | "text-ellipsis": "^1.0.3" 29 | }, 30 | "devDependencies": {}, 31 | "description": "" 32 | } 33 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Head from "next/head"; 3 | import config from "../config"; 4 | import "./blog/detail.scss"; 5 | 6 | function App({ Component, pageProps }) { 7 | return ( 8 | 9 | 10 | {`${config.username} Blog`} 11 | 12 | 13 | 14 | 18 | 22 | 26 | 29 |