├── .babelrc ├── .dockerignore ├── .editorconfig ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── launch.json ├── CHANGELOG.md ├── HOC └── withRoot.js ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── components ├── layout │ ├── Layout.js │ ├── Menus.js │ └── styles.js └── privateRoute │ └── PrivateRoute.js ├── config └── appConfig.js ├── flow-typed └── npm │ ├── babel-plugin-transform-async-to-generator_vx.x.x.js │ ├── babel-plugin-transform-regenerator_vx.x.x.js │ ├── babel-preset-es2015_vx.x.x.js │ ├── babel-preset-flow_vx.x.x.js │ ├── babel-preset-react_vx.x.x.js │ ├── babel-preset-stage-2_vx.x.x.js │ ├── eslint-plugin-flowtype_vx.x.x.js │ ├── eslint-plugin-react_vx.x.x.js │ ├── eslint_vx.x.x.js │ ├── flow-bin_v0.x.x.js │ └── next_vx.x.x.js ├── mock ├── fakeAPI.json └── userInfosMock.json ├── next.config.js ├── offline └── serviceWorker.js ├── package.json ├── pages ├── _document.js ├── about.js ├── index.js ├── login.js └── protected.js ├── preview.png ├── redux ├── middleware │ └── fetchMiddleware.js ├── modules │ ├── fakeModuleWithFetch.js │ ├── persistStore.js │ ├── reducers.js │ └── userAuth.js └── store │ ├── configureStore.dev.js │ ├── configureStore.js │ └── configureStore.prod.js ├── server.js ├── services ├── auth.js ├── fetchTools.js ├── registerBeforeinstallprompt.js ├── registerServiceWorker.js └── server │ └── asyncWrap.js ├── static ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── browserconfig.xml ├── css │ └── bootstrap.min.css ├── favicon-16x16.png ├── favicon-32x32.png ├── manifest.json ├── mstile-150x150.png ├── robot.txt ├── safari-pinned-tab.svg └── splashscreen-icon-512x512.png ├── styles └── getContext.js ├── typings.json ├── typings ├── globals │ ├── axios │ │ ├── index.d.ts │ │ └── typings.json │ ├── jss │ │ ├── index.d.ts │ │ └── typings.json │ ├── localforage │ │ ├── index.d.ts │ │ └── typings.json │ ├── material-ui │ │ ├── index.d.ts │ │ └── typings.json │ ├── moment │ │ ├── index.d.ts │ │ └── typings.json │ ├── recompose │ │ ├── index.d.ts │ │ └── typings.json │ ├── redux-thunk │ │ ├── index.d.ts │ │ └── typings.json │ └── redux │ │ ├── index.d.ts │ │ └── typings.json └── index.d.ts └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel", 4 | "es2015", 5 | "react", 6 | "stage-2", 7 | "flow" 8 | ], 9 | "plugins": [ 10 | "transform-regenerator", 11 | "transform-async-to-generator" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .git 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 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 -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "es6": true 7 | }, 8 | "plugins": [ 9 | "react", 10 | "flowtype" 11 | ], 12 | "extends": [ 13 | "plugin:react/recommended", 14 | "plugin:flowtype/recommended" 15 | ], 16 | "parserOptions": { 17 | "ecmaFeatures": { 18 | "arrowFunctions": true, 19 | "binaryLiterals": true, 20 | "blockBindings": true, 21 | "classes": true, 22 | "defaultParams": true, 23 | "destructuring": true, 24 | "forOf": true, 25 | "generators": true, 26 | "modules": true, 27 | "objectLiteralComputedProperties": true, 28 | "objectLiteralDuplicateProperties": true, 29 | "objectLiteralShorthandMethods": true, 30 | "objectLiteralShorthandProperties": true, 31 | "octalLiterals": true, 32 | "regexUFlag": true, 33 | "regexYFlag": true, 34 | "spread": true, 35 | "superInFunctions": true, 36 | "templateStrings": true, 37 | "unicodeCodePointEscapes": true, 38 | "globalReturn": true, 39 | "jsx": true 40 | } 41 | }, 42 | "rules": { 43 | // 44 | //Possible Errors 45 | // 46 | // The following rules point out areas where you might have made mistakes. 47 | // 48 | "comma-dangle": [ 49 | "error", 50 | "always-multiline" 51 | ], 52 | "no-cond-assign": 2, // disallow assignment in conditional expressions 53 | "no-console": 1, // disallow use of console (off by default in the node environment) 54 | "no-constant-condition": 2, // disallow use of constant expressions in conditions 55 | "no-control-regex": 2, // disallow control characters in regular expressions 56 | "no-debugger": 2, // disallow use of debugger 57 | "no-dupe-args": 2, // disallow duplicate arguments in functions 58 | "no-dupe-keys": 2, // disallow duplicate keys when creating object literals 59 | "no-duplicate-case": 2, // disallow a duplicate case label. 60 | "no-empty": 2, // disallow empty statements 61 | "no-empty-character-class": 2, // disallow the use of empty character classes in regular expressions 62 | "no-ex-assign": 2, // disallow assigning to the exception in a catch block 63 | "no-extra-boolean-cast": 2, // disallow double-negation boolean casts in a boolean context 64 | "no-extra-parens": 0, // disallow unnecessary parentheses (off by default) 65 | "no-extra-semi": 2, // disallow unnecessary semicolons 66 | "no-func-assign": 2, // disallow overwriting functions written as function declarations 67 | "no-inner-declarations": 2, // disallow function or variable declarations in nested blocks 68 | "no-invalid-regexp": 2, // disallow invalid regular expression strings in the RegExp constructor 69 | "no-irregular-whitespace": 2, // disallow irregular whitespace outside of strings and comments 70 | "no-negated-in-lhs": 2, // disallow negation of the left operand of an in expression 71 | "no-obj-calls": 2, // disallow the use of object properties of the global object (Math and JSON) as functions 72 | "no-regex-spaces": 2, // disallow multiple spaces in a regular expression literal 73 | "no-sparse-arrays": 2, // disallow sparse arrays 74 | "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement 75 | "use-isnan": 2, // disallow comparisons with the value NaN 76 | "valid-jsdoc": 2, // Ensure JSDoc comments are valid (off by default) 77 | "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string 78 | // 79 | // Best Practices 80 | // 81 | // These are rules designed to prevent you from making mistakes. 82 | // They either prescribe a better way of doing something or help you avoid footguns. 83 | // 84 | "prefer-const": [ 85 | "error", 86 | { 87 | "destructuring": "any", 88 | "ignoreReadBeforeAssign": false 89 | } 90 | ], 91 | "block-scoped-var": 0, // treat var statements as if they were block scoped (off by default). 0: deep destructuring is not compatible https://github.com/eslint/eslint/issues/1863 92 | "complexity": 0, // specify the maximum cyclomatic complexity allowed in a program (off by default) 93 | "consistent-return": 2, // require return statements to either always or never specify values 94 | "curly": 2, // specify curly brace conventions for all control statements 95 | "default-case": 2, // require default case in switch statements (off by default) 96 | "dot-notation": 2, // encourages use of dot notation whenever possible 97 | "eqeqeq": 2, // require the use of === and !== 98 | "guard-for-in": 2, // make sure for-in loops have an if statement (off by default) 99 | "no-alert": 2, // disallow the use of alert, confirm, and prompt 100 | "no-caller": 2, // disallow use of arguments.caller or arguments.callee 101 | "no-div-regex": 2, // disallow division operators explicitly at beginning of regular expression (off by default) 102 | //"no-else-return": 2, // disallow else after a return in an if (off by default) 103 | //"no-empty-label": 2, // disallow use of labels for anything other then loops and switches 104 | "no-eq-null": 2, // disallow comparisons to null without a type-checking operator (off by default) 105 | "no-eval": 2, // disallow use of eval() 106 | "no-extend-native": 2, // disallow adding to native types 107 | "no-extra-bind": 2, // disallow unnecessary function binding 108 | "no-fallthrough": 2, // disallow fallthrough of case statements 109 | "no-floating-decimal": 2, // disallow the use of leading or trailing decimal points in numeric literals (off by default) 110 | "no-implied-eval": 2, // disallow use of eval()-like methods 111 | "no-iterator": 2, // disallow usage of __iterator__ property 112 | "no-labels": 2, // disallow use of labeled statements 113 | "no-lone-blocks": 2, // disallow unnecessary nested blocks 114 | "no-loop-func": 2, // disallow creation of functions within loops 115 | "no-multi-spaces": 0, // disallow use of multiple spaces 116 | "no-multi-str": 2, // disallow use of multiline strings 117 | "no-native-reassign": 2, // disallow reassignments of native objects 118 | "no-new": 2, // disallow use of new operator when not part of the assignment or comparison 119 | "no-new-func": 2, // disallow use of new operator for Function object 120 | "no-new-wrappers": 2, // disallows creating new instances of String,Number, and Boolean 121 | "no-octal": 2, // disallow use of octal literals 122 | "no-octal-escape": 2, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251"; 123 | "no-param-reassign": 2, // disallow reassignment of function parameters (off by default) 124 | "no-process-env": 2, // disallow use of process.env (off by default) 125 | "no-proto": 2, // disallow usage of __proto__ property 126 | "no-redeclare": 2, // disallow declaring the same variable more then once 127 | "no-return-assign": 2, // disallow use of assignment in return statement 128 | "no-script-url": 2, // disallow use of javascript: urls. 129 | "no-self-compare": 2, // disallow comparisons where both sides are exactly the same (off by default) 130 | "no-sequences": 2, // disallow use of comma operator 131 | "no-throw-literal": 2, // restrict what can be thrown as an exception (off by default) 132 | "no-unused-expressions": 2, // disallow usage of expressions in statement position 133 | "no-void": 2, // disallow use of void operator (off by default) 134 | "no-warning-comments": [ 135 | 0, 136 | { 137 | "terms": [ 138 | "todo", 139 | "fixme" 140 | ], 141 | "location": "start" 142 | } 143 | ], // disallow usage of configurable warning terms in comments": 2, // e.g. TODO or FIXME (off by default) 144 | "no-with": 2, // disallow use of the with statement 145 | "radix": 2, // require use of the second argument for parseInt() (off by default) 146 | "vars-on-top": 2, // requires to declare all vars on top of their containing scope (off by default) 147 | "wrap-iife": 2, // require immediate function invocation to be wrapped in parentheses (off by default) 148 | "yoda": 2, // require or disallow Yoda conditions 149 | // 150 | // Strict Mode 151 | // 152 | // These rules relate to using strict mode. 153 | // 154 | "strict": 0, // controls location of Use Strict Directives. 0: required by `babel-eslint` 155 | // 156 | // Variables 157 | // 158 | // These rules have to do with variable declarations. 159 | // 160 | "no-catch-shadow": 2, // disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment) 161 | "no-delete-var": 2, // disallow deletion of variables 162 | "no-label-var": 2, // disallow labels that share a name with a variable 163 | "no-shadow": 2, // disallow declaration of variables already declared in the outer scope 164 | "no-shadow-restricted-names": 2, // disallow shadowing of names such as arguments 165 | "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block 166 | "no-undef-init": 2, // disallow use of undefined when initializing variables 167 | "no-undefined": 2, // disallow use of undefined variable (off by default) 168 | "no-unused-vars": 2, // disallow declaration of variables that are not used in the code 169 | "no-use-before-define": [ 170 | "error", 171 | { 172 | "functions": false, 173 | "classes": true 174 | } 175 | ], // disallow use of variables before they are defined 176 | // 177 | //Stylistic Issues 178 | // 179 | // These rules are purely matters of style and are quite subjective. 180 | // 181 | "indent": 0, 182 | "brace-style": 1, // enforce one true brace style (off by default) 183 | "camelcase": 1, // require camel case names 184 | "comma-spacing": [ 185 | 1, 186 | { 187 | "before": false, 188 | "after": true 189 | } 190 | ], // enforce spacing before and after comma 191 | "comma-style": [ 192 | 1, 193 | "last" 194 | ], // enforce one true comma style (off by default) 195 | "consistent-this": [ 196 | 1, 197 | "_this" 198 | ], // enforces consistent naming when capturing the current execution context (off by default) 199 | "eol-last": 1, // enforce newline at the end of file, with no multiple empty lines 200 | "func-names": 0, // require function expressions to have a name (off by default) 201 | "func-style": 0, // enforces use of function declarations or expressions (off by default) 202 | "max-nested-callbacks": [ 203 | 1, 204 | 3 205 | ], // specify the maximum depth callbacks can be nested (off by default) 206 | "new-cap": [ 207 | 1, 208 | { 209 | "newIsCap": true, 210 | "capIsNew": false 211 | } 212 | ], // require a capital letter for constructors 213 | "new-parens": 1, // disallow the omission of parentheses when invoking a constructor with no arguments 214 | "newline-after-var": 0, // allow/disallow an empty newline after var statement (off by default) 215 | "no-array-constructor": 1, // disallow use of the Array constructor 216 | "no-inline-comments": 0, // disallow comments inline after code (off by default) 217 | "no-lonely-if": 1, // disallow if as the only statement in an else block (off by default) 218 | "no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation 219 | "no-multiple-empty-lines": [ 220 | 1, 221 | { 222 | "max": 2 223 | } 224 | ], // disallow multiple empty lines (off by default) 225 | "no-nested-ternary": 1, // disallow nested ternary expressions (off by default) 226 | "no-new-object": 1, // disallow use of the Object constructor 227 | "no-spaced-func": 1, // disallow space between function identifier and application 228 | "no-ternary": 0, // disallow the use of ternary operators (off by default) 229 | //"no-trailing-spaces": 1, // disallow trailing whitespace at the end of lines 230 | //"no-underscore-dangle": 1, // disallow dangling underscores in identifiers 231 | "one-var": [ 232 | 1, 233 | "never" 234 | ], // allow just one var statement per function (off by default) 235 | "operator-assignment": [ 236 | 1, 237 | "never" 238 | ], // require assignment operator shorthand where possible or prohibit it entirely (off by default) 239 | "padded-blocks": [ 240 | 1, 241 | "never" 242 | ], // enforce padding within blocks (off by default) 243 | "quotes": [ 244 | 1, 245 | "single" 246 | ], // specify whether double or single quotes should be used 247 | "semi": [ 248 | 1, 249 | "always" 250 | ], // require or disallow use of semicolons instead of ASI 251 | "semi-spacing": [ 252 | 1, 253 | { 254 | "before": false, 255 | "after": true 256 | } 257 | ], // enforce spacing before and after semicolons 258 | "sort-vars": 0, // sort variables within the same declaration block (off by default) 259 | // "space-after-keywords": [1, "always"], // require a space after certain keywords (off by default) 260 | "space-before-blocks": [ 261 | 1, 262 | "always" 263 | ], // require or disallow space before blocks (off by default) 264 | "space-before-function-paren": [ 265 | 1, 266 | { 267 | "anonymous": "never", 268 | "named": "never" 269 | } 270 | ], // require or disallow space before function opening parenthesis (off by default) 271 | //"space-in-brackets": [1, "never"], // require or disallow spaces inside brackets (off by default) 272 | "space-in-parens": [ 273 | 1, 274 | "never" 275 | ], // require or disallow spaces inside parentheses (off by default) 276 | "space-unary-ops": [ 277 | 1, 278 | { 279 | "words": true, 280 | "nonwords": false 281 | } 282 | ], // Require or disallow spaces before/after unary operators (words on by default, nonwords off by default) 283 | "spaced-comment": [ 284 | 1, 285 | "always" 286 | ], // require or disallow a space immediately following the // in a line comment (off by default) 287 | "wrap-regex": 0, // require regex literals to be wrapped in parentheses (off by default) 288 | // 289 | // ECMAScript 6 290 | // 291 | // These rules are only relevant to ES6 environments and are off by default. 292 | // 293 | "no-var": 2, // require let or const instead of var (off by default) 294 | "generator-star-spacing": [ 295 | 2, 296 | "before" 297 | ], // enforce the spacing around the * in generator functions (off by default) 298 | // 299 | // Legacy 300 | // 301 | // The following rules are included for compatibility with JSHint and JSLint. 302 | // While the names of the rules may not match up with the JSHint/JSLint counterpart, 303 | // the functionality is the same. 304 | // 305 | "max-depth": [ 306 | 2, 307 | 3 308 | ], // specify the maximum depth that blocks can be nested (off by default) 309 | "max-len": [ 310 | 2, 311 | 300, 312 | 2 313 | ], // specify the maximum length of a line in your program (off by default) 314 | "max-params": [ 315 | 2, 316 | 5 317 | ], // limits the number of parameters that can be used in the function declaration. (off by default) 318 | "max-statements": 0, // specify the maximum number of statement allowed in a function (off by default) 319 | "no-bitwise": 0, // disallow use of bitwise operators (off by default) 320 | "no-plusplus": 2, // disallow use of unary operators, ++ and -- (off by default) 321 | // 322 | // eslint-plugin-react 323 | // 324 | // React specific linting rules for ESLint 325 | // 326 | "react/display-name": 0, // Prevent missing displayName in a React component definition 327 | //"react/jsx-quotes": [2, "double", "avoid-escape"], // Enforce quote style for JSX attributes 328 | "jsx-quotes": [ 329 | 2, 330 | "prefer-double" 331 | ], 332 | // "react/jsx-quotes": 0, 333 | "react/jsx-no-undef": 2, // Disallow undeclared variables in JSX 334 | "react/jsx-sort-props": 0, // Enforce props alphabetical sorting 335 | "react/jsx-uses-react": 2, // Prevent React to be incorrectly marked as unused 336 | "react/jsx-uses-vars": 2, // Prevent variables used in JSX to be incorrectly marked as unused 337 | // "react/jsx-first-prop-new-line": "multiline-multiprop", 338 | // "react/jsx-max-props-per-line": [1, { "when": "always" }], 339 | // "react/no-did-mount-set-state": [2, "allow-in-func"], // Prevent usage of setState in componentDidMount 340 | // "react/no-did-update-set-state": 2, // Prevent usage of setState in componentDidUpdate 341 | "react/no-multi-comp": 0, // Prevent multiple component definition per file 342 | "react/no-unknown-property": 2, // Prevent usage of unknown DOM property 343 | "react/prop-types": 2, // Prevent missing props validation in a React component definition 344 | "react/react-in-jsx-scope": 0, // Prevent missing React when using JSX: No more need in next js since react is global 345 | "react/self-closing-comp": 2, // Prevent extra closing tags for components without children 346 | "react/jsx-wrap-multilines": 2 // Prevent missing parentheses around multilines JSX 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | module.system=haste 11 | strip_root=true 12 | suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store* 3 | Icon? 4 | ._* 5 | 6 | # Windows 7 | Thumbs.db 8 | ehthumbs.db 9 | Desktop.ini 10 | 11 | # Linux 12 | .directory 13 | *~ 14 | 15 | # npm 16 | node_modules 17 | *.log 18 | *.gz 19 | 20 | # intelliJ 21 | .idea/ 22 | 23 | # Coveralls 24 | coverage 25 | 26 | # next 27 | .next/ 28 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.json 2 | **/*.txt 3 | **/*.xml 4 | **/*.svg 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "trailingComma": "all", 4 | "bracketSpacing": true, 5 | "jsxBracketSameLine": false, 6 | "singleQuote": true, 7 | "overrides": [], 8 | "printWidth": 80, 9 | "useTabs": false, 10 | "tabWidth": 2, 11 | "parser": "babylon" 12 | } 13 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. 3 | // Pointez pour afficher la description des attributs existants. 4 | // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "chrome", 9 | "request": "launch", 10 | "name": "Launch Chrome localhost:3000", 11 | "url": "http://localhost:3000", 12 | "webRoot": "${workspaceRoot}" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## 0.0.1 (COMING SOON) 3 | - first bricks of this starter 4 | -------------------------------------------------------------------------------- /HOC/withRoot.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React, { Component } from 'react'; 5 | import { withStyles, MuiThemeProvider } from 'material-ui/styles'; 6 | import wrapDisplayName from 'recompose/wrapDisplayName'; 7 | import getContext from '../styles/getContext'; 8 | import registerServiceWorker from '../services/registerServiceWorker'; 9 | import registerBeforeinstallprompt from '../services/registerBeforeinstallprompt'; 10 | // #endregion 11 | 12 | // #region Apply some style reset 13 | const styles = theme => ({ 14 | '@global': { 15 | html: { 16 | background: theme.palette.background.default, 17 | WebkitFontSmoothing: 'antialiased', // Antialiasing. 18 | MozOsxFontSmoothing: 'grayscale', // Antialiasing. 19 | }, 20 | body: { 21 | margin: 0, 22 | }, 23 | }, 24 | }); 25 | // #endregion 26 | 27 | // #region AppWrapper component 28 | let AppWrapper = props => props.children; 29 | 30 | AppWrapper = withStyles(styles)(AppWrapper); 31 | // #endregion 32 | 33 | // #region flow types 34 | type InitialProps = { 35 | req: any, 36 | res: any, 37 | pathname: string, 38 | query: any, 39 | asPath: string, 40 | isServer: boolean, 41 | store?: any, 42 | ...any, 43 | }; 44 | // #endregion 45 | 46 | // #region withRoot HOC 47 | function withRoot(BaseComponent) { 48 | class WithRoot extends Component { 49 | static getInitialProps(ctx: InitialProps) { 50 | if (BaseComponent.getInitialProps) { 51 | return BaseComponent.getInitialProps(ctx); 52 | } 53 | return {}; 54 | } 55 | 56 | // #region lifecycle methods 57 | componentWillMount() { 58 | this.styleContext = getContext(); 59 | } 60 | 61 | async componentDidMount() { 62 | try { 63 | // register service worker: 64 | await registerServiceWorker(); 65 | // install banner notification: 66 | await registerBeforeinstallprompt(); 67 | } catch (error) { 68 | console.log('service worker error: ', error); 69 | } 70 | 71 | // Remove the server-side injected CSS. 72 | const jssStyles = document.querySelector('#jss-server-side'); 73 | if (jssStyles && jssStyles.parentNode) { 74 | jssStyles.parentNode.removeChild(jssStyles); 75 | } 76 | } 77 | 78 | render() { 79 | return ( 80 | 84 | 85 | 86 | 87 | 88 | ); 89 | } 90 | // #endregion 91 | } 92 | /* eslint-disable no-process-env */ 93 | if (process.env.NODE_ENV !== 'production') { 94 | WithRoot.displayName = wrapDisplayName(BaseComponent, 'withRoot'); 95 | } 96 | /* eslint-enable no-process-env */ 97 | return WithRoot; 98 | } 99 | // #endregion 100 | 101 | export default withRoot; 102 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Version 2 | 1.2.0 3 | 4 | ### Node JS 5 | v7.x | v8.X | v9.X 6 | 7 | ### Browser 8 | Chrome 64.x | Safari 11.x 9 | 10 | ### OS version 11 | macOS | windows 10 | linux Ubuntu... 12 | 13 | ### Steps to reproduce 14 | 1. 15 | 2. 16 | 3. 17 | 18 | ### Expected behavior 19 | What should happen 20 | 21 | ### Actual behavior 22 | What is happening 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## LICENSE 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2018 Erwan DATIN 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PWA: Next JS + Redux + Redux persist + redux-devtools-extension + Material UI starter 2 | 3 | > A progressive web app starter with NextJS, redux and bootstrap 4 | 5 | 6 | ![preview](./preview.png) 7 | 8 | 9 | 10 | ## Detailed Content 11 | 12 | **Front:** 13 | 14 | * Next js (4.x+ [github :link:](https://github.com/zeit/next.js)) 15 | * React JS (16.x+ - [github :link:](https://github.com/facebook/react)) 16 | * redux (_as your application grows managing state will be a serious concern, save pain with Redux_) 17 | * redux-persist (_simplifies your NextJS state share between pages_ [github :link:](https://github.com/rt2zz/redux-persist)) 18 | * localForage 19 | * react-redux (_Redux is not specific to ReactJS, you could easily use it with Angular2 for instance_) 20 | * redux-thunk (_simple and does the job_) 21 | * next-redux-wrapper 22 | * redux-devtools-extension ([github :link:](https://github.com/zalmoxisus/redux-devtools-extension#redux-devtools-extension)) 23 | * material UI 1.x beta ([github :link:](https://github.com/callemall/material-ui/tree/v1-beta)) 24 | * axios ([github :link:](https://github.com/mzabriskie/axios) _Why: simple, complete, isomorphic ..._) 25 | 26 | **Tool chain:** 27 | 28 | * Next js (4.x+ [github :link:](https://github.com/zeit/next.js)) 29 | * Flow JS types 30 | 31 | **fav icon** 32 | 33 | * favicons generated by [realfavicongenerator](https://realfavicongenerator.net/) 34 | 35 | ## Usage 36 | 37 | **IMPORTANT: `Next JS` when `redux` connected** 38 | 39 | * **you are forced to connect each page** (_even if you don't need redux in that page_) with `withRedux` from `next-redux-wrapper` (_[see page1 as an example](https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter/blob/master/pages/page1.js)_). 40 | * **each sub component you may want to connect** should be connected by usual `connect` from `redux` (_[see Header component as an example](https://github.com/MacKentoch/react-redux-nextjs-bootstrap-starter/blob/master/components/header/Header.js)_) 41 | 42 | ### Install 43 | 44 | ```bash 45 | npm install 46 | ``` 47 | 48 | ### Scripts 49 | 50 | #### run dev with hot reload 51 | 52 | Clone this repository, then install dependencies: 53 | 54 | ```bash 55 | npm run start 56 | ``` 57 | 58 | #### build dev bundle 59 | 60 | ```bash 61 | npm run build 62 | ``` 63 | 64 | #### start dev (no hot reload) 65 | 66 | _NOTE: ensure you built first before starting_ 67 | 68 | ```bash 69 | npm run start 70 | ``` 71 | 72 | ## LICENSE 73 | 74 | The MIT License (MIT) 75 | 76 | Copyright (c) 2018 Erwan DATIN 77 | 78 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 79 | 80 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 81 | 82 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 83 | -------------------------------------------------------------------------------- /components/layout/Layout.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React, { PureComponent } from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import { connect } from 'react-redux'; 7 | import Link from 'next/link'; 8 | import { withStyles } from 'material-ui/styles'; 9 | import Drawer from 'material-ui/Drawer'; 10 | import AppBar from 'material-ui/AppBar'; 11 | import Toolbar from 'material-ui/Toolbar'; 12 | import Typography from 'material-ui/Typography'; 13 | import IconButton from 'material-ui/IconButton'; 14 | import Hidden from 'material-ui/Hidden'; 15 | import Divider from 'material-ui/Divider'; 16 | import Menu, { MenuItem } from 'material-ui/Menu'; 17 | import AccountCircle from 'material-ui-icons/AccountCircle'; 18 | import MenuIcon from 'material-ui-icons/Menu'; 19 | import compose from 'recompose/compose'; 20 | import Menus from './Menus'; 21 | import styles from './styles'; 22 | import * as userAuthActions from '../../redux/modules/userAuth'; 23 | // #endregion 24 | 25 | // #region flow types 26 | type Props = { 27 | children: ReactNode, 28 | 29 | // userAuth: 30 | isAuthenticated: boolean, 31 | isFetching: boolean, 32 | isLogging: boolean, 33 | disconnectUser: () => string, 34 | 35 | // withStyle injected 36 | classes: any, 37 | theme: any, 38 | }; 39 | 40 | type State = { 41 | mobileOpen: boolean, 42 | anchorEl: any, 43 | }; 44 | // #endregion 45 | 46 | class Layout extends PureComponent { 47 | // #region state initialization 48 | state = { 49 | mobileOpen: false, 50 | anchorEl: null, 51 | }; 52 | // #endregion 53 | 54 | // #region component lifecycle methods 55 | render() { 56 | const { 57 | // withStyle HOC: 58 | classes, 59 | theme, 60 | // children: 61 | children, 62 | // userAuth 63 | isAuthenticated, 64 | disconnectUser, 65 | } = this.props; 66 | 67 | const { anchorEl } = this.state; 68 | 69 | const drawer = ( 70 |
71 |
72 | 73 | 74 | 75 |
76 | ); 77 | 78 | const open = Boolean(anchorEl); 79 | 80 | return ( 81 |
82 |
83 | 84 | 85 | {/* burger menu */} 86 | 92 | 93 | 94 | 95 | {/* title */} 96 | 97 | PWA Next Material UI 98 | 99 | 100 | {/* a filler */} 101 |
102 | 103 | {/* right actions */} 104 | {isAuthenticated ? ( 105 |
106 | 112 | 113 | 114 | 128 | 129 | Profile 130 | 131 | 132 | My account 133 | 134 | Disconnect 135 | 136 |
137 | ) : ( 138 |
139 | 140 | 146 | 147 | 148 | 149 |
150 | )} 151 | 152 | 153 | {/* sidemenu small screen: */} 154 | 155 | 167 | {drawer} 168 | 169 | 170 | {/* sidemenu medium to large screen: */} 171 | 172 | 179 | {drawer} 180 | 181 | 182 |
{children}
183 |
184 |
185 | ); 186 | } 187 | // #endregion 188 | 189 | // #region drawer management 190 | handleDrawerToggle = () => 191 | this.setState(({ mobileOpen: prevMobileOpen }: State) => ({ 192 | mobileOpen: !prevMobileOpen, 193 | })); 194 | // #endregion 195 | 196 | // #region appBar action menu 197 | handleMenu = (event: SyntheticEvent<>) => { 198 | this.setState({ anchorEl: event.currentTarget }); 199 | }; 200 | 201 | handleRequestClose = () => { 202 | this.setState({ anchorEl: null }); 203 | }; 204 | // #endregion 205 | } 206 | 207 | // #region redux state and dispatch map to props 208 | const mapStateToProps = (state: any) => ({ 209 | // userAuth: 210 | isAuthenticated: state.userAuth.isAuthenticated, 211 | isFetching: state.userAuth.isFetching, 212 | isLogging: state.userAuth.isLogging, 213 | }); 214 | 215 | const mapDispatchToProps = (dispatch: (...any) => any) => { 216 | return { 217 | ...bindActionCreators( 218 | { 219 | // userAuth: 220 | ...userAuthActions, 221 | }, 222 | dispatch, 223 | ), 224 | }; 225 | }; 226 | // #endregion 227 | 228 | export default compose( 229 | connect(mapStateToProps, mapDispatchToProps), 230 | withStyles(styles, { withTheme: true }), 231 | )(Layout); 232 | -------------------------------------------------------------------------------- /components/layout/Menus.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React, { PureComponent } from 'react'; 5 | // import Router from 'next/router'; 6 | import Link from 'next/link'; 7 | import { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'; 8 | import InfoIcon from 'material-ui-icons/Info'; 9 | import HomeIcon from 'material-ui-icons/Home'; 10 | import LockIcon from 'material-ui-icons/Lock'; 11 | // #endregion 12 | 13 | // #region flow types 14 | type Props = { 15 | ...any, 16 | }; 17 | // #endregion 18 | 19 | class Menus extends PureComponent { 20 | render() { 21 | return ( 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | ); 51 | } 52 | } 53 | 54 | export default Menus; 55 | -------------------------------------------------------------------------------- /components/layout/styles.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const drawerWidth = 240; 4 | 5 | const styles = theme => ({ 6 | root: { 7 | width: '100%', 8 | height: '100%', 9 | zIndex: 1, 10 | overflow: 'hidden', 11 | }, 12 | appFrame: { 13 | position: 'relative', 14 | display: 'flex', 15 | width: '100%', 16 | height: '100%', 17 | }, 18 | appBar: { 19 | position: 'absolute', 20 | marginLeft: drawerWidth, 21 | [theme.breakpoints.up('md')]: { 22 | width: 'calc(100%)' 23 | }, 24 | }, 25 | navIconHide: { 26 | [theme.breakpoints.up('md')]: { 27 | display: 'none', 28 | }, 29 | }, 30 | drawerHeader: theme.mixins.toolbar, 31 | drawerPaper: { 32 | zIndex: 1, 33 | width: 250, 34 | [theme.breakpoints.up('md')]: { 35 | width: drawerWidth, 36 | position: 'relative', 37 | height: '100vh', // IMPORTANT use 100vh and not 100% which would not work 38 | }, 39 | }, 40 | content: { 41 | backgroundColor: theme.palette.background.default, 42 | width: '100%', 43 | padding: theme.spacing.unit * 3, 44 | height: 'calc(100% - 56px)', 45 | marginTop: 56, 46 | [theme.breakpoints.up('sm')]: { 47 | height: 'calc(100% - 64px)', 48 | marginTop: 64, 49 | }, 50 | }, 51 | flexible: { 52 | flex: 1 53 | } 54 | }); 55 | 56 | // const styles = theme => ({ 57 | // root: { 58 | // width: '100%', 59 | // height: 430, 60 | // marginTop: theme.spacing.unit * 3, 61 | // zIndex: 1, 62 | // overflow: 'hidden', 63 | // }, 64 | // appFrame: { 65 | // position: 'relative', 66 | // display: 'flex', 67 | // width: '100%', 68 | // height: '100%', 69 | // }, 70 | // appBar: { 71 | // position: 'absolute', 72 | // marginLeft: drawerWidth, 73 | // [theme.breakpoints.up('md')]: { 74 | // width: `calc(100% - ${drawerWidth}px)`, 75 | // }, 76 | // }, 77 | // navIconHide: { 78 | // [theme.breakpoints.up('md')]: { 79 | // display: 'none', 80 | // }, 81 | // }, 82 | // drawerHeader: theme.mixins.toolbar, 83 | // drawerPaper: { 84 | // width: 250, 85 | // [theme.breakpoints.up('md')]: { 86 | // width: drawerWidth, 87 | // position: 'relative', 88 | // height: '100%', 89 | // }, 90 | // }, 91 | // content: { 92 | // backgroundColor: theme.palette.background.default, 93 | // width: '100%', 94 | // padding: theme.spacing.unit * 3, 95 | // height: 'calc(100% - 56px)', 96 | // marginTop: 56, 97 | // [theme.breakpoints.up('sm')]: { 98 | // height: 'calc(100% - 64px)', 99 | // marginTop: 64, 100 | // }, 101 | // }, 102 | // }); 103 | 104 | export default styles; 105 | -------------------------------------------------------------------------------- /components/privateRoute/PrivateRoute.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import { PureComponent } from 'react'; 5 | import Router from 'next/router'; 6 | import auth from '../../services/auth'; 7 | // #endregion 8 | 9 | // #region flow types 10 | type Props = { 11 | fromPath: string, 12 | children: ReactNode, 13 | }; 14 | 15 | type State = any; 16 | // #endregion 17 | 18 | class Private extends PureComponent { 19 | // #region 20 | static defaultProps = { 21 | fromPath: '/', 22 | }; 23 | 24 | // #region component lifecycle methods 25 | componentDidMount() { 26 | const { fromPath } = this.props; 27 | 28 | const userIsAuthenticated = this.isAuthenticated(); 29 | const userTokenExpired = this.isExpired(); 30 | 31 | const RoutePayload = { 32 | pathname: '/login', 33 | query: { from: fromPath }, 34 | }; 35 | 36 | if (!userIsAuthenticated) { 37 | return Router.replace(RoutePayload); 38 | } 39 | 40 | if (userTokenExpired) { 41 | return Router.replace(RoutePayload); 42 | } 43 | 44 | return true; 45 | } 46 | 47 | render() { 48 | const { children } = this.props; 49 | 50 | return
{children}
; 51 | } 52 | // #endregion 53 | 54 | // #region authentication check methods 55 | isAuthenticated(): boolean { 56 | const checkUserHasId = user => user && user.id; 57 | const user = auth.getUserInfo() ? auth.getUserInfo() : null; 58 | const isAuthenticated = 59 | auth.getToken() && checkUserHasId(user) ? true : false; 60 | return isAuthenticated; 61 | } 62 | 63 | isExpired(): boolean { 64 | /* eslint-disable no-console */ 65 | // comment me: 66 | console.log( 67 | 'token expires: ', 68 | auth.getTokenExpirationDate(auth.getToken()), 69 | ); 70 | /* eslint-enable no-console */ 71 | return auth.isExpiredToken(auth.getToken()); 72 | } 73 | // #endregion 74 | } 75 | 76 | export default Private; 77 | -------------------------------------------------------------------------------- /config/appConfig.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const AppConfig = { 4 | // flag: set fetch mock or real fetch 5 | DEV_MODE: true, 6 | 7 | // API 8 | api: { 9 | fakeEndPoint: 'api/somewhere', 10 | }, 11 | 12 | // navigation 13 | navigation: { 14 | sidemenu: [ 15 | { 16 | id: 'home', 17 | label: 'Home', 18 | link: '/', 19 | icon: require('material-ui-icons/Home'), 20 | }, 21 | { 22 | id: 'protected', 23 | label: 'Protected', 24 | link: '/protected', 25 | icon: require('material-ui-icons/Lock'), 26 | }, 27 | { 28 | id: 'about', 29 | label: 'About', 30 | link: '/about', 31 | icon: require('material-ui-icons/Info'), 32 | }, 33 | ], 34 | }, 35 | }; 36 | 37 | export default AppConfig; 38 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-plugin-transform-async-to-generator_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: b566883b98bb79a75cbf392f24988c4f 2 | // flow-typed version: <>/babel-plugin-transform-async-to-generator_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-plugin-transform-async-to-generator' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-plugin-transform-async-to-generator' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-plugin-transform-async-to-generator/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-plugin-transform-async-to-generator/lib/index.js' { 31 | declare module.exports: $Exports<'babel-plugin-transform-async-to-generator/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 104fda36b08cda34bbac121973e64b1d 2 | // flow-typed version: <>/babel-plugin-transform-regenerator_v^6.26.0/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-plugin-transform-regenerator' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-plugin-transform-regenerator' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-plugin-transform-regenerator/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-plugin-transform-regenerator/lib/index.js' { 31 | declare module.exports: $Exports<'babel-plugin-transform-regenerator/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-es2015_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 8722dd2bea14809f8f45293872c8f6cf 2 | // flow-typed version: <>/babel-preset-es2015_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-es2015' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-es2015' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-es2015/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-es2015/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-es2015/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-flow_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2f58597102bce11ff3a4482d6607d60f 2 | // flow-typed version: <>/babel-preset-flow_v^6.23.0/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-flow' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-flow' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-flow/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-flow/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-flow/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 1421db38882c7eb42bf18e8dbb388727 2 | // flow-typed version: <>/babel-preset-react_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-react' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-react' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-react/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-react/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-react/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-preset-stage-2_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a801d20d6e50d29432634751cde9135d 2 | // flow-typed version: <>/babel-preset-stage-2_v^6.24.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-preset-stage-2' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-preset-stage-2' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-preset-stage-2/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'babel-preset-stage-2/lib/index.js' { 31 | declare module.exports: $Exports<'babel-preset-stage-2/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 54255bb1299438546b6f355a212368bb 2 | // flow-typed version: <>/eslint-plugin-flowtype_v^2.39.1/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-plugin-flowtype' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'eslint-plugin-flowtype' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'eslint-plugin-flowtype/bin/readmeAssertions' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-plugin-flowtype/dist/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'eslint-plugin-flowtype/dist/rules/noMutableArray' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'eslint-plugin-flowtype/dist/rules/noUnusedExpressions' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'eslint-plugin-flowtype/dist/rules/requireVariableType' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'eslint-plugin-flowtype/dist/rules/semi' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'eslint-plugin-flowtype/dist/rules/sortKeys' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'eslint-plugin-flowtype/dist/rules/useFlowType' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'eslint-plugin-flowtype/dist/rules/validSyntax' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'eslint-plugin-flowtype/dist/utilities/index' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'eslint-plugin-flowtype/dist/utilities/quoteName' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers' { 202 | declare module.exports: any; 203 | } 204 | 205 | // Filename aliases 206 | declare module 'eslint-plugin-flowtype/bin/readmeAssertions.js' { 207 | declare module.exports: $Exports<'eslint-plugin-flowtype/bin/readmeAssertions'>; 208 | } 209 | declare module 'eslint-plugin-flowtype/dist/index.js' { 210 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/index'>; 211 | } 212 | declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle.js' { 213 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/booleanStyle'>; 214 | } 215 | declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType.js' { 216 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/defineFlowType'>; 217 | } 218 | declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle.js' { 219 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/delimiterDangle'>; 220 | } 221 | declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing.js' { 222 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/genericSpacing'>; 223 | } 224 | declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys.js' { 225 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noDupeKeys'>; 226 | } 227 | declare module 'eslint-plugin-flowtype/dist/rules/noMutableArray.js' { 228 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noMutableArray'>; 229 | } 230 | declare module 'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes.js' { 231 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes'>; 232 | } 233 | declare module 'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation.js' { 234 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation'>; 235 | } 236 | declare module 'eslint-plugin-flowtype/dist/rules/noUnusedExpressions.js' { 237 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noUnusedExpressions'>; 238 | } 239 | declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes.js' { 240 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noWeakTypes'>; 241 | } 242 | declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter.js' { 243 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter'>; 244 | } 245 | declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType.js' { 246 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireParameterType'>; 247 | } 248 | declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType.js' { 249 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireReturnType'>; 250 | } 251 | declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation.js' { 252 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation'>; 253 | } 254 | declare module 'eslint-plugin-flowtype/dist/rules/requireVariableType.js' { 255 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireVariableType'>; 256 | } 257 | declare module 'eslint-plugin-flowtype/dist/rules/semi.js' { 258 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/semi'>; 259 | } 260 | declare module 'eslint-plugin-flowtype/dist/rules/sortKeys.js' { 261 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/sortKeys'>; 262 | } 263 | declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon.js' { 264 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon'>; 265 | } 266 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket.js' { 267 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket'>; 268 | } 269 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon.js' { 270 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon'>; 271 | } 272 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions.js' { 273 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions'>; 274 | } 275 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer.js' { 276 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer'>; 277 | } 278 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty.js' { 279 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty'>; 280 | } 281 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType.js' { 282 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType'>; 283 | } 284 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression.js' { 285 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression'>; 286 | } 287 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical.js' { 288 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical'>; 289 | } 290 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index.js' { 291 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index'>; 292 | } 293 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter.js' { 294 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter'>; 295 | } 296 | declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch.js' { 297 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeIdMatch'>; 298 | } 299 | declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing.js' { 300 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing'>; 301 | } 302 | declare module 'eslint-plugin-flowtype/dist/rules/useFlowType.js' { 303 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/useFlowType'>; 304 | } 305 | declare module 'eslint-plugin-flowtype/dist/rules/validSyntax.js' { 306 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/validSyntax'>; 307 | } 308 | declare module 'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation.js' { 309 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation'>; 310 | } 311 | declare module 'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch.js' { 312 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch'>; 313 | } 314 | declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName.js' { 315 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getParameterName'>; 316 | } 317 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens.js' { 318 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens'>; 319 | } 320 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens.js' { 321 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens'>; 322 | } 323 | declare module 'eslint-plugin-flowtype/dist/utilities/index.js' { 324 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/index'>; 325 | } 326 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile.js' { 327 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFile'>; 328 | } 329 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation.js' { 330 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation'>; 331 | } 332 | declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes.js' { 333 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes'>; 334 | } 335 | declare module 'eslint-plugin-flowtype/dist/utilities/quoteName.js' { 336 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/quoteName'>; 337 | } 338 | declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers.js' { 339 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/spacingFixers'>; 340 | } 341 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-bin_v0.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 2 | // flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x 3 | 4 | declare module "flow-bin" { 5 | declare module.exports: string; 6 | } 7 | -------------------------------------------------------------------------------- /flow-typed/npm/next_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a090d89ea52a4af4a03acae98696426a 2 | // flow-typed version: <>/next_v^4.0.3/flow_v0.57.2 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'next' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'next' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'next/babel' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'next/css' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'next/dist/client/head-manager' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'next/dist/client/index' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'next/dist/client/next-dev' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'next/dist/client/next' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'next/dist/client/on-demand-entries-client' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'next/dist/client/webpack-hot-middleware-client' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'next/dist/lib/app' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'next/dist/lib/css' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'next/dist/lib/dynamic' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'next/dist/lib/error-debug' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'next/dist/lib/error' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'next/dist/lib/EventEmitter' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'next/dist/lib/head' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'next/dist/lib/link' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'next/dist/lib/p-queue' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'next/dist/lib/page-loader' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'next/dist/lib/prefetch' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'next/dist/lib/router/index' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'next/dist/lib/router/router' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'next/dist/lib/router/with-router' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'next/dist/lib/shallow-equals' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'next/dist/lib/side-effect' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'next/dist/lib/utils' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'next/dist/pages/_document' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'next/dist/pages/_error' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'next/dist/server/build/babel/find-config' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'next/dist/server/build/babel/plugins/handle-import' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'next/dist/server/build/babel/preset' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'next/dist/server/build/clean' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'next/dist/server/build/index' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'next/dist/server/build/loaders/emit-file-loader' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'next/dist/server/build/loaders/hot-self-accept-loader' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'next/dist/server/build/plugins/combine-assets-plugin' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'next/dist/server/build/plugins/dynamic-chunks-plugin' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'next/dist/server/build/plugins/pages-plugin' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'next/dist/server/build/plugins/unlink-file-plugin' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'next/dist/server/build/plugins/watch-pages-plugin' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'next/dist/server/build/replace' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'next/dist/server/build/root-module-relative-path' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'next/dist/server/build/webpack' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'next/dist/server/config' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'next/dist/server/document' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'next/dist/server/export' { 202 | declare module.exports: any; 203 | } 204 | 205 | declare module 'next/dist/server/hot-reloader' { 206 | declare module.exports: any; 207 | } 208 | 209 | declare module 'next/dist/server/index' { 210 | declare module.exports: any; 211 | } 212 | 213 | declare module 'next/dist/server/next' { 214 | declare module.exports: any; 215 | } 216 | 217 | declare module 'next/dist/server/on-demand-entry-handler' { 218 | declare module.exports: any; 219 | } 220 | 221 | declare module 'next/dist/server/render' { 222 | declare module.exports: any; 223 | } 224 | 225 | declare module 'next/dist/server/require' { 226 | declare module.exports: any; 227 | } 228 | 229 | declare module 'next/dist/server/resolve' { 230 | declare module.exports: any; 231 | } 232 | 233 | declare module 'next/dist/server/router' { 234 | declare module.exports: any; 235 | } 236 | 237 | declare module 'next/dist/server/utils' { 238 | declare module.exports: any; 239 | } 240 | 241 | declare module 'next/document' { 242 | declare module.exports: any; 243 | } 244 | 245 | declare module 'next/dynamic' { 246 | declare module.exports: any; 247 | } 248 | 249 | declare module 'next/error' { 250 | declare module.exports: any; 251 | } 252 | 253 | declare module 'next/head' { 254 | declare module.exports: any; 255 | } 256 | 257 | declare module 'next/link' { 258 | declare module.exports: any; 259 | } 260 | 261 | declare module 'next/prefetch' { 262 | declare module.exports: any; 263 | } 264 | 265 | declare module 'next/router' { 266 | declare module.exports: any; 267 | } 268 | 269 | // Filename aliases 270 | declare module 'next/babel.js' { 271 | declare module.exports: $Exports<'next/babel'>; 272 | } 273 | declare module 'next/css.js' { 274 | declare module.exports: $Exports<'next/css'>; 275 | } 276 | declare module 'next/dist/client/head-manager.js' { 277 | declare module.exports: $Exports<'next/dist/client/head-manager'>; 278 | } 279 | declare module 'next/dist/client/index.js' { 280 | declare module.exports: $Exports<'next/dist/client/index'>; 281 | } 282 | declare module 'next/dist/client/next-dev.js' { 283 | declare module.exports: $Exports<'next/dist/client/next-dev'>; 284 | } 285 | declare module 'next/dist/client/next.js' { 286 | declare module.exports: $Exports<'next/dist/client/next'>; 287 | } 288 | declare module 'next/dist/client/on-demand-entries-client.js' { 289 | declare module.exports: $Exports<'next/dist/client/on-demand-entries-client'>; 290 | } 291 | declare module 'next/dist/client/webpack-hot-middleware-client.js' { 292 | declare module.exports: $Exports<'next/dist/client/webpack-hot-middleware-client'>; 293 | } 294 | declare module 'next/dist/lib/app.js' { 295 | declare module.exports: $Exports<'next/dist/lib/app'>; 296 | } 297 | declare module 'next/dist/lib/css.js' { 298 | declare module.exports: $Exports<'next/dist/lib/css'>; 299 | } 300 | declare module 'next/dist/lib/dynamic.js' { 301 | declare module.exports: $Exports<'next/dist/lib/dynamic'>; 302 | } 303 | declare module 'next/dist/lib/error-debug.js' { 304 | declare module.exports: $Exports<'next/dist/lib/error-debug'>; 305 | } 306 | declare module 'next/dist/lib/error.js' { 307 | declare module.exports: $Exports<'next/dist/lib/error'>; 308 | } 309 | declare module 'next/dist/lib/EventEmitter.js' { 310 | declare module.exports: $Exports<'next/dist/lib/EventEmitter'>; 311 | } 312 | declare module 'next/dist/lib/head.js' { 313 | declare module.exports: $Exports<'next/dist/lib/head'>; 314 | } 315 | declare module 'next/dist/lib/link.js' { 316 | declare module.exports: $Exports<'next/dist/lib/link'>; 317 | } 318 | declare module 'next/dist/lib/p-queue.js' { 319 | declare module.exports: $Exports<'next/dist/lib/p-queue'>; 320 | } 321 | declare module 'next/dist/lib/page-loader.js' { 322 | declare module.exports: $Exports<'next/dist/lib/page-loader'>; 323 | } 324 | declare module 'next/dist/lib/prefetch.js' { 325 | declare module.exports: $Exports<'next/dist/lib/prefetch'>; 326 | } 327 | declare module 'next/dist/lib/router/index.js' { 328 | declare module.exports: $Exports<'next/dist/lib/router/index'>; 329 | } 330 | declare module 'next/dist/lib/router/router.js' { 331 | declare module.exports: $Exports<'next/dist/lib/router/router'>; 332 | } 333 | declare module 'next/dist/lib/router/with-router.js' { 334 | declare module.exports: $Exports<'next/dist/lib/router/with-router'>; 335 | } 336 | declare module 'next/dist/lib/shallow-equals.js' { 337 | declare module.exports: $Exports<'next/dist/lib/shallow-equals'>; 338 | } 339 | declare module 'next/dist/lib/side-effect.js' { 340 | declare module.exports: $Exports<'next/dist/lib/side-effect'>; 341 | } 342 | declare module 'next/dist/lib/utils.js' { 343 | declare module.exports: $Exports<'next/dist/lib/utils'>; 344 | } 345 | declare module 'next/dist/pages/_document.js' { 346 | declare module.exports: $Exports<'next/dist/pages/_document'>; 347 | } 348 | declare module 'next/dist/pages/_error.js' { 349 | declare module.exports: $Exports<'next/dist/pages/_error'>; 350 | } 351 | declare module 'next/dist/server/build/babel/find-config.js' { 352 | declare module.exports: $Exports<'next/dist/server/build/babel/find-config'>; 353 | } 354 | declare module 'next/dist/server/build/babel/plugins/handle-import.js' { 355 | declare module.exports: $Exports<'next/dist/server/build/babel/plugins/handle-import'>; 356 | } 357 | declare module 'next/dist/server/build/babel/preset.js' { 358 | declare module.exports: $Exports<'next/dist/server/build/babel/preset'>; 359 | } 360 | declare module 'next/dist/server/build/clean.js' { 361 | declare module.exports: $Exports<'next/dist/server/build/clean'>; 362 | } 363 | declare module 'next/dist/server/build/index.js' { 364 | declare module.exports: $Exports<'next/dist/server/build/index'>; 365 | } 366 | declare module 'next/dist/server/build/loaders/emit-file-loader.js' { 367 | declare module.exports: $Exports<'next/dist/server/build/loaders/emit-file-loader'>; 368 | } 369 | declare module 'next/dist/server/build/loaders/hot-self-accept-loader.js' { 370 | declare module.exports: $Exports<'next/dist/server/build/loaders/hot-self-accept-loader'>; 371 | } 372 | declare module 'next/dist/server/build/plugins/combine-assets-plugin.js' { 373 | declare module.exports: $Exports<'next/dist/server/build/plugins/combine-assets-plugin'>; 374 | } 375 | declare module 'next/dist/server/build/plugins/dynamic-chunks-plugin.js' { 376 | declare module.exports: $Exports<'next/dist/server/build/plugins/dynamic-chunks-plugin'>; 377 | } 378 | declare module 'next/dist/server/build/plugins/pages-plugin.js' { 379 | declare module.exports: $Exports<'next/dist/server/build/plugins/pages-plugin'>; 380 | } 381 | declare module 'next/dist/server/build/plugins/unlink-file-plugin.js' { 382 | declare module.exports: $Exports<'next/dist/server/build/plugins/unlink-file-plugin'>; 383 | } 384 | declare module 'next/dist/server/build/plugins/watch-pages-plugin.js' { 385 | declare module.exports: $Exports<'next/dist/server/build/plugins/watch-pages-plugin'>; 386 | } 387 | declare module 'next/dist/server/build/replace.js' { 388 | declare module.exports: $Exports<'next/dist/server/build/replace'>; 389 | } 390 | declare module 'next/dist/server/build/root-module-relative-path.js' { 391 | declare module.exports: $Exports<'next/dist/server/build/root-module-relative-path'>; 392 | } 393 | declare module 'next/dist/server/build/webpack.js' { 394 | declare module.exports: $Exports<'next/dist/server/build/webpack'>; 395 | } 396 | declare module 'next/dist/server/config.js' { 397 | declare module.exports: $Exports<'next/dist/server/config'>; 398 | } 399 | declare module 'next/dist/server/document.js' { 400 | declare module.exports: $Exports<'next/dist/server/document'>; 401 | } 402 | declare module 'next/dist/server/export.js' { 403 | declare module.exports: $Exports<'next/dist/server/export'>; 404 | } 405 | declare module 'next/dist/server/hot-reloader.js' { 406 | declare module.exports: $Exports<'next/dist/server/hot-reloader'>; 407 | } 408 | declare module 'next/dist/server/index.js' { 409 | declare module.exports: $Exports<'next/dist/server/index'>; 410 | } 411 | declare module 'next/dist/server/next.js' { 412 | declare module.exports: $Exports<'next/dist/server/next'>; 413 | } 414 | declare module 'next/dist/server/on-demand-entry-handler.js' { 415 | declare module.exports: $Exports<'next/dist/server/on-demand-entry-handler'>; 416 | } 417 | declare module 'next/dist/server/render.js' { 418 | declare module.exports: $Exports<'next/dist/server/render'>; 419 | } 420 | declare module 'next/dist/server/require.js' { 421 | declare module.exports: $Exports<'next/dist/server/require'>; 422 | } 423 | declare module 'next/dist/server/resolve.js' { 424 | declare module.exports: $Exports<'next/dist/server/resolve'>; 425 | } 426 | declare module 'next/dist/server/router.js' { 427 | declare module.exports: $Exports<'next/dist/server/router'>; 428 | } 429 | declare module 'next/dist/server/utils.js' { 430 | declare module.exports: $Exports<'next/dist/server/utils'>; 431 | } 432 | declare module 'next/document.js' { 433 | declare module.exports: $Exports<'next/document'>; 434 | } 435 | declare module 'next/dynamic.js' { 436 | declare module.exports: $Exports<'next/dynamic'>; 437 | } 438 | declare module 'next/error.js' { 439 | declare module.exports: $Exports<'next/error'>; 440 | } 441 | declare module 'next/head.js' { 442 | declare module.exports: $Exports<'next/head'>; 443 | } 444 | declare module 'next/link.js' { 445 | declare module.exports: $Exports<'next/link'>; 446 | } 447 | declare module 'next/prefetch.js' { 448 | declare module.exports: $Exports<'next/prefetch'>; 449 | } 450 | declare module 'next/router.js' { 451 | declare module.exports: $Exports<'next/router'>; 452 | } 453 | -------------------------------------------------------------------------------- /mock/fakeAPI.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "label": "item 1" 5 | }, 6 | { 7 | "id": 2, 8 | "label": "item 2" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /mock/userInfosMock.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJkZW1vIiwiaWF0IjoxNTAyMzA3MzU0LCJleHAiOjE3MjMyMzIxNTQsImF1ZCI6ImRlbW8tZGVtbyIsInN1YiI6ImRlbW8iLCJHaXZlbk5hbWUiOiJKb2huIiwiU3VybmFtZSI6IkRvZSIsIkVtYWlsIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJSb2xlIjpbIlN1cGVyIGNvb2wgZGV2IiwibWFnaWMgbWFrZXIiXX0.6FjgLCypaqmRp4tDjg_idVKIzQw16e-z_rjA3R94IqQ", 3 | "user": { 4 | "id": 111, 5 | "login": "john.doe@fake.mail", 6 | "firstname": "John", 7 | "lastname": "Doe", 8 | "isAdmin": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin'); 2 | 3 | module.exports = { 4 | webpack: (config) => { 5 | config.plugins.push( 6 | new SWPrecacheWebpackPlugin({ 7 | verbose: true, 8 | staticFileGlobsIgnorePatterns: [/\.next\//], 9 | staticFileGlobs: [ 10 | 'https://fonts.googleapis.com/css?family=Roboto:300,400,500', 11 | 'src/static/img/**.*', 12 | 'src/static/**/*.png', 13 | 'src/static/**/*.xml', 14 | 'src/static/**/*.json', 15 | 'src/static/**/*.txt', 16 | 'src/static/**/*.svg', 17 | 'src/static/css/**/*.css' 18 | ], 19 | runtimeCaching: [ 20 | { 21 | handler: 'networkFirst', 22 | urlPattern: /^https?.*/ 23 | } 24 | ] 25 | }) 26 | ); 27 | return config; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /offline/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // no more used, now using "sw-precache-webpack-plugin" (for production only) 2 | 3 | // service workers rocks: https://developers.google.com/web/fundamentals/primers/service-workers/ 4 | const CACHE_NAME = 'rrnm-cache-v1'; 5 | const urlsToCache = [ 6 | '/', 7 | 'https://fonts.googleapis.com/css?family=Roboto:300,400,500', 8 | ]; 9 | const cacheWhitelist = [CACHE_NAME]; // by default current CACHE_NAME will persist on acivation (non whitelisted one will be deleted) 10 | 11 | self.addEventListener('install', event => { 12 | const addAllToCache = cache => cache.addAll(urlsToCache); 13 | const preLoaded = caches.open(CACHE_NAME).then(addAllToCache); 14 | event.waitUntil(preLoaded); 15 | }); 16 | 17 | self.addEventListener('fetch', event => { 18 | const cacheNonMatchedThenReturnFetchReponse = eventRequest => 19 | fetch(eventRequest).then(fetchResponse => 20 | caches.open(CACHE_NAME).then(cache => { 21 | cache.put(eventRequest, fetchResponse.clone()); 22 | return fetchResponse; 23 | }), 24 | ); 25 | 26 | const response = caches 27 | .match(event.request) 28 | .then( 29 | match => match || cacheNonMatchedThenReturnFetchReponse(event.request), 30 | ); 31 | event.respondWith(response); 32 | }); 33 | 34 | self.addEventListener('activate', event => { 35 | const cachesCleaned = caches.keys().then(cacheNames => { 36 | return Promise.all( 37 | cacheNames.map(cacheName => { 38 | if (cacheWhitelist.indexOf(cacheName) === -1) { 39 | return caches.delete(cacheName); 40 | } 41 | return Promise.resolve(); 42 | }), 43 | ); 44 | }); 45 | 46 | event.waitUntil(cachesCleaned); 47 | }); 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-redux-nextjs-material-ui-pwa-starter", 3 | "version": "0.0.1", 4 | "description": "a progressive web app starter with next js redux + redux-persist + material ui", 5 | "author": "Erwan DATIN (http://www.erwan-datin.com)", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/MacKentoch/react-redux-nextjs-material-ui-pwa-starter" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/MacKentoch/react-redux-nextjs-material-ui-pwa-starter/issues" 13 | }, 14 | "keywords": [ 15 | "react", 16 | "next", 17 | "pwa", 18 | "progressive", 19 | "progressive web app", 20 | "web", 21 | "app", 22 | "zeit", 23 | "next.js", 24 | "next js", 25 | "now", 26 | "redux", 27 | "react-redux", 28 | "ES6", 29 | "ES7", 30 | "ES8", 31 | "ES2015", 32 | "ES2016", 33 | "ES2017", 34 | "material", 35 | "material-ui", 36 | "starter", 37 | "persist", 38 | "redux-persist", 39 | "hot-reload" 40 | ], 41 | "engines": { 42 | "node": ">=8.1.4", 43 | "npm": ">=5.4.2" 44 | }, 45 | "main": "index.js", 46 | "scripts": { 47 | "dev": "cross-env NODE_ENV=development node server", 48 | "build": "next build", 49 | "start": "cross-env NODE_ENV=production node server", 50 | "deploy": "now --public" 51 | }, 52 | "dependencies": { 53 | "axios": "^0.16.2", 54 | "chalk": "^2.2.0", 55 | "deepmerge": "^2.0.1", 56 | "es6-promise-debounce": "^1.0.1", 57 | "express": "^4.16.2", 58 | "jss": "^9.2.0", 59 | "jss-preset-default": "^4.0.1", 60 | "jss-vendor-prefixer": "^7.0.0", 61 | "jwt-decode": "^2.2.0", 62 | "localforage": "^1.5.2", 63 | "material-ui": "next", 64 | "material-ui-icons": "^1.0.0-beta.17", 65 | "moment": "^2.19.1", 66 | "next": "latest", 67 | "next-redux-wrapper": "^1.3.4", 68 | "normalize.css": "^7.0.0", 69 | "react": "^16.0.0", 70 | "react-dom": "^16.0.0", 71 | "react-jss": "^7.2.0", 72 | "react-overdrive": "^0.0.9", 73 | "react-redux": "^5.0.6", 74 | "recompose": "^0.26.0", 75 | "redux": "^3.7.2", 76 | "redux-persist": "^4.10.1", 77 | "redux-thunk": "^2.2.0", 78 | "smoothscroll-polyfill": "^0.4.3", 79 | "styled-components": "^3.2.6", 80 | "sw-precache-webpack-plugin": "^0.11.4" 81 | }, 82 | "devDependencies": { 83 | "@types/axios": "^0.14.0", 84 | "@types/chalk": "^0.4.31", 85 | "@types/express": "^4.0.37", 86 | "@types/jss": "^0.6.28", 87 | "@types/jwt-decode": "^2.2.1", 88 | "@types/localforage": "0.0.34", 89 | "@types/material-ui": "^0.18.4", 90 | "@types/moment": "^2.13.0", 91 | "@types/next": "^2.4.3", 92 | "@types/next-redux-wrapper": "^1.3.3", 93 | "@types/react": "^16.0.10", 94 | "@types/react-dom": "^16.0.1", 95 | "@types/react-redux": "^5.0.10", 96 | "@types/recompose": "^0.24.2", 97 | "@types/redux": "^3.6.0", 98 | "@types/redux-persist": "^4.3.1", 99 | "@types/redux-thunk": "^2.1.0", 100 | "babel-eslint": "^8.0.1", 101 | "babel-plugin-transform-async-to-generator": "^6.24.1", 102 | "babel-plugin-transform-regenerator": "^6.26.0", 103 | "babel-preset-es2015": "^6.24.1", 104 | "babel-preset-flow": "^6.23.0", 105 | "babel-preset-react": "^6.24.1", 106 | "babel-preset-stage-2": "^6.24.1", 107 | "cross-env": "^5.1.0", 108 | "eslint": "^4.8.0", 109 | "eslint-plugin-flowtype": "^2.39.1", 110 | "eslint-plugin-react": "^7.4.0", 111 | "flow-bin": "^0.59.0", 112 | "nodemon": "^1.12.1", 113 | "redux-devtools-extension": "^2.13.2", 114 | "redux-logger": "^3.0.6", 115 | "rimraf": "^2.6.2" 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React from 'react'; 5 | import Document, { Head, Main, NextScript } from 'next/document'; 6 | import JssProvider from 'react-jss/lib/JssProvider'; 7 | import getContext from '../styles/getContext'; 8 | import registerServiceWorker from '../services/registerServiceWorker'; 9 | // #endregion 10 | 11 | // #region global vars or polyfill 12 | 13 | if (process.browser) { 14 | // eslint-disable-next-line global-require 15 | require('smoothscroll-polyfill').polyfill(); 16 | // force polyfill 17 | window.__forceSmoothScrollPolyfill__ = true; 18 | } 19 | // #endregion 20 | 21 | // #region flow types 22 | type Props = { 23 | ...any, 24 | }; 25 | 26 | type State = any; 27 | 28 | type InitialProps = { 29 | req: any, 30 | res: any, 31 | pathname: string, 32 | query: any, 33 | asPath: string, 34 | isServer: boolean, 35 | store?: any, 36 | ...any, 37 | }; 38 | // #endregion 39 | 40 | class RootDocument extends Document { 41 | // #region props initialization 42 | static async getInitialProps(initProps: InitialProps) { 43 | // Resolution order 44 | // 45 | // On the server: 46 | // 1. page.getInitialProps 47 | // 2. document.getInitialProps 48 | // 3. page.render 49 | // 4. document.render 50 | // 51 | // On the server with error: 52 | // 2. document.getInitialProps 53 | // 3. page.render 54 | // 4. document.render 55 | // 56 | // On the client 57 | // 1. page.getInitialProps 58 | // 3. page.render 59 | 60 | // Get the context to collected side effects. 61 | const context = getContext(); 62 | const page = initProps.renderPage(Component => props => ( 63 | 64 | 65 | 66 | )); 67 | 68 | return { 69 | ...page, 70 | stylesContext: context, 71 | styles: ( 72 | 156 | 157 | 158 |
159 | 160 | 161 | 162 | ); 163 | } 164 | // #endregion 165 | } 166 | 167 | export default RootDocument; 168 | -------------------------------------------------------------------------------- /pages/about.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React, { PureComponent } from 'react'; 5 | import { bindActionCreators } from 'redux'; 6 | import withRedux from 'next-redux-wrapper'; 7 | import Router from 'next/router'; 8 | import compose from 'recompose/compose'; 9 | import Button from 'material-ui/Button'; 10 | import Typography from 'material-ui/Typography'; 11 | import { withStyles } from 'material-ui/styles'; 12 | import withRoot from '../HOC/withRoot'; 13 | import Layout from '../components/layout/Layout'; 14 | import configureStore from '../redux/store/configureStore'; 15 | // #endregion 16 | 17 | // #region flow types 18 | type Props = { 19 | classes: any, 20 | ...any, 21 | }; 22 | 23 | type State = { 24 | ...any, 25 | }; 26 | // #endregion 27 | 28 | // #region styles 29 | const styles = theme => ({ 30 | card: { 31 | minWidth: 310, 32 | }, 33 | bullet: { 34 | display: 'inline-block', 35 | margin: '0 2px', 36 | transform: 'scale(0.8)', 37 | }, 38 | title: { 39 | marginBottom: 16, 40 | fontSize: 14, 41 | color: theme.palette.text.secondary, 42 | }, 43 | pos: { 44 | marginBottom: 12, 45 | color: theme.palette.text.secondary, 46 | }, 47 | }); 48 | // #endregion 49 | 50 | class About extends PureComponent { 51 | // #region component lifecycle methods 52 | render() { 53 | return ( 54 | 55 | 56 | About 57 | 58 | 59 | 60 | example project 61 | 62 | 65 | 66 | ); 67 | } 68 | // #endregion 69 | 70 | handleRequestClose = () => { 71 | this.setState({ 72 | open: false, 73 | }); 74 | }; 75 | 76 | handleClick = () => { 77 | Router.push('/'); 78 | }; 79 | } 80 | 81 | // #region redux state and dispatch map to props 82 | const mapStateToProps = state => ({ 83 | // nothing right now 84 | }); 85 | 86 | const mapDispatchToProps = (dispatch: (...any) => any) => { 87 | return { 88 | ...bindActionCreators({}, dispatch), 89 | }; 90 | }; 91 | // #endregion 92 | 93 | export default compose( 94 | withRedux(configureStore, mapStateToProps, mapDispatchToProps), 95 | withRoot, 96 | withStyles(styles), 97 | )(About); 98 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | // #region imports 4 | import React, { PureComponent } from 'react'; 5 | import Router from 'next/router'; 6 | import { bindActionCreators } from 'redux'; 7 | import Button from 'material-ui/Button'; 8 | import Typography from 'material-ui/Typography'; 9 | import { withStyles } from 'material-ui/styles'; 10 | import withRedux from 'next-redux-wrapper'; 11 | import compose from 'recompose/compose'; 12 | import configureStore from '../redux/store/configureStore'; 13 | import withRoot from '../HOC/withRoot'; 14 | import Layout from '../components/layout/Layout'; 15 | // #endregion 16 | 17 | // #region flow types 18 | type Props = { 19 | classes: any, 20 | ...any, 21 | }; 22 | 23 | type State = { 24 | ...any, 25 | }; 26 | // #endregion 27 | 28 | // #region styles 29 | const styles = { 30 | root: { 31 | textAlign: 'center', 32 | paddingTop: 200, 33 | }, 34 | }; 35 | // #endregion 36 | class Index extends PureComponent { 37 | // #region props initialization 38 | // static async getInitialProps({ 39 | // isServer, 40 | // store 41 | // }: InitialProps) { 42 | // const SIDE = isServer ? 'SERVER SIDE' : 'FRONT SIDE'; 43 | 44 | // try { 45 | // const response = await store.dispatch(fakeFetchActions.fakeFetchIfNeeded()); 46 | // const { 47 | // payload: { 48 | // data 49 | // } 50 | // } = response; 51 | // // NOTE: you will see this log in your server console (where you `npm run dev`): 52 | // /* eslint-disable no-console */ 53 | // console.log(`getInitialProps - ${SIDE} - fake fetch result: `, data); 54 | // } catch (error) { 55 | // console.error(`getInitialProps - ${SIDE} - fake fetch failed: `, error); 56 | // /* eslint-enable no-console */ 57 | // } 58 | // } 59 | // #endregion 60 | 61 | // #region component lifecycle methods 62 | render() { 63 | return ( 64 | 65 | 66 | Material-UI 67 | 68 | 69 | 70 | example project 71 | 72 | 73 | 76 | 77 | ); 78 | } 79 | // #endregion 80 | 81 | handleRequestClose = () => { 82 | this.setState({ 83 | open: false, 84 | }); 85 | }; 86 | 87 | handleClick = () => { 88 | Router.push('/login'); 89 | }; 90 | } 91 | 92 | // #region redux state and dispatch map to props 93 | const mapStateToProps = (state: any) => ({}); 94 | 95 | const mapDispatchToProps = (dispatch: (...any) => any) => { 96 | return { 97 | ...bindActionCreators({}, dispatch), 98 | }; 99 | }; 100 | // #endregion 101 | 102 | export default compose( 103 | withRedux(configureStore, mapStateToProps, mapDispatchToProps), 104 | withRoot, 105 | withStyles(styles), 106 | )(Index); 107 | -------------------------------------------------------------------------------- /pages/login.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /* eslint-disable quotes */ 3 | 4 | // #region imports 5 | import { PureComponent } from 'react'; 6 | import { bindActionCreators } from 'redux'; 7 | import withRedux from 'next-redux-wrapper'; 8 | import debounce from 'es6-promise-debounce'; 9 | import Router from 'next/router'; 10 | import compose from 'recompose/compose'; 11 | import Button from 'material-ui/Button'; 12 | import Snackbar from 'material-ui/Snackbar'; 13 | import Slide from 'material-ui/transitions/Slide'; 14 | import Grid from 'material-ui/Grid'; 15 | import Typography from 'material-ui/Typography'; 16 | import { withStyles } from 'material-ui/styles'; 17 | import Input, { InputLabel, InputAdornment } from 'material-ui/Input'; 18 | import { FormControl } from 'material-ui/Form'; 19 | import MailOutline from 'material-ui-icons/MailOutline'; 20 | import LockOutline from 'material-ui-icons/LockOutline'; 21 | import configureStore from '../redux/store/configureStore'; 22 | import * as userAuthActions from '../redux/modules/userAuth'; 23 | import withRoot from '../HOC/withRoot'; 24 | import Layout from '../components/layout/Layout'; 25 | import auth from '../services/auth'; 26 | // #endregion 27 | 28 | // #region flow types 29 | type Props = { 30 | // next/route: 31 | url: { 32 | // query.from sent by Private component when user auth failed 33 | query?: { 34 | from?: string, 35 | }, 36 | }, 37 | 38 | // userAuth: 39 | isAuthenticated: boolean, 40 | isFetching: boolean, 41 | isLogging: boolean, 42 | disconnectUser: () => string, 43 | logUserIfNeeded: (user: string) => any, 44 | 45 | ...any, 46 | }; 47 | 48 | type State = { 49 | email: string, 50 | password: string, 51 | browserStorageSupported: boolean, 52 | showSnackbar: boolean, 53 | }; 54 | // #endregion 55 | 56 | // #region styles 57 | const styles = theme => ({ 58 | content: { 59 | flexGrow: 1, 60 | marginTop: '70px', 61 | paddingTop: '40px', 62 | }, 63 | formControl: { 64 | margin: theme.spacing.unit, 65 | }, 66 | inputIcon: { 67 | marginBottom: 1, 68 | }, 69 | 70 | formButtonContainer: { 71 | marginTop: '10px', 72 | }, 73 | }); 74 | // #endregion 75 | 76 | class Login extends PureComponent { 77 | // #region default PropTypes 78 | static defaultProps = { 79 | isFetching: false, 80 | isLogging: false, 81 | }; 82 | // #endregion 83 | 84 | // #region state initialization 85 | state = { 86 | email: '', 87 | password: '', 88 | browserStorageSupported: true, 89 | showSnackbar: false, 90 | }; 91 | // #endregion 92 | 93 | // #region component lifecycle methods 94 | componentDidMount() { 95 | const { disconnectUser } = this.props; 96 | const browserStorageSupported = 97 | auth.supportsLocalStorage() && auth.supportsSessionStorage(); 98 | 99 | this.setBrowserStorageSupportedState(browserStorageSupported); 100 | 101 | if (browserStorageSupported) { 102 | disconnectUser(); // diconnect user: remove token and user info 103 | } 104 | } 105 | 106 | render() { 107 | const { email, password, browserStorageSupported } = this.state; 108 | 109 | const { isLogging, classes } = this.props; 110 | 111 | return ( 112 | 113 |
114 | 121 | 122 | {browserStorageSupported && ( 123 |
124 | 125 | Login 126 | 127 | 128 | 129 | Email 130 | 138 | 139 | 140 | } 141 | /> 142 | 143 | 144 | 145 | Password 146 | 154 | 155 | 156 | } 157 | /> 158 | 159 | 160 |
161 | 166 |
167 | 183 |
184 |
185 |
186 |
187 | )} 188 | } 193 | SnackbarContentProps={{ 194 | 'aria-describedby': 'login-failed-container', 195 | }} 196 | message={ 197 |
198 |

199 |