├── config-example.json ├── .gitignore ├── static ├── img │ ├── fp.png │ ├── go.png │ ├── ml.png │ ├── chat.png │ ├── cpp.png │ ├── game.png │ ├── iot.png │ ├── java.png │ ├── php.png │ ├── rust.png │ ├── android.png │ ├── csharp.png │ ├── design.png │ ├── devops.png │ ├── kotlin.png │ ├── linux.png │ ├── og-card.png │ ├── python.png │ ├── thedevs.png │ ├── databases.png │ ├── devsshare.png │ ├── dartflutter.png │ ├── datascience.png │ ├── javascript.png │ ├── twitter-card.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── thedevs_greyscale.jpg │ ├── posts │ │ ├── simple-telegram-bot-nodejs.jpg │ │ ├── type-coercion-javascript.jpg │ │ ├── the-forth-programming-language.jpg │ │ ├── what-is-functional-programming.jpg │ │ ├── the-forth-programming-language │ │ │ └── forth-2.png │ │ ├── best-ui-libraries-and-frameworks-for-reactjs.jpg │ │ ├── you-have-been-using-console-wrong-the-whole-time.jpg │ │ ├── build-a-telegram-bot-with-node.js │ │ │ ├── nodejs-reddit-bot-1.gif │ │ │ ├── nodejs-reddit-bot-2.gif │ │ │ ├── nodejs-reddit-bot-3.gif │ │ │ └── nodejs-reddit-bot-4.gif │ │ ├── you-have-been-using-console-wrong-the-whole-time │ │ │ ├── arr.png │ │ │ └── obj.png │ │ └── best-ui-libraries-and-frameworks-for-reactjs │ │ │ ├── react-ui-libraries-1.png │ │ │ ├── react-ui-libraries-10.png │ │ │ ├── react-ui-libraries-2.png │ │ │ ├── react-ui-libraries-3.png │ │ │ ├── react-ui-libraries-4.png │ │ │ ├── react-ui-libraries-5.png │ │ │ ├── react-ui-libraries-6.png │ │ │ ├── react-ui-libraries-7.png │ │ │ ├── react-ui-libraries-8.png │ │ │ └── react-ui-libraries-9.png │ ├── telegram.svg │ ├── share │ │ ├── telegram.svg │ │ ├── facebook.svg │ │ ├── googleplus.svg │ │ ├── linkedin.svg │ │ ├── twitter.svg │ │ └── vk.svg │ ├── twitter.svg │ └── github.svg ├── js │ ├── analytics.js │ └── prism.js └── css │ ├── tables.css │ ├── main.scss │ ├── prism.scss │ ├── flexboxgrid.min.scss │ └── normalize.scss ├── post-format.md ├── .eslintrc.json ├── pages ├── post.js ├── index.js ├── blog.js └── _document.js ├── components ├── Blog │ ├── index.js │ ├── Header │ │ ├── index.js │ │ └── Menu.js │ └── Posts │ │ ├── index.js │ │ └── Post.js ├── Post │ ├── index.js │ ├── Header │ │ ├── Menu.js │ │ ├── index.js │ │ └── Logo.js │ ├── TopBar │ │ └── index.js │ ├── Share │ │ └── index.js │ └── Content │ │ └── index.js ├── Footer │ ├── Logo.js │ ├── Description.js │ ├── index.js │ └── Buttons.js ├── Header │ ├── Logo.js │ ├── index.js │ ├── Buttons.js │ └── Titles.js ├── Community │ ├── index.js │ └── Group.js ├── withRoot.js └── Subscription │ └── index.js ├── TODO.md ├── README.md ├── bot ├── index.js ├── updateGroupsJSON.sh └── groups.json ├── next.config.js ├── styles └── getContext.js ├── package.json ├── CONTRIBUTING.md ├── server.js └── posts ├── the-forth-programming-language.md ├── best-ui-libraries-and-frameworks-for-reactjs.md ├── you-have-been-using-console-wrong-the-whole-time.md ├── type-coercion-in-javascript.md ├── build-a-telegram-bot-with-node.js.md └── what-is-functional-programming.md /config-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "googleVerificationContent": "" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | .env 4 | config.json 5 | static/.well-known -------------------------------------------------------------------------------- /static/img/fp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/fp.png -------------------------------------------------------------------------------- /static/img/go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/go.png -------------------------------------------------------------------------------- /static/img/ml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/ml.png -------------------------------------------------------------------------------- /static/img/chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/chat.png -------------------------------------------------------------------------------- /static/img/cpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/cpp.png -------------------------------------------------------------------------------- /static/img/game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/game.png -------------------------------------------------------------------------------- /static/img/iot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/iot.png -------------------------------------------------------------------------------- /static/img/java.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/java.png -------------------------------------------------------------------------------- /static/img/php.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/php.png -------------------------------------------------------------------------------- /static/img/rust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/rust.png -------------------------------------------------------------------------------- /static/img/android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/android.png -------------------------------------------------------------------------------- /static/img/csharp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/csharp.png -------------------------------------------------------------------------------- /static/img/design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/design.png -------------------------------------------------------------------------------- /static/img/devops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/devops.png -------------------------------------------------------------------------------- /static/img/kotlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/kotlin.png -------------------------------------------------------------------------------- /static/img/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/linux.png -------------------------------------------------------------------------------- /static/img/og-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/og-card.png -------------------------------------------------------------------------------- /static/img/python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/python.png -------------------------------------------------------------------------------- /static/img/thedevs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/thedevs.png -------------------------------------------------------------------------------- /static/img/databases.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/databases.png -------------------------------------------------------------------------------- /static/img/devsshare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/devsshare.png -------------------------------------------------------------------------------- /static/img/dartflutter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/dartflutter.png -------------------------------------------------------------------------------- /static/img/datascience.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/datascience.png -------------------------------------------------------------------------------- /static/img/javascript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/javascript.png -------------------------------------------------------------------------------- /static/img/twitter-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/twitter-card.png -------------------------------------------------------------------------------- /static/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/favicon-16x16.png -------------------------------------------------------------------------------- /static/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/favicon-32x32.png -------------------------------------------------------------------------------- /static/img/thedevs_greyscale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/thedevs_greyscale.jpg -------------------------------------------------------------------------------- /static/img/posts/simple-telegram-bot-nodejs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/simple-telegram-bot-nodejs.jpg -------------------------------------------------------------------------------- /static/img/posts/type-coercion-javascript.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/type-coercion-javascript.jpg -------------------------------------------------------------------------------- /static/img/posts/the-forth-programming-language.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/the-forth-programming-language.jpg -------------------------------------------------------------------------------- /static/img/posts/what-is-functional-programming.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/what-is-functional-programming.jpg -------------------------------------------------------------------------------- /static/img/posts/the-forth-programming-language/forth-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/the-forth-programming-language/forth-2.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs.jpg -------------------------------------------------------------------------------- /post-format.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | img: 4 | date: yyyy, mm, dd 5 | author: 6 | cats: 7 | tags: 8 | --- 9 | ### Make a copy of this file in `/posts/` folder, delete this line and start writing! -------------------------------------------------------------------------------- /static/img/posts/you-have-been-using-console-wrong-the-whole-time.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/you-have-been-using-console-wrong-the-whole-time.jpg -------------------------------------------------------------------------------- /static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-1.gif -------------------------------------------------------------------------------- /static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-2.gif -------------------------------------------------------------------------------- /static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-3.gif -------------------------------------------------------------------------------- /static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/build-a-telegram-bot-with-node.js/nodejs-reddit-bot-4.gif -------------------------------------------------------------------------------- /static/img/posts/you-have-been-using-console-wrong-the-whole-time/arr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/you-have-been-using-console-wrong-the-whole-time/arr.png -------------------------------------------------------------------------------- /static/img/posts/you-have-been-using-console-wrong-the-whole-time/obj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/you-have-been-using-console-wrong-the-whole-time/obj.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-1.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-10.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-2.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-3.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-4.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-5.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-6.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-7.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-8.png -------------------------------------------------------------------------------- /static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevs-network/website/HEAD/static/img/posts/best-ui-libraries-and-frameworks-for-reactjs/react-ui-libraries-9.png -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "react" 4 | ], 5 | "parserOptions": { 6 | "ecmaVersion": 7, 7 | "sourceType": "module", 8 | "ecmaFeatures": { 9 | "jsx": true 10 | } 11 | }, 12 | "rules": { 13 | "semi": 1 14 | } 15 | } -------------------------------------------------------------------------------- /pages/post.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import withRoot from '../components/withRoot'; 3 | import BlogPost from '../components/Post'; 4 | 5 | const index = (props) => ( 6 | 7 | ); 8 | 9 | index.getInitialProps = async ({ query }) => { 10 | return { post: query } 11 | } 12 | 13 | export default withRoot(index); -------------------------------------------------------------------------------- /components/Blog/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './Header'; 3 | import Posts from './Posts'; 4 | import Subscription from '../Subscription'; 5 | 6 | const Blog = ({ posts, cats }) => ( 7 |
8 |
9 | 10 | 11 |
12 | ); 13 | 14 | export default Blog; -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ## TODOs 2 | 3 | - [x] Blog page 4 | - [x] Blog post page 5 | - [x] General style 6 | - [x] Footer 7 | - [x] Social meta tags for posts 8 | - [x] Use Webpack to import styles 9 | - [ ] Add CDN for images 10 | - [ ] Commenting system 11 | - [ ] Telegram preview 12 | - [ ] Loading bar 13 | - [ ] Subscription 14 | - [ ] Feedback/contact form 15 | - [ ] An about page to show admins(?!) 16 | -------------------------------------------------------------------------------- /static/js/analytics.js: -------------------------------------------------------------------------------- 1 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 2 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 3 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 4 | })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); 5 | 6 | ga('create', 'UA-97516317-2', 'auto'); 7 | ga('send', 'pageview'); -------------------------------------------------------------------------------- /components/Post/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './Header'; 3 | import TopBar from './TopBar'; 4 | import Content from './Content'; 5 | import Footer from '../Footer'; 6 | 7 | const BlogPost = ({ post }) => { 8 | return ( 9 |
10 |
11 | 12 | 13 |
14 |
15 | ); 16 | }; 17 | 18 | export default BlogPost; -------------------------------------------------------------------------------- /static/img/telegram.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Devs 2 | 3 | This is the official website for The Devs Network. Available at: https://thedevs.network/ 4 | 5 | ### Run localy 6 | 7 | The Devs uses [Next.js](https://github.com/zeit/next.js/tree/v3-beta) and [React](https://facebook.github.io/react/) with [Material-UI](https://github.com/callemall/material-ui). Make sure your Node.js version is > 7.6. 8 | 9 | ```javascript 10 | npm install 11 | npm run dev 12 | 13 | // now available on localhost:8168 14 | ``` 15 | -------------------------------------------------------------------------------- /static/img/share/telegram.svg: -------------------------------------------------------------------------------- 1 | Telegram icon -------------------------------------------------------------------------------- /static/img/share/facebook.svg: -------------------------------------------------------------------------------- 1 | Facebook icon -------------------------------------------------------------------------------- /components/Post/Header/Menu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Button from 'material-ui/Button'; 5 | import Home from 'material-ui-icons/Home'; 6 | 7 | const Menu = () => ( 8 |
9 | 12 | 15 |
16 | ); 17 | 18 | 19 | export default Menu; -------------------------------------------------------------------------------- /static/img/share/googleplus.svg: -------------------------------------------------------------------------------- 1 | Google+ icon -------------------------------------------------------------------------------- /static/img/share/linkedin.svg: -------------------------------------------------------------------------------- 1 | LinkedIn icon -------------------------------------------------------------------------------- /components/Footer/Logo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Avatar from 'material-ui/Avatar'; 5 | 6 | const styles = theme => ({ 7 | logo: { 8 | width: 72, 9 | height: 72, 10 | marginBottom: "1em", 11 | boxShadow: theme.shadows[8] 12 | } 13 | }); 14 | 15 | const Logo = ({classes}) => ( 16 |
17 | 18 |
19 | ) 20 | 21 | Logo.propTypes = { 22 | classes: PropTypes.object.isRequired 23 | } 24 | 25 | export default withStyles(styles)(Logo); -------------------------------------------------------------------------------- /components/Header/Logo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Avatar from 'material-ui/Avatar'; 5 | 6 | const styles = theme => ({ 7 | logo: { 8 | width: 145, 9 | height: 145, 10 | marginBottom: "1em", 11 | boxShadow: theme.shadows[4] 12 | } 13 | }); 14 | 15 | const Logo = ({ classes }) => ( 16 |
17 | 18 | 19 | 20 |
21 | ); 22 | 23 | Logo.propTypes = { 24 | classes: PropTypes.object.isRequired 25 | }; 26 | 27 | export default withStyles(styles)(Logo); -------------------------------------------------------------------------------- /components/Footer/Description.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Typography from 'material-ui/Typography'; 3 | 4 | const Description = () => ( 5 |
6 |
7 | 8 | / / 9 | 10 | 11 | The Devs is a community on Telegram that tries to gather developers around the world together and help them to chat and discuss about things they love. 12 | 13 |
14 |
15 | ); 16 | 17 | export default Description; -------------------------------------------------------------------------------- /static/img/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/img/share/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bot/index.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const groups = require('./groups.json'); 3 | 4 | const requestCount = (token, id) => { 5 | return axios.get(`https://api.telegram.org/bot${token}/getChatMembersCount?chat_id=${id}`); 6 | } 7 | 8 | module.exports = (token) => { 9 | return new Promise((resolve, reject) => { 10 | if (!token) return resolve(groups); 11 | const groupWithCounts = groups.map(async group => { 12 | const { displayName, name, id, link } = group; 13 | const count = await requestCount(token, group.id); 14 | return { 15 | displayName, 16 | name, 17 | id, 18 | link, 19 | count: count.data.result 20 | } 21 | }) 22 | Promise.all(groupWithCounts) 23 | .then(result => resolve(result)) 24 | .catch(() => resolve(groups)); 25 | }); 26 | } -------------------------------------------------------------------------------- /components/Header/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | 5 | import Logo from './Logo'; 6 | import Titles from './Titles'; 7 | import Buttons from './Buttons'; 8 | 9 | const styles = theme => ({ 10 | root: { 11 | flexGrow: 1, 12 | paddingTop: theme.spacing.unit * 13, 13 | paddingBottom: theme.spacing.unit * 13, 14 | backgroundColor: theme.palette.primary[700], 15 | boxShadow: theme.shadows[4], 16 | color: '#f5f5f5', 17 | zIndex: 999 18 | } 19 | }); 20 | 21 | const Header = ({ classes }) => ( 22 |
23 | 24 | 25 | 26 |
27 | ); 28 | 29 | Header.propTypes = { 30 | classes: PropTypes.object.isRequired 31 | }; 32 | 33 | export default withStyles(styles)(Header); -------------------------------------------------------------------------------- /components/Blog/Header/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | 5 | import Menu from './Menu'; 6 | import Logo from '../../Header/Logo'; 7 | import Titles from '../../Header/Titles'; 8 | 9 | const styles = theme => ({ 10 | root: { 11 | flexGrow: 1, 12 | paddingTop: theme.spacing.unit * 8, 13 | paddingBottom: theme.spacing.unit * 3, 14 | backgroundColor: theme.palette.primary[700], 15 | boxShadow: theme.shadows[4], 16 | color: '#f5f5f5' 17 | } 18 | }); 19 | 20 | const Header = ({ classes, cats }) => ( 21 |
22 | 23 | 24 | 25 |
26 | ); 27 | 28 | Header.PropTypes = { 29 | classes: PropTypes.object.isRequired 30 | }; 31 | 32 | export default withStyles(styles)(Header); -------------------------------------------------------------------------------- /static/img/github.svg: -------------------------------------------------------------------------------- 1 | GitHub icon 2 | -------------------------------------------------------------------------------- /components/Footer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | 5 | import Description from './Description'; 6 | import Buttons from './Buttons'; 7 | 8 | const styles = theme => ({ 9 | root: { 10 | backgroundColor: theme.palette.common.darkBlack, 11 | color: '#f5f5f5' 12 | }, 13 | container: { 14 | width: 1120, 15 | flexBasis: 1120, 16 | marginTop: 0, 17 | paddingTop: theme.spacing.unit * 13, 18 | paddingBottom: theme.spacing.unit * 13 19 | } 20 | }); 21 | 22 | const Footer = ({ classes }) => ( 23 |
24 |
25 | 26 | 27 |
28 |
29 | ) 30 | 31 | Footer.propTypes = { 32 | classes: PropTypes.object.isRequired 33 | } 34 | 35 | export default withStyles(styles)(Footer); -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const glob = require('glob') 3 | 4 | module.exports = { 5 | webpack: (config, { dev }) => { 6 | config.module.rules.push( 7 | { 8 | test: /\.(css|scss)/, 9 | loader: 'emit-file-loader', 10 | options: { 11 | name: 'dist/[path][name].[ext]' 12 | } 13 | } 14 | , 15 | { 16 | test: /\.css$/, 17 | use: ['babel-loader', 'raw-loader'] 18 | } 19 | , 20 | { 21 | test: /\.s(a|c)ss$/, 22 | use: ['babel-loader', 'raw-loader', 23 | { loader: 'sass-loader', 24 | options: { 25 | includePaths: ['styles', 'node_modules'] 26 | .map((d) => path.join(__dirname, d)) 27 | .map((g) => glob.sync(g)) 28 | .reduce((a, c) => a.concat(c), []) 29 | } 30 | } 31 | ] 32 | } 33 | ) 34 | return config; 35 | } 36 | } -------------------------------------------------------------------------------- /components/Blog/Posts/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Typography from 'material-ui/Typography'; 5 | 6 | import Post from './Post'; 7 | 8 | const styles = theme => ({ 9 | root: { 10 | flexGrow: 1, 11 | paddingTop: theme.spacing.unit * 11, 12 | paddingBottom: theme.spacing.unit * 11, 13 | backgroundColor: theme.palette.shades.light.background.default, 14 | color: '#f5f5f5', 15 | marginTop: 8 16 | }, 17 | container: { 18 | width: 1120, 19 | flexBasis: 1120 20 | } 21 | }); 22 | 23 | const showPosts = (post, index) => ( 24 | 25 | ); 26 | 27 | const Posts = ({ classes, posts }) => ( 28 |
29 |
30 | {posts.map(showPosts)} 31 |
32 |
33 | ); 34 | 35 | Posts.PropTypes = { 36 | classes: PropTypes.object.isRequired 37 | }; 38 | 39 | export default withStyles(styles)(Posts); -------------------------------------------------------------------------------- /static/img/share/vk.svg: -------------------------------------------------------------------------------- 1 | VK icon -------------------------------------------------------------------------------- /components/Header/Buttons.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Button from 'material-ui/Button'; 5 | 6 | const styles = theme => ({ 7 | svg: { 8 | width: 12, 9 | height: 12, 10 | marginRight: 8 11 | }, 12 | button: { 13 | marginRight: '.5em', 14 | marginLeft: '.5em' 15 | } 16 | }); 17 | 18 | const Buttons = ({ classes }) => ( 19 |
20 | 23 | 26 |
27 | ) 28 | 29 | Buttons.propTypes = { 30 | classes: PropTypes.object.isRequired 31 | } 32 | 33 | export default withStyles(styles)(Buttons); -------------------------------------------------------------------------------- /components/Post/Header/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Logo from './Logo'; 5 | import Menu from './Menu'; 6 | 7 | const styles = theme => ({ 8 | root: { 9 | flexGrow: 1, 10 | height: theme.spacing.unit * 54, 11 | backgroundColor: theme.palette.primary[700], 12 | boxShadow: theme.shadows[4], 13 | color: '#f5f5f5' 14 | }, 15 | container: { 16 | width: 1120, 17 | flexBasis: 1120, 18 | height: 88, 19 | alignItems: 'center' 20 | }, 21 | '@media screen and (max-width: 1120px)': { 22 | root: { 23 | height: theme.spacing.unit * 38 24 | }, 25 | container: { 26 | width: '100%', 27 | flexBasis: '100%' 28 | } 29 | } 30 | }); 31 | 32 | const Header = ({ classes }) => ( 33 |
34 |
35 | 36 | 37 |
38 |
39 | ); 40 | 41 | Header.PropTypes = { 42 | classes: PropTypes.object.isRequired 43 | }; 44 | 45 | export default withStyles(styles)(Header); -------------------------------------------------------------------------------- /components/Header/Titles.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Typography from 'material-ui/Typography'; 5 | 6 | const styles = () => ({ 7 | title: { 8 | textAlign: "center", 9 | color: 'inherit', 10 | fontWeight: 500, 11 | marginBottom: '.2em' 12 | }, 13 | subtitle: { 14 | textAlign: "center", 15 | color: 'inherit', 16 | marginBottom: '3em', 17 | fontWeight: 300, 18 | opacity: .7 19 | } 20 | }); 21 | 22 | const Titles = ({ classes }) => ( 23 |
24 |
25 | 26 | 27 | The Devs 28 | 29 | 30 |
31 |
32 | 33 | Developers community on Telegram 34 | 35 |
36 |
37 | ) 38 | 39 | Titles.propTypes = { 40 | classes: PropTypes.object.isRequired 41 | } 42 | 43 | export default withStyles(styles)(Titles); -------------------------------------------------------------------------------- /components/Blog/Header/Menu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Button from 'material-ui/Button'; 5 | 6 | const styles = theme => ({ 7 | container: { 8 | width: 1120, 9 | flexBasis: 1120, 10 | marginTop: theme.spacing.unit * 6 11 | } 12 | }); 13 | 14 | const showCats = (cat, index) => ( 15 | 18 | ); 19 | 20 | const Menu = ({ classes, cats }) => ( 21 |
22 |
23 |
24 | 27 | {cats.map(showCats)} 28 |
29 |
30 | 33 |
34 |
35 |
36 | ); 37 | 38 | Menu.PropTypes = { 39 | classes: PropTypes.object.isRequired 40 | }; 41 | 42 | 43 | export default withStyles(styles)(Menu); -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Head from 'next/head'; 3 | import withRoot from '../components/withRoot'; 4 | import Header from '../components/Header'; 5 | import Community from '../components/Community'; 6 | import Footer from '../components/Footer'; 7 | import Subscription from '../components/Subscription'; 8 | 9 | class Index extends Component { 10 | render() { 11 | return ( 12 |
13 | 14 | The Devs, Developers Community on Telegram. 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | 32 | export default withRoot(Index); 33 | -------------------------------------------------------------------------------- /components/Post/Header/Logo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Avatar from 'material-ui/Avatar'; 5 | import Typography from 'material-ui/Typography'; 6 | 7 | const styles = theme => ({ 8 | logoLink: { 9 | display: 'flex', 10 | alignItems: 'center' 11 | }, 12 | logo: { 13 | width: 44, 14 | height: 44, 15 | boxShadow: theme.shadows[4] 16 | }, 17 | title: { 18 | marginLeft: theme.spacing.unit * 2, 19 | color: '#f5f5f5', 20 | fontWeight: 500 21 | }, 22 | '@media screen and (max-width: 1120px)': { 23 | logo: { 24 | width: 40, 25 | height: 40 26 | }, 27 | title: { 28 | marginLeft: theme.spacing.unit, 29 | padding: '1em 0' 30 | } 31 | } 32 | }); 33 | 34 | const Logo = ({ classes }) => ( 35 |
36 | 37 | 38 | 39 | The Devs 40 | 41 | 42 |
43 | ); 44 | 45 | Logo.propTypes = { 46 | classes: PropTypes.object.isRequired 47 | }; 48 | 49 | export default withStyles(styles)(Logo); -------------------------------------------------------------------------------- /styles/getContext.js: -------------------------------------------------------------------------------- 1 | import { create, SheetsRegistry } from 'jss'; 2 | import preset from 'jss-preset-default'; 3 | import { createMuiTheme } from 'material-ui/styles'; 4 | import deepPurple from 'material-ui/colors/deepPurple'; 5 | import blue from 'material-ui/colors/blue'; 6 | import createGenerateClassName from 'material-ui/styles/createGenerateClassName'; 7 | 8 | const theme = createMuiTheme({ 9 | palette: { 10 | primary: deepPurple, 11 | secondary: blue, 12 | }, 13 | }); 14 | 15 | // Configure JSS 16 | const jss = create(preset()); 17 | jss.options.createGenerateClassName = createGenerateClassName; 18 | 19 | function createContext() { 20 | return { 21 | jss, 22 | theme, 23 | // This is needed in order to deduplicate the injection of CSS in the page. 24 | sheetsManager: new Map(), 25 | // This is needed in order to inject the critical CSS. 26 | sheetsRegistry: new SheetsRegistry(), 27 | }; 28 | } 29 | 30 | export default function getContext() { 31 | // Make sure to create a new store for every server-side request so that data 32 | // isn't shared between connections (which would be bad) 33 | if (!process.browser) { 34 | return createContext(); 35 | } 36 | 37 | // Reuse context on the client-side 38 | if (!global.__INIT_MATERIAL_UI__) { 39 | global.__INIT_MATERIAL_UI__ = createContext(); 40 | } 41 | 42 | return global.__INIT_MATERIAL_UI__; 43 | } 44 | -------------------------------------------------------------------------------- /components/Footer/Buttons.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Typography from 'material-ui/Typography'; 5 | import Button from 'material-ui/Button'; 6 | 7 | const styles = () => ({ 8 | root: { 9 | marginTop: '4em' 10 | }, 11 | svg: { 12 | width: 12, 13 | height: 12, 14 | marginRight: 8 15 | }, 16 | button: { 17 | marginRight: '.5em', 18 | marginLeft: '.5em' 19 | } 20 | }); 21 | 22 | const Buttons = ({ classes }) => ( 23 |
24 | 27 | 30 | 33 |
34 | ) 35 | 36 | Buttons.propTypes = { 37 | classes: PropTypes.object.isRequired 38 | } 39 | 40 | export default withStyles(styles)(Buttons); -------------------------------------------------------------------------------- /bot/updateGroupsJSON.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | exec > /tmp/tempgroup 5 | echo '[' 6 | for i in $(jq -r '.[] | "\(.displayName)💩\(.name)💩\(.id)💩\(.link)"' < groups.json); do 7 | #displayName=$(echo ${i} | awk -F💩 '{ print $1 }') 8 | name=$( echo ${i} | awk -F💩 '{ print $2 }') 9 | id=$( echo ${i} | awk -F💩 '{ print $3 }') 10 | link=$( echo ${i} | awk -F💩 '{ print $4 }') 11 | scrappedHTML=$(curl --silent https://t.me/joinchat/${link}) 12 | displayName=$(echo "${scrappedHTML}" | grep '' | sed 's///g' | sed 's/<\/span>//') 13 | memberCount=$(echo "${scrappedHTML}" | grep extra | cut -c30- | sed 's/ //g' | sed 's/members.*//g') 14 | imageLink=$(echo "${scrappedHTML}" | grep 'og:image' | cut -c36- | sed 's/">//g') 15 | if [[ ! -e ../static/img/${name}.png ]]; then 16 | #echo "Downloading missing group image!" 17 | curl --silent ${imageLink} > /tmp/groupimage.jpg 18 | convert /tmp/groupimage.jpg -resize 64x64 ../static/img/${name}.png 19 | fi 20 | cat << EOF 21 | { 22 | "displayName": "${displayName}", 23 | "name": "${name}", 24 | "id": "${id}", 25 | "link": "${link}", 26 | "count": ${memberCount} 27 | }, 28 | EOF 29 | done 30 | echo ']' 31 | 32 | # Yeet the final comma in "}," 33 | temp=$(cat /tmp/tempgroup) 34 | echo "${temp}" | tac | sed -z 's/},/}/' | tac > /tmp/tempgroup 35 | 36 | jq -r 'sort_by(.count) | reverse' < /tmp/tempgroup > groups.json 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "thedevs.network", 3 | "version": "1.0.0", 4 | "description": "Website for TheDevs Network", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "node server.js", 8 | "build": "next build", 9 | "start": "cross-env NODE_ENV=production node server.js" 10 | }, 11 | "dependencies": { 12 | "autoprefixer": "^6.7.7", 13 | "axios": "^0.16.2", 14 | "babel-plugin-module-resolver": "^2.7.1", 15 | "babel-plugin-wrap-in-js": "^1.1.1", 16 | "body-parser": "^1.18.2", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.16.2", 19 | "front-matter": "^2.2.0", 20 | "glob": "^7.1.2", 21 | "material-ui": "^1.0.0-beta.16", 22 | "material-ui-icons": "^1.0.0-beta.15", 23 | "minify-css-string": "^1.0.0", 24 | "moment": "^2.21.0", 25 | "next": "^4.2.3", 26 | "node-sass": "^4.7.2", 27 | "raw-loader": "^0.5.1", 28 | "react": "^16.0.0", 29 | "react-dom": "^16.0.0", 30 | "react-jss": "^7.2.0", 31 | "react-markdown": "^2.5.0", 32 | "react-svg": "^2.1.22", 33 | "sass-loader": "^4.1.1", 34 | "source-list-map": "^2.0.0", 35 | "speakingurl": "^14.0.1", 36 | "webpack": "^3.6.0" 37 | }, 38 | "devDependencies": { 39 | "ajv": "^5.2.3", 40 | "cross-env": "^5.1.6", 41 | "eslint-plugin-react": "^7.4.0" 42 | }, 43 | "keywords": [ 44 | "TheDevs", 45 | "website" 46 | ], 47 | "repository": { 48 | "type": "git", 49 | "url": "git+https://github.com/TheDevs-Network/website.git" 50 | }, 51 | "license": "GPL-2.0", 52 | "bugs": { 53 | "url": "https://github.com/TheDevs-Network/website/issues" 54 | }, 55 | "homepage": "https://github.com/TheDevs-Network/website#readme" 56 | } 57 | -------------------------------------------------------------------------------- /components/Community/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Typography from 'material-ui/Typography'; 5 | import Group from './Group'; 6 | import Button from 'material-ui/Button'; 7 | 8 | const styles = theme => ({ 9 | container: { 10 | width: 1120, 11 | flexBasis: 1120, 12 | marginTop: 8, 13 | paddingTop: theme.spacing.unit * 13, 14 | paddingBottom: theme.spacing.unit * 13, 15 | backgroundColor: theme.palette.shades.light.background.default 16 | }, 17 | title: { 18 | marginBottom: theme.spacing.unit * 7 19 | } 20 | }); 21 | 22 | const showGroups = (group, index) => ( 23 | 30 | ); 31 | 32 | const Community = ({ classes, groups }) => ( 33 |
34 |
35 |
36 | 37 | Join The Communities 38 | 39 |
40 |
41 | {groups.map(showGroups)} 42 |
43 |
44 | 47 |
48 |
49 |
50 | ) 51 | 52 | Community.PropTypes = { 53 | classes: PropTypes.object.isRequired 54 | } 55 | 56 | export default withStyles(styles)(Community); -------------------------------------------------------------------------------- /pages/blog.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Head from 'next/head'; 3 | import withRoot from '../components/withRoot'; 4 | import Blog from '../components/Blog'; 5 | 6 | const index = ({ posts, cats }) => ( 7 |
8 | 9 | The Devs Blog, Developers Community on Telegram. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | ); 21 | 22 | index.getInitialProps = async ({ req, query }) => { 23 | let posts = query; 24 | 25 | const cats = posts.reduce((a, b) => { 26 | let allcats = [...a]; 27 | const newcats = b.attributes.cats.split(', '); 28 | newcats.forEach(cat => { 29 | if (allcats.indexOf(cat) < 0) { 30 | allcats.push(cat); 31 | } 32 | }); 33 | return allcats; 34 | }, []); 35 | 36 | if (req.query) { 37 | if (req.query.cat) 38 | posts = posts.filter(post => 39 | post.attributes.cats.split(', ').indexOf(req.query.cat) >= 0 40 | ) 41 | if (req.query.tag) 42 | posts = posts.filter(post => 43 | post.attributes.tags.split(', ').indexOf(req.query.tag) >= 0 44 | ) 45 | } 46 | 47 | return { posts, cats }; 48 | } 49 | 50 | export default withRoot(index); -------------------------------------------------------------------------------- /components/withRoot.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { withStyles, MuiThemeProvider } from 'material-ui/styles'; 3 | import wrapDisplayName from 'recompose/wrapDisplayName'; 4 | import getContext from '../styles/getContext'; 5 | 6 | // Apply some reset 7 | const styles = theme => ({ 8 | '@global': { 9 | html: { 10 | background: theme.palette.background.default, 11 | WebkitFontSmoothing: 'antialiased', // Antialiasing. 12 | MozOsxFontSmoothing: 'grayscale', // Antialiasing. 13 | }, 14 | body: { 15 | margin: 0, 16 | }, 17 | }, 18 | }); 19 | 20 | let AppWrapper = props => props.children; 21 | 22 | AppWrapper = withStyles(styles)(AppWrapper); 23 | 24 | function withRoot(BaseComponent) { 25 | class WithRoot extends Component { 26 | static getInitialProps(ctx) { 27 | if (BaseComponent.getInitialProps) { 28 | return BaseComponent.getInitialProps(ctx); 29 | } 30 | 31 | return {}; 32 | } 33 | 34 | componentWillMount() { 35 | this.styleContext = getContext(); 36 | } 37 | 38 | componentDidMount() { 39 | // Remove the server-side injected CSS. 40 | const jssStyles = document.querySelector('#jss-server-side'); 41 | if (jssStyles && jssStyles.parentNode) { 42 | jssStyles.parentNode.removeChild(jssStyles); 43 | } 44 | } 45 | 46 | render() { 47 | return ( 48 | 52 | 53 | 54 | 55 | 56 | ); 57 | } 58 | } 59 | 60 | if (process.env.NODE_ENV !== 'production') { 61 | WithRoot.displayName = wrapDisplayName(BaseComponent, 'withRoot'); 62 | } 63 | 64 | return WithRoot; 65 | } 66 | 67 | export default withRoot; 68 | -------------------------------------------------------------------------------- /static/css/tables.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Pure v1.0.0 3 | Copyright 2013 Yahoo! 4 | Licensed under the BSD License. 5 | https://github.com/yahoo/pure/blob/master/LICENSE.md 6 | */ 7 | .pure-table { 8 | /* Remove spacing between table cells (from Normalize.css) */ 9 | border-collapse: collapse; 10 | border-spacing: 0; 11 | empty-cells: show; 12 | border: 1px solid #cbcbcb; 13 | } 14 | 15 | .pure-table caption { 16 | color: #000; 17 | font: italic 85%/1 arial, sans-serif; 18 | padding: 1em 0; 19 | text-align: center; 20 | } 21 | 22 | .pure-table td, 23 | .pure-table th { 24 | border-left: 1px solid #cbcbcb;/* inner column border */ 25 | border-width: 0 0 0 1px; 26 | font-size: inherit; 27 | margin: 0; 28 | overflow: visible; /*to make ths where the title is really long work*/ 29 | padding: 0.5em 1em; /* cell padding */ 30 | } 31 | 32 | /* Consider removing this next declaration block, as it causes problems when 33 | there's a rowspan on the first cell. Case added to the tests. issue#432 */ 34 | .pure-table td:first-child, 35 | .pure-table th:first-child { 36 | border-left-width: 0; 37 | } 38 | 39 | .pure-table thead { 40 | background-color: #e0e0e0; 41 | color: #000; 42 | text-align: left; 43 | vertical-align: bottom; 44 | } 45 | 46 | /* 47 | striping: 48 | even - #fff (white) 49 | odd - #f2f2f2 (light gray) 50 | */ 51 | .pure-table td { 52 | background-color: transparent; 53 | } 54 | .pure-table-odd td { 55 | background-color: #f2f2f2; 56 | } 57 | 58 | /* nth-child selector for modern browsers */ 59 | .pure-table-striped tr:nth-child(2n-1) td { 60 | background-color: #f2f2f2; 61 | } 62 | 63 | /* BORDERED TABLES */ 64 | .pure-table-bordered td { 65 | border-bottom: 1px solid #cbcbcb; 66 | } 67 | .pure-table-bordered tbody > tr:last-child > td { 68 | border-bottom-width: 0; 69 | } 70 | 71 | 72 | /* HORIZONTAL BORDERED TABLES */ 73 | 74 | .pure-table-horizontal td, 75 | .pure-table-horizontal th { 76 | border-width: 0 0 1px 0; 77 | border-bottom: 1px solid #cbcbcb; 78 | } 79 | .pure-table-horizontal tbody > tr:last-child > td { 80 | border-bottom-width: 0; 81 | } 82 | -------------------------------------------------------------------------------- /components/Blog/Posts/Post.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Card, { CardActions, CardContent, CardMedia } from 'material-ui/Card'; 5 | import getSlug from 'speakingurl'; 6 | import Typography from 'material-ui/Typography'; 7 | import Button from 'material-ui/Button'; 8 | 9 | const styles = theme => ({ 10 | card: { 11 | padding: 0, 12 | marginBottom: theme.spacing.unit * 4, 13 | cursor: 'pointer', 14 | transition: '.3s all ease', 15 | '&:hover': { 16 | transform: 'translateY(-1%)', 17 | boxShadow: theme.shadows[6] 18 | } 19 | }, 20 | media: { 21 | height: 297, 22 | backgroundPosition: 'center center' 23 | }, 24 | chip: { 25 | margin: theme.spacing.unit 26 | }, 27 | actions: { 28 | paddingRight: theme.spacing.unit * 2, 29 | paddingLeft: theme.spacing.unit * 2, 30 | paddingBottom: theme.spacing.unit * 2 31 | } 32 | }); 33 | 34 | const Post = ({ classes, post }) => ( 35 | 62 | ); 63 | 64 | Post.PropTypes = { 65 | classes: PropTypes.object.isRequired 66 | }; 67 | 68 | 69 | export default withStyles(styles)(Post); -------------------------------------------------------------------------------- /components/Community/Group.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import Paper from 'material-ui/Paper'; 5 | import Avatar from 'material-ui/Avatar'; 6 | import Typography from 'material-ui/Typography'; 7 | import Button from 'material-ui/Button'; 8 | 9 | const styles = theme => ({ 10 | root: { 11 | marginBottom: theme.spacing.unit * 4 12 | }, 13 | paper: { 14 | padding: theme.spacing.unit * 2, 15 | textAlign: 'left', 16 | overflow: 'hidden', 17 | transition: 'all .2s ease', 18 | '&:hover': { 19 | boxShadow: theme.shadows[8], 20 | transform: 'translateY(-1%)' 21 | } 22 | }, 23 | photo: { 24 | width: 64, 25 | height: 64, 26 | float: 'left', 27 | marginRight: theme.spacing.unit * 2, 28 | boxShadow: theme.shadows[4] 29 | }, 30 | typography: { 31 | marginBottom: '.3em', 32 | wordWrap: 'break-word', 33 | width: '140px', 34 | }, 35 | svg: { 36 | width: 10, 37 | height: 10, 38 | marginRight: 8 39 | } 40 | }); 41 | 42 | const Group = (props) => { 43 | const { classes, displayName, name, count, link } = props; 44 | return ( 45 |
46 | 47 |
48 | 49 |
50 | 51 | {displayName} 52 | 53 | 54 | {count} members 55 | 56 |
57 |
58 | 61 |
62 |
63 | ); 64 | }; 65 | 66 | Group.PropTypes = { 67 | classes: PropTypes.object.isRequired 68 | }; 69 | 70 | export default withStyles(styles)(Group); -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | - [How to write for The Devs blog?](#posts) 4 | 5 | ## Posts 6 | 7 | [The Devs blog](https://thedevs.network/blog) is an [open source](https://github.com/TheDevs-Network/website/tree/master/posts) blog where **anyone** can publish their aricles, provided it follows certain guidelines. 8 | 9 | ### Choosing a subject 10 | 11 | - Make sure the subject you're choosing is interesting and has the potential for **high quality** content. 12 | 13 | - Since our blog is pretty fresh, try to choose **trendy** topics on trendy languages, which will attract visitors, in turn helping them discover our community. 14 | 15 | - That said, if you're unsure about your subject, you can open an issue and ask for feedback. 16 | 17 | ### Format 18 | 19 | Our blog posts are written in Markdown. Make a copy of [`post-format.md`](post-format.md) in the [`/posts/`](/posts) folder and start writing! 20 | 21 | ### Post info 22 | 23 | If you look at any of our [blog posts](https://github.com/TheDevs-Network/website/edit/master/posts/build-a-telegram-bot-with-node.js.md), you will notice that the first section, called **front matter**, contains the **post information**. This section will be **omitted** from the final article. It includes these fields: 24 | 25 | - **title:** Post title in the blog. 26 | - **img:** Alt name for the article's featured image. (More info in image section) 27 | - **date:** Publishing date for your article, in _Y, M, D_ format. 28 | - **author:** Name of the article's author _(you)_. 29 | - **cats:** Categories, seprated by comma. 30 | - **tags:** Tags, seprated by comma. 31 | 32 | ### Images 33 | 34 | For the featured image of the article: 35 | - Image size must be **800x450** 36 | - Image format must be **jpg** and it should be optimized. 37 | - Add the image to **/static/img/posts**. 38 | - Rename it to match what you entered in the front matter above. 39 | 40 | For images you use inside the article, create a folder in the **/static/img/posts**, add all the images there and reference to that properly. 41 | 42 | **DO NOT use a copyrighted image, or an image that requires attribution.** You can use [Unsplash](https://unsplash.com/) if you need to use stock photos. 43 | 44 | ### Ready to create pull request 45 | 46 | Add the post in [posts](https://github.com/TheDevs-Network/website/tree/master/posts) folder. Make sure all images are properly referenced. 47 | > Note: If your post needs refining, others have the right to edit the content it is published. 48 | -------------------------------------------------------------------------------- /static/css/main.scss: -------------------------------------------------------------------------------- 1 | @import 'flexboxgrid.min'; 2 | @import 'normalize'; 3 | @import 'prism'; 4 | @import 'tables'; 5 | 6 | body { 7 | font: 16px/1.618 'Roboto', sans-serif; 8 | } 9 | 10 | a { 11 | color: inherit; 12 | text-decoration: none; 13 | } 14 | 15 | .post-body a { 16 | color: #448aff; 17 | border-bottom: 1px dotted #448aff; 18 | } 19 | 20 | .post-body a:hover { 21 | opacity: 0.8; 22 | border-bottom: none; 23 | } 24 | 25 | .post-body p, 26 | .post-body ul { 27 | font-size: 18px; 28 | margin: 0 0 1.5em; 29 | } 30 | 31 | .post-body h1, 32 | .post-body h2, 33 | .post-body h3, 34 | .post-body h4, 35 | .post-body h5 { 36 | margin: 0 0 0.2em; 37 | line-height: 1.2; 38 | } 39 | 40 | .post-body h1 { 41 | margin-top: 0; 42 | font-size: 3.827em; 43 | } 44 | 45 | .post-body h2 { 46 | font-size: 2.827em; 47 | } 48 | 49 | .post-body h3 { 50 | font-size: 1.999em; 51 | } 52 | 53 | .post-body h4 { 54 | font-size: 1.414em; 55 | } 56 | 57 | .post-body h1, 58 | .post-body h2, 59 | .post-body h3, 60 | .post-body h4, 61 | .post-body h5, 62 | .post-body p { 63 | width: 100%; 64 | color: #212121; 65 | } 66 | 67 | .post-body * { 68 | max-width: 100%; 69 | } 70 | 71 | .post-body img { 72 | display: block; 73 | margin: 0 auto 2em; 74 | box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 75 | 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12); 76 | } 77 | 78 | .post-body .gist { 79 | transform: scale(1.1, 1.1); 80 | margin: 1em 0; 81 | } 82 | 83 | .row { 84 | margin-left: 0; 85 | margin-right: 0; 86 | min-width:0; 87 | } 88 | 89 | .top-bar.active { 90 | top: 0; 91 | } 92 | 93 | .post-body pre { 94 | width: 100%; 95 | margin-bottom: 2em !important; 96 | } 97 | 98 | .post-body blockquote { 99 | margin: 0 0 2em; 100 | padding: 1em 2em; 101 | border-left: 12px solid #b39ddb; 102 | font-style: italic; 103 | } 104 | 105 | .post-body blockquote p:before { 106 | content: '" '; 107 | } 108 | 109 | .post-body blockquote p:after { 110 | content: ' "'; 111 | } 112 | 113 | .post-body table { 114 | margin-bottom: 2em; 115 | } 116 | 117 | @media only screen and (max-width: 48em) { 118 | .col-xs, 119 | .col-xs-1, 120 | .col-xs-10, 121 | .col-xs-11, 122 | .col-xs-12, 123 | .col-xs-2, 124 | .col-xs-3, 125 | .col-xs-4, 126 | .col-xs-5, 127 | .col-xs-6, 128 | .col-xs-7, 129 | .col-xs-8, 130 | .col-xs-9 { 131 | padding-right: 0.5em; 132 | padding-left: 0.5em; 133 | } 134 | } 135 | 136 | @media only screen and (max-width: 1120px) { 137 | .post-title { 138 | text-align: left; 139 | font-size: 2.4em !important; 140 | } 141 | 142 | .post-body h2 { 143 | font-size: 2em; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /components/Post/TopBar/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import AppBar from 'material-ui/AppBar'; 5 | import Toolbar from 'material-ui/Toolbar'; 6 | import Avatar from 'material-ui/Avatar'; 7 | import Typography from 'material-ui/Typography'; 8 | import Button from 'material-ui/Button'; 9 | 10 | const styles = theme => ({ 11 | logoLink: { 12 | display: 'flex', 13 | alignItems: 'center' 14 | }, 15 | root: { 16 | position: 'fixed', 17 | width: '100%', 18 | top: -100, 19 | transition: '.3s all ease', 20 | zIndex: 9 21 | }, 22 | container: { 23 | width: 1120, 24 | flexBasis: 1120 25 | }, 26 | appBar: { 27 | backgroundColor: theme.palette.primary[700] 28 | }, 29 | logo: { 30 | marginRight: theme.spacing.unit * 2, 31 | boxShadow: theme.shadows[4], 32 | float: 'left' 33 | }, 34 | '@media screen and (max-width: 1120px)': { 35 | appBar: { 36 | padding: '.5em .2em' 37 | }, 38 | logo: { 39 | margin: '0 .5em .5em 0' 40 | } 41 | } 42 | }); 43 | 44 | class TopBar extends Component { 45 | constructor() { 46 | super(); 47 | } 48 | 49 | componentDidMount() { 50 | let lastScroll = 0; 51 | const bar = document.querySelector('.top-bar'); 52 | 53 | window.addEventListener('scroll', (e) => { 54 | const currentScroll = window.pageYOffset || document.documentElement.scrollTop; 55 | if (lastScroll > currentScroll && currentScroll > 300) 56 | bar.classList.add('active') 57 | else 58 | bar.classList.remove('active') 59 | lastScroll = currentScroll; 60 | }); 61 | } 62 | 63 | render() { 64 | return ( 65 |
66 | 67 | 68 |
69 | 77 |
78 | 81 | 84 |
85 |
86 |
87 |
88 |
89 | ); 90 | } 91 | } 92 | 93 | TopBar.PropTypes = { 94 | classes: PropTypes.object.isRequired 95 | }; 96 | 97 | export default withStyles(styles)(TopBar); -------------------------------------------------------------------------------- /static/css/prism.scss: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+git+go+graphql+json+python+jsx+scss */ 2 | /** 3 | * prism.js default theme for JavaScript, CSS and HTML 4 | * Based on dabblet (http://dabblet.com) 5 | * @author Lea Verou 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: black; 11 | background: none; 12 | text-shadow: 0 1px white; 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 32 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 33 | text-shadow: none; 34 | background: #b3d4fc; 35 | } 36 | 37 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 38 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 39 | text-shadow: none; 40 | background: #b3d4fc; 41 | } 42 | 43 | @media print { 44 | code[class*="language-"], 45 | pre[class*="language-"] { 46 | text-shadow: none; 47 | } 48 | } 49 | 50 | /* Code blocks */ 51 | pre[class*="language-"] { 52 | padding: 1em; 53 | margin: .5em 0; 54 | overflow: auto; 55 | } 56 | 57 | :not(pre) > code[class*="language-"], 58 | pre[class*="language-"] { 59 | background: #f5f2f0; 60 | } 61 | 62 | /* Inline code */ 63 | :not(pre) > code[class*="language-"] { 64 | padding: .1em; 65 | border-radius: .3em; 66 | white-space: normal; 67 | } 68 | 69 | .token.comment, 70 | .token.prolog, 71 | .token.doctype, 72 | .token.cdata { 73 | color: slategray; 74 | } 75 | 76 | .token.punctuation { 77 | color: #999; 78 | } 79 | 80 | .namespace { 81 | opacity: .7; 82 | } 83 | 84 | .token.property, 85 | .token.tag, 86 | .token.boolean, 87 | .token.number, 88 | .token.constant, 89 | .token.symbol, 90 | .token.deleted { 91 | color: #905; 92 | } 93 | 94 | .token.selector, 95 | .token.attr-name, 96 | .token.string, 97 | .token.char, 98 | .token.builtin, 99 | .token.inserted { 100 | color: #690; 101 | } 102 | 103 | .token.operator, 104 | .token.entity, 105 | .token.url, 106 | .language-css .token.string, 107 | .style .token.string { 108 | color: #a67f59; 109 | background: hsla(0, 0%, 100%, .5); 110 | } 111 | 112 | .token.atrule, 113 | .token.attr-value, 114 | .token.keyword { 115 | color: #07a; 116 | } 117 | 118 | .token.function { 119 | color: #DD4A68; 120 | } 121 | 122 | .token.regex, 123 | .token.important, 124 | .token.variable { 125 | color: #e90; 126 | } 127 | 128 | .token.important, 129 | .token.bold { 130 | font-weight: bold; 131 | } 132 | .token.italic { 133 | font-style: italic; 134 | } 135 | 136 | .token.entity { 137 | cursor: help; 138 | } 139 | 140 | -------------------------------------------------------------------------------- /components/Post/Share/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { withStyles } from 'material-ui/styles'; 4 | import ReactSVG from 'react-svg'; 5 | import Typography from 'material-ui/Typography'; 6 | import IconButton from 'material-ui/IconButton'; 7 | import DeleteIcon from 'material-ui-icons/Delete'; 8 | 9 | const styles = theme => ({ 10 | shareComp: { 11 | display: 'flex', 12 | width: '100%', 13 | margin: '.5em 0 0', 14 | flexDirection: 'column', 15 | alignContent: 'center', 16 | '& a': { 17 | borderBottom: 'none !important', 18 | } 19 | }, 20 | shareIcons: { 21 | flexGrow: '1 1 100%', 22 | marginTop: '2em', 23 | display: 'flex', 24 | padding: '1em 2em', 25 | alignItems: 'center', 26 | background: '#eee', 27 | flexWrap: 'wrap', 28 | }, 29 | text: { 30 | width: 'auto !important', 31 | margin: '0 1em 0 0 !important', 32 | }, 33 | button: { 34 | transition: 'all .3s ease', 35 | margin: '1.1em', 36 | '&:hover': { 37 | '& svg': { 38 | fill: '#7B1FA2', 39 | }, 40 | }, 41 | }, 42 | svg: { 43 | width: 16, 44 | height: 16, 45 | margin: '0 !important', 46 | boxShadow: 'none !important', 47 | backgroundColor: 'transparent !important', 48 | } 49 | }); 50 | 51 | const Share = ({ classes, title }) => { 52 | return ( 53 |
54 |
55 | 56 | Share socially: 57 | 58 | 63 | 64 | 65 | 70 | 71 | 72 | 77 | 78 | 79 | 84 | 85 | 86 | 91 | 92 | 93 | 98 | 99 | 100 |
101 |
102 | ); 103 | }; 104 | 105 | export default withStyles(styles)(Share); -------------------------------------------------------------------------------- /components/Post/Content/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Head from 'next/head'; 3 | import PropTypes from 'prop-types'; 4 | import getSlug from 'speakingurl'; 5 | import { withStyles } from 'material-ui/styles'; 6 | import Typography from 'material-ui/Typography'; 7 | import Chip from 'material-ui/Chip'; 8 | import ReactMarkdown from 'react-markdown'; 9 | import Share from '../Share'; 10 | import Subscription from '../../Subscription'; 11 | 12 | const styles = theme => ({ 13 | root: { 14 | flexGrow: 1, 15 | marginTop: -theme.spacing.unit * 40, 16 | paddingBottom: "2.5em" 17 | }, 18 | container: { 19 | width: 1120, 20 | flexBasis: 1120 21 | }, 22 | image: { 23 | width: 800, 24 | height: 450, 25 | marginBottom: theme.spacing.unit * 8, 26 | boxShadow: theme.shadows[16] 27 | }, 28 | body: { 29 | width: 672, 30 | marginTop: theme.spacing.unit * 10 31 | }, 32 | '@media screen and (max-width: 1120px)': { 33 | root: { 34 | marginTop: -theme.spacing.unit * 20 35 | }, 36 | container: { 37 | width: '100%', 38 | flexBasis: '100%' 39 | }, 40 | image: { 41 | width: '92vw', 42 | height: '51.75vw' 43 | }, 44 | body: { 45 | width: '100%', 46 | padding: '0 .2em', 47 | marginTop: theme.spacing.unit * 8 48 | } 49 | } 50 | }); 51 | 52 | const showTags = (tag, index) => ( 53 | 54 | ); 55 | 56 | const Content = ({ classes, post }) => ( 57 |
58 | 59 | {post.attributes.title} 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 |
74 | 91 |
92 |
93 | 94 |
95 | ); 96 | 97 | Content.PropTypes = { 98 | classes: PropTypes.object.isRequired 99 | }; 100 | 101 | export default withStyles(styles)(Content); -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const fs = require('fs'); 3 | const express = require('express'); 4 | const next = require('next'); 5 | const bodyParser = require('body-parser'); 6 | const fm = require('front-matter'); 7 | const moment = require('moment'); 8 | const getSlug = require('speakingurl'); 9 | const axios = require('axios'); 10 | const getMembersCount = require('./bot'); 11 | 12 | const dev = process.env.NODE_ENV !== 'production'; 13 | const app = next({ dev }); 14 | const handle = app.getRequestHandler(); 15 | 16 | let state = { 17 | posts: [] 18 | }; 19 | 20 | getMembersCount(process.env.BOT_TOKEN) 21 | .then(groups => state.groups = groups) 22 | .catch(err => console.log(err)); 23 | 24 | setInterval(async () => { 25 | state.groups = await getMembersCount(process.env.BOT_TOKEN); 26 | }, 1000 * 60 * 60); 27 | 28 | fs.readdir('./posts', 'utf8', (err, files) => { 29 | if (err) throw err; 30 | files.forEach(file => { 31 | fs.readFile(`./posts/${file}`, 'utf8', (err, data) => { 32 | let post = fm(data); 33 | let date = post.attributes.date.split(', '); 34 | date[1] = date[1] - 1; 35 | date = moment(date) 36 | post.attributes.date = date; 37 | post.attributes.displayDate = date.format('MMM D') 38 | state.posts.push(post); 39 | if (state.posts.length === files.length) { 40 | state.posts.sort((a, b) => b.attributes.date - a.attributes.date); 41 | } 42 | }); 43 | }); 44 | }); 45 | 46 | const subscribe = (email) => { 47 | const list = process.env.MAILCHIMP_LIST; 48 | const token = process.env.MAILCHIMP_TOKEN; 49 | return new Promise((resolve, reject) => { 50 | if (!email) { 51 | reject('No email address has provided'); 52 | } 53 | if (!list || !token) { 54 | reject('API has not been provided.') 55 | } 56 | axios({ 57 | method: 'post', 58 | url: `https://us16.api.mailchimp.com/3.0/lists/${list}/members/`, 59 | headers: { 60 | 'Content-Type': 'application/json', 61 | 'Authorization': `Basic ${token}`, 62 | }, 63 | data: { 64 | email_address: email, 65 | status: 'subscribed', 66 | }, 67 | }) 68 | .then(res => resolve(res)) 69 | .catch(err => reject(err)) 70 | }); 71 | } 72 | 73 | app.prepare() 74 | .then(() => { 75 | const server = express(); 76 | 77 | server.use(bodyParser.urlencoded({ 78 | extended: true 79 | })); 80 | 81 | server.use(bodyParser.json()); 82 | 83 | server.use('/static', express.static('static')); 84 | server.use('/.well-known', express.static('.well-known')); 85 | 86 | server.get('/', (req, res) => { 87 | return app.render(req, res, '/', state.groups); 88 | }); 89 | 90 | server.get('/blog/', (req, res) => { 91 | return app.render(req, res, '/blog', state.posts); 92 | }); 93 | 94 | server.get('/blog/:post', (req, res) => { 95 | const post = state.posts.filter(item => 96 | getSlug(item.attributes.title) === getSlug(req.params.post) 97 | ); 98 | if (post.length < 1) return res.redirect('/404'); 99 | return app.render(req, res, '/post', ...post); 100 | }); 101 | 102 | server.post('/subscription', (req, res) => { 103 | subscribe(req.body.email) 104 | .then(response => res.status(200).send('subsribed!')) 105 | .catch(err => res.status(400).send({message: err})); 106 | }); 107 | 108 | server.get('/mailto/:mail', (req, res) => { 109 | const { mail } = req.params; 110 | res.redirect(`mailto:${mail}`); 111 | }); 112 | 113 | server.get('*', (req, res) => { 114 | return handle(req, res); 115 | }); 116 | 117 | server.listen(8168, (err) => { 118 | if (err) throw err; 119 | console.log('> Ready on http://localhost:8168'); 120 | }); 121 | }); 122 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Document, { Head, Main, NextScript } from 'next/document'; 3 | import JssProvider from 'react-jss/lib/JssProvider'; 4 | import getContext from '../styles/getContext'; 5 | import stylesheet from '../static/css/main.scss'; 6 | import minifyCSSString from 'minify-css-string'; 7 | import config from '../config.json' 8 | 9 | const customStyles = minifyCSSString(stylesheet); 10 | 11 | export default class MyDocument extends Document { 12 | static async getInitialProps(ctx) { 13 | const context = getContext(); 14 | const page = ctx.renderPage(Component => props => ( 15 | 16 | 17 | 18 | )); 19 | 20 | return { 21 | ...page, 22 | stylesContext: context, 23 | styles: ( 24 |