├── .babelrc ├── .editorconfig ├── .env.sample ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── antd ├── antd-config.js └── antd.less ├── components ├── antd │ ├── form │ │ └── index.js │ └── input │ │ └── index.js ├── clients.js ├── countDown │ ├── index.js │ └── style.js ├── head.js ├── layouts │ ├── doubleGrid.js │ ├── footer.js │ ├── header.js │ ├── mainLayout.js │ └── singleGrid.js ├── multiLingualNumber.js ├── people.js ├── react-css-grid.js ├── schedule.js ├── sponsorItem.js └── subscribeForm.js ├── hooks └── useIntl.js ├── localization ├── entries │ ├── en_US.js │ └── fa_IR.js ├── index.js └── locales │ ├── en_US.json │ └── fa_IR.json ├── mock ├── data.json └── users.json ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── _app.js ├── _document.js └── index.js ├── partials └── home │ └── style.js ├── public ├── icons │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── apple-icon-precomposed.png │ ├── apple-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── manifest.json │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ └── ms-icon-70x70.png ├── manifest.json ├── sitemap.xml └── static │ ├── favicon.ico │ ├── fonts │ ├── inter.woff2 │ └── vazir │ │ ├── eot │ │ ├── Vazir-Black.eot │ │ ├── Vazir-Bold.eot │ │ ├── Vazir-Light.eot │ │ ├── Vazir-Medium.eot │ │ ├── Vazir-Thin.eot │ │ └── Vazir.eot │ │ ├── ttf │ │ ├── Vazir-Black.ttf │ │ ├── Vazir-Bold.ttf │ │ ├── Vazir-Light.ttf │ │ ├── Vazir-Medium.ttf │ │ ├── Vazir-Thin.ttf │ │ └── Vazir.ttf │ │ ├── woff │ │ ├── Vazir-Black.woff │ │ ├── Vazir-Bold.woff │ │ ├── Vazir-Light.woff │ │ ├── Vazir-Medium.woff │ │ ├── Vazir-Thin.woff │ │ ├── Vazir.woff │ │ └── desktop.ini │ │ └── woff2 │ │ ├── Vazir-Black.woff2 │ │ ├── Vazir-Bold.woff2 │ │ ├── Vazir-Light.woff2 │ │ ├── Vazir-Medium.woff2 │ │ ├── Vazir-Thin.woff2 │ │ └── Vazir.woff2 │ ├── images │ ├── ReactConf.svg │ ├── contact.svg │ ├── hall.jpg │ ├── icon │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon.png │ │ └── favicon.ico │ ├── like.svg │ ├── partners │ │ ├── Binosha.png │ │ ├── flerbo.png │ │ ├── frontcast.png │ │ ├── karlib.svg │ │ ├── macneed.png │ │ ├── raychat.png │ │ ├── reacttehran.png │ │ ├── sazito.png │ │ ├── siamak.png │ │ ├── vip │ │ │ ├── hastnama-academy-color.svg │ │ │ ├── hastnama-color.svg │ │ │ ├── hastnama.svg │ │ │ ├── hastnama_academy.svg │ │ │ └── kidcoding.ir.svg │ │ ├── virgool.png │ │ ├── virgool.svg │ │ └── webbranding.png │ ├── people │ │ ├── ali.jpg │ │ ├── behrouz.jpg │ │ ├── majid.jpg │ │ ├── mehri.jpg │ │ ├── milad.jpg │ │ ├── pourya.jpg │ │ ├── samaneh.jpg │ │ ├── siamak.jpg │ │ └── spearkes.jpg │ ├── reactconf.png │ ├── speakerad.jpg │ ├── subscribe.jpg │ ├── subscribeIcon.svg │ ├── surprise.jpg │ ├── talking.jpg │ └── ticket.jpg │ ├── reactconf-iran-share.jpg │ └── video │ ├── pr.gif │ └── static.mp4 ├── reactconf.png ├── registerServiceWorker.js ├── routes.js ├── server.js ├── styles ├── injectGlobal.js ├── modules │ ├── colors.scss │ ├── grid.scss │ ├── timetable.scss │ └── typography.scss └── styles.scss └── utils ├── intlMessage.js ├── isRTL.js ├── masonary.js ├── shuffle.js └── utils.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"], 3 | "env": { 4 | "production": { 5 | "plugins": ["transform-remove-console"] 6 | } 7 | }, 8 | "plugins": [ 9 | ["@babel/plugin-proposal-class-properties"], 10 | ["inline-react-svg"], 11 | [ 12 | "import", 13 | { 14 | "libraryName": "antd", 15 | "style": true 16 | } 17 | ], 18 | [ 19 | "module-resolver", 20 | { 21 | "root": "./", 22 | "extensions": [".js"], 23 | "alias": { 24 | "components": "./components", 25 | "utils": "./utils", 26 | "mock": "./mock", 27 | "partials": "./partials", 28 | "styles": "./styles", 29 | "localization": "./localization", 30 | "hooks": "./hooks", 31 | "config": "./config" 32 | }, 33 | "cwd": "packagejson" 34 | } 35 | ] 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | # trim_trailing_whitespace = true 9 | # insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.env.sample: -------------------------------------------------------------------------------- 1 | API_URL=https://api.reactconf.ir/ 2 | RANDOM_USER_LIMIT=200 3 | REACT_CONF_DATE=July 30, 2020 08:00:00 4 | PORT=2000 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node 3 | # Edit at https://www.gitignore.io/?templates=node 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 | # vuepress build output 84 | .vuepress/dist 85 | 86 | # Serverless directories 87 | .serverless/ 88 | 89 | # FuseBox cache 90 | .fusebox/ 91 | 92 | # DynamoDB Local files 93 | .dynamodb/ 94 | *.iml 95 | /node_modules 96 | dist 97 | build 98 | .env 99 | .next 100 | .idea 101 | .DS_Store 102 | _MACOSX 103 | _next/ 104 | # End of https://www.gitignore.io/api/node 105 | /bundles 106 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": true 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | react conf banner 3 | 4 | # Next.js Boilerplate (ReactConf Iran website 2020) 5 | 6 |
Be familiar with next react project
7 | 8 |
A complete guide for learn react and also use it as boilerplate 9 |
10 | Created by Milad Heydari, Mehri Daei and maintained with ❤️ by an amazing react conf team. 11 | 12 |
13 | 14 | ## Features 15 | 16 |
17 | 18 |
Quick Scaffolding
19 |
You can create components, routes, make API call and also make your App more attractive with using AntDesign, besides you can have multilingual App.
20 | 21 |
Instant Feedback
22 | 23 |
Enjoy coding with good speed and awsome DX (Developer eXperience). As soon as you change CSS, SASS,LESS, JS, your changes are directly implemented without having to refresh your browser. One more thing Enjoy using one of the best UI libraries name AntDesign and finally have clean and formatted code.
24 | 25 |
Philosophy
26 | 27 | - **Purpose :**
React conf has been tried to have a positive effect on developer training. The only purpose of this boilerplate is to help those interested in development using react.js. We use different tools to show you how these tools work and also help you to compare them together.
28 | - **One Dependency :**
You will have only one build dependency. It uses Webpack, Babel. It provides a cohesive experience for you.
29 | - **No Configuration Required :**
You don't need to configure anything. Only required thing is to focus on writing code. You can reach a reasonably good configuration of both development and production builds.
30 | 31 | ## What's included ? 32 | 33 | - **React, Hooks.**
34 | - **ES6 & Next Generation JavaScript :**
Use object destructuring, arrow functions, JSX syntax and more.
35 | - **Next Generation CSS :** 36 | 37 | - **Styled-Components :**
It is powered of CSS and help you to write actual CSS code. you will have unique generated class names to keep your code coupsoled.
38 | - **SASS**
If it's easily for you to use SASS, so keep use it. we support SASS too.
39 | - **LESS** 40 |
At the end, with using this boilerplate you can ship only the styles that are on the page. This feature guide you to the best performance.
41 | 42 | - **React-intl:**
If you want to have scalable apps, you probably need to support multiple languages. We use react-intl in this boilerplate to have a multilingual app.
43 | - **Offline-First :**
Availability without network connection, INTERESTED :) , from the instant your users load the app, they can reach your app without network connection.
44 | - **Formatting :**
Don't worry about implementing clean code or formatted one. We use prettier and have some configuration in Babel. to being sure that your codes always are clean and formated.
45 | - **SEO :**
We support SEO (document head tags management ) for search engines that support indexing of JS content.
46 | - **Next-SEO** 47 | - **AntDesign :**
You can easily customize ant design component and also use the only component that you need them in your project. Considering these features, your app can meet a great performance.
48 | 49 | - **Next.js & Webpack Setting**
50 | 51 | - **Next-Compose-Plugin** 52 | - **OptimizeCSSAssetsPlugin :**
Next.js doesn't minify CSS files out of the box, so we've added the OptimizeCSSAssetsPlugin to handle this lack.
53 | - **TerserPlugin:**
This plugin uses terser to minify your JavaScript.
54 | - **BundleAnalyzer:**
Visualize the size of webpack output files with an interactive zoomable treemap.
55 | - **Transform Remove Console:**
This plugin removes all console.\* calls.
56 | - **Babel Plugin Module Resolver:**
A Babel plugin to add a new resolver for your modules when compiling your code using Babel. This plugin allows you to add new "root" directories that contain your modules. It also allows you to setup a custom alias for directories, specific files, or even other npm modules.
57 | - **cross-env** 58 | 59 | ## Environment Configuration 60 | 61 | The root directory of your application, contain a .env.example file. You should copy the file with .env. Your .env file should not be committed to your application's source control, since each developer / server using your application could require a different environment configuration. 62 | 63 | ## Quick start 64 | 65 | 1. Make sure that you have Node.js v10 or later and npm v5 or above installed. 66 | 67 | 2. Clone this repo using `git clone https://github.com/ReactConf/nextjs-boilerplate-reactconf-ir2020.git` 68 | 69 | 3. Move to the appropriate directory: `cd `.
70 | 71 | 4. Run `npm install` in order to install dependencies.
72 | 73 | 5.At this point you can run `npm start` to see the example app at `http://localhost:4000`. You can easily change this port by changing the `.env` file ._ 74 | -------------------------------------------------------------------------------- /antd/antd-config.js: -------------------------------------------------------------------------------- 1 | const cssLoaderConfig = require("@zeit/next-css/css-loader-config"); 2 | const lessToJS = require("less-vars-to-js"); 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | 6 | // Where your antd-custom.less file lives 7 | const themeVariables = lessToJS( 8 | fs.readFileSync(path.resolve(__dirname, "./antd.less"), "utf8") 9 | ); 10 | 11 | module.exports = (nextConfig = {}) => ({ 12 | ...nextConfig, 13 | ...{ 14 | webpack(config, options) { 15 | if (!options.defaultLoaders) { 16 | throw new Error( 17 | "This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade" 18 | ); 19 | } 20 | 21 | const { dev, isServer } = options; 22 | const { 23 | cssModules, 24 | cssLoaderOptions, 25 | postcssLoaderOptions, 26 | lessLoaderOptions = {} 27 | } = nextConfig; 28 | 29 | // for all less in clint 30 | const baseLessConfig = { 31 | extensions: ["less"], 32 | cssModules, 33 | cssLoaderOptions, 34 | postcssLoaderOptions, 35 | dev, 36 | isServer, 37 | loaders: [ 38 | { 39 | loader: "less-loader", 40 | options: { 41 | ...lessLoaderOptions, 42 | javascriptEnabled: true, 43 | modifyVars: themeVariables // make your antd custom effective 44 | } 45 | } 46 | ] 47 | }; 48 | 49 | config.module.rules.push({ 50 | test: /\.less$/, 51 | exclude: /node_modules/, 52 | use: cssLoaderConfig(config, baseLessConfig) 53 | }); 54 | 55 | // for antd less in client 56 | // disable antd css module 57 | const antdLessConfig = { 58 | ...baseLessConfig, 59 | ...{ 60 | cssModules: false, 61 | cssLoaderOptions: {}, 62 | postcssLoaderOptions: {} 63 | } 64 | }; 65 | config.module.rules.push({ 66 | test: /\.less$/, 67 | include: /node_modules/, 68 | use: cssLoaderConfig(config, antdLessConfig) 69 | }); 70 | 71 | // for antd less in server (yarn build) 72 | if (isServer) { 73 | const antStyles = /antd\/.*?\/style.*?/; 74 | const origExternals = [...config.externals]; 75 | config.externals = [ 76 | (context, request, callback) => { 77 | if (request.match(antStyles)) return callback(); 78 | if (typeof origExternals[0] === "function") { 79 | origExternals[0](context, request, callback); 80 | } else { 81 | callback(); 82 | } 83 | }, 84 | ...(typeof origExternals[0] === "function" 85 | ? [] 86 | : origExternals) 87 | ]; 88 | 89 | config.module.rules.unshift({ 90 | test: antStyles, 91 | use: "null-loader" 92 | }); 93 | } 94 | 95 | if (typeof nextConfig.webpack === "function") { 96 | return nextConfig.webpack(config, options); 97 | } 98 | 99 | return config; 100 | } 101 | } 102 | }); 103 | -------------------------------------------------------------------------------- /components/antd/form/index.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Form as AntForm } from "antd"; 3 | 4 | const Form = styled(AntForm)` 5 | .ant-form-item-has-error .ant-input:not([disabled]):hover, 6 | .ant-form-item-has-error .ant-input-affix-wrapper:not([disabled]):hover { 7 | box-shadow: rgb(55, 56, 62) 0px 0px 0px 1000px inset; 8 | background-color: transparent; 9 | border-color: transparent; 10 | } 11 | .ant-form-item-has-error .ant-input:focus, 12 | .ant-form-item-has-error .ant-input-affix-wrapper:focus, 13 | .ant-form-item-has-error .ant-input-focused, 14 | .ant-form-item-has-error .ant-input-affix-wrapper-focused { 15 | border-right-width: 0px; 16 | outline: 0; 17 | box-shadow: rgb(55, 56, 62) 0px 0px 0px 1000px inset; 18 | } 19 | .ant-form-vertical .ant-form-item-label { 20 | padding: 0px; 21 | } 22 | .ant-form-item-label { 23 | line-height: 45px; 24 | color: var(--foreground-color); 25 | } 26 | .ant-form-item-label > label::after { 27 | display: inline-block; 28 | margin-right: 4px; 29 | color: var(--foreground-color); 30 | font-size: 18px; 31 | font-family: SimSun, sans-serif; 32 | line-height: 1; 33 | content: "*"; 34 | position: relative; 35 | top: -5px; 36 | } 37 | .ant-form-item-label > label::before { 38 | content: ""; 39 | } 40 | .ant-form-item-explain, 41 | .ant-form-item-extra { 42 | padding-top: 5px; 43 | } 44 | `; 45 | export default Form; 46 | -------------------------------------------------------------------------------- /components/antd/input/index.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Input as AntInput } from "antd"; 3 | import { isRTL } from "utils/isRTL"; 4 | import { fontFamily } from "styles/injectGlobal"; 5 | const Input = styled(AntInput)` 6 | color: var(--foreground-color); 7 | direction: ${({ locale }) => (isRTL(locale) ? "rtl" : "ltr")}; 8 | text-align: ${({ locale }) => (isRTL(locale) ? "right" : "left")}; 9 | width: 100%; 10 | border: none; 11 | margin: 0; 12 | max-width: 450px; 13 | padding: 0 16px; 14 | position: relative; 15 | font-size: 16px; 16 | transition: background-color 5000s ease-in-out 0s; 17 | line-height: 50px; 18 | background-color: transparent; 19 | box-shadow: rgb(55, 56, 62) 0px 0px 0px 1000px inset; 20 | font-family: ${({ locale }) => 21 | isRTL(locale) ? fontFamily.persian : fontFamily.english}; 22 | &:focus { 23 | border-right: none; 24 | box-shadow: rgb(55, 56, 62) 0px 0px 0px 1000px inset; 25 | background-color: transparent; 26 | } 27 | `; 28 | export default Input; 29 | -------------------------------------------------------------------------------- /components/clients.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import LazyLoad from "react-lazyload"; 3 | import cx from "classnames"; 4 | 5 | const Clients = ({ data }) => { 6 | const {fullName, email} = data; 7 | return ( 8 |
9 | 10 |
11 | {fullName} 12 |
13 |
14 |
15 | ); 16 | }; 17 | export default Clients; 18 | -------------------------------------------------------------------------------- /components/countDown/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, Fragment } from "react"; 2 | import { Parallax } from "react-scroll-parallax"; 3 | import MultiLingualNumber from "components/multiLingualNumber"; 4 | import Style from "./style"; 5 | import IntlMessage from "utils/intlMessage"; 6 | import getConfig from "next/config"; 7 | const { 8 | publicRuntimeConfig: { REACT_CONF_DATE } 9 | } = getConfig(); 10 | 11 | function CountDown({ confDate, locale }) { 12 | const [days, setDays] = useState(0); 13 | const [isEnd, setIsEnd] = useState(false); 14 | let timeInterval; 15 | useEffect(() => { 16 | countDownTimer(); 17 | }, []); 18 | const countDownTimer = () => { 19 | const t = getTimeRemaining(); 20 | setDays(`${t.finalDays}`); 21 | setIsEnd(t.isEnd); 22 | if (t.isEnd) { 23 | clearInterval(timeInterval); 24 | } 25 | return t; 26 | }; 27 | const getTimeRemaining = () => { 28 | const currentTime = new Date(); 29 | const confTime = new Date(confDate); 30 | const timeToConf = confTime - currentTime; 31 | const finalDays = Math.floor(timeToConf / 86400000); 32 | const finalHours = Math.floor((timeToConf % 86400000) / 3600000); 33 | const finalMinutes = Math.floor( 34 | ((timeToConf % 86400000) % 3600000) / 60000 35 | ); 36 | const finalSeconds = Math.floor( 37 | (((timeToConf % 86400000) % 3600000) % 60000) / 1000 38 | ); 39 | return { 40 | isEnd: finalSeconds <= 0 && finalMinutes <= 0 && finalHours <= 0, 41 | finalDays 42 | }; 43 | }; 44 | if (!isEnd) { 45 | return ( 46 | 60 | ); 61 | } else { 62 | return ; 63 | } 64 | } 65 | CountDown.defaultProps = { 66 | confDate: REACT_CONF_DATE || "July 30, 2020 08:00:00" 67 | }; 68 | export default CountDown; 69 | -------------------------------------------------------------------------------- /components/countDown/style.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { isRTL } from "utils/isRTL"; 3 | 4 | const Style = styled.div` 5 | position: absolute; 6 | ${({ locale }) => 7 | isRTL(locale) ? "left: var(--gap)" : "right: var(--gap)"}; 8 | font-weight: 545; 9 | font-size: 25vw; 10 | color: #070708; 11 | top: 0; 12 | line-height: 0.75; 13 | text-align: right; 14 | letter-spacing: -0.02em; 15 | z-index: -1; 16 | .month { 17 | font-size: 0.75em; 18 | position: relative; 19 | top: 20px; 20 | } 21 | .counter { 22 | display: flex; 23 | font-weight: 500; 24 | color: var(--gray-color); 25 | opacity: 0.15; 26 | justify-content: center; 27 | margin: -1rem 0 0; 28 | letter-spacing: -0.07em; 29 | padding-right: var(--gap); 30 | min-height: 42px; 31 | } 32 | `; 33 | export default Style; 34 | -------------------------------------------------------------------------------- /components/head.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import NextHead from "next/head"; 3 | 4 | const Head = () => ( 5 | 6 |