├── .editorconfig ├── shared ├── css │ └── var │ │ ├── var.css.d.ts │ │ └── var.css ├── images │ ├── boil.jpg │ ├── boil2.jpg │ ├── cancel.svg │ ├── boy.svg │ ├── girl.svg │ └── boil.svg ├── icon │ └── favicon.png ├── signal │ ├── OneSignalSDKWorker.js │ └── OneSignalSDKUpdaterWorker.js ├── components │ ├── toastrCSS.tsx │ ├── scripter.tsx │ ├── styler.tsx │ └── MUIProvider │ │ └── index.tsx ├── declarations.d.tsx ├── helmet │ └── index.tsx └── theme │ └── index.tsx ├── internal ├── test │ ├── jest.js │ └── jestSetup.js ├── docker │ ├── Dockerfile.dev │ └── Dockerfile ├── kubernetes │ ├── service.yaml │ ├── ingress.yaml │ └── frontend.yaml └── webpack │ ├── extras.js │ ├── css.js │ ├── loaders.js │ └── plugins.js ├── .eslintrc.js ├── app ├── components │ ├── 404 │ │ ├── 404.tsx │ │ ├── __snapshots__ │ │ │ └── 404.test.tsx.snap │ │ └── 404.test.tsx │ ├── home │ │ ├── css │ │ │ ├── home.css.d.ts │ │ │ └── home.css │ │ └── index.tsx │ ├── shell │ │ ├── shell.css.d.ts │ │ ├── shell.css │ │ └── index.tsx │ └── user │ │ ├── css │ │ ├── teste.css.d.ts │ │ └── teste.css │ │ ├── country │ │ ├── country.test.tsx │ │ ├── __snapshots__ │ │ │ └── country.test.tsx.snap │ │ └── country.tsx │ │ ├── item │ │ ├── item.tsx │ │ ├── item.test.tsx │ │ └── __snapshots__ │ │ │ └── item.test.tsx.snap │ │ ├── user.test.tsx │ │ ├── index.tsx │ │ ├── user.tsx │ │ └── __snapshots__ │ │ └── user.test.tsx.snap ├── router.tsx └── route.map.tsx ├── .gitignore ├── webpack.config.js ├── .travis.yml ├── store ├── logger.tsx ├── epics.tsx ├── actions.tsx ├── createStore.tsx └── reducers.tsx ├── tsconfig.json ├── webpack.dll.js ├── tslint.json ├── server ├── flush.tsx ├── renderer.tsx ├── middleware.tsx ├── html.tsx ├── server.js ├── helpers.tsx └── index.html ├── webpack.server.js ├── client ├── client.tsx ├── offline.tsx ├── sw.tsx └── renderer.tsx ├── webpack.client.js ├── hot.js ├── dobi.yaml ├── README.org └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shared/css/var/var.css.d.ts: -------------------------------------------------------------------------------- 1 | export default {}; 2 | -------------------------------------------------------------------------------- /internal/test/jest.js: -------------------------------------------------------------------------------- 1 | module.exports = 'test-file-stub'; 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "cesco" 3 | }; 4 | -------------------------------------------------------------------------------- /app/components/home/css/home.css.d.ts: -------------------------------------------------------------------------------- 1 | export const container: string 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | dll/ 3 | .awcache/ 4 | 5 | node_modules/ 6 | .wercker/ 7 | coverage/ 8 | -------------------------------------------------------------------------------- /shared/images/boil.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cescoferraro/react-boil/HEAD/shared/images/boil.jpg -------------------------------------------------------------------------------- /shared/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cescoferraro/react-boil/HEAD/shared/icon/favicon.png -------------------------------------------------------------------------------- /shared/images/boil2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cescoferraro/react-boil/HEAD/shared/images/boil2.jpg -------------------------------------------------------------------------------- /shared/css/var/var.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --mainColor: red; 3 | --contentHeight: calc( 100vh -64px ); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = env => [ 2 | require('./webpack.client.js')(env), 3 | require('./webpack.server.js')(env) 4 | ]; 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | before_script: 5 | - npm run prod 6 | script: 7 | - npm run lint 8 | - npm run test 9 | -------------------------------------------------------------------------------- /internal/docker/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM node:6 2 | RUN npm i -g typescript 3 | RUN npm i -g tslint 4 | RUN npm i -g webpack 5 | 6 | # GOPATH 7 | WORKDIR /srv/boil 8 | -------------------------------------------------------------------------------- /shared/signal/OneSignalSDKWorker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://boil.cescoferraro.xyz/service-worker.js'); 2 | importScripts('https://cdn.onesignal.com/sdks/OneSignalSDK.js'); 3 | -------------------------------------------------------------------------------- /shared/signal/OneSignalSDKUpdaterWorker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://boil.cescoferraro.xyz/service-worker.js'); 2 | importScripts('https://cdn.onesignal.com/sdks/OneSignalSDK.js'); 3 | -------------------------------------------------------------------------------- /app/components/shell/shell.css.d.ts: -------------------------------------------------------------------------------- 1 | export const base: string 2 | export const container: string 3 | export const button: string 4 | export const flex: string 5 | export const main: string 6 | export const svg: string 7 | -------------------------------------------------------------------------------- /internal/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mhart/alpine-node:latest 2 | WORKDIR /srv/acharh 3 | RUN npm i express@5.0.0-alpha.5 4 | RUN npm i compression 5 | RUN npm i morgan 6 | ADD dist/ /srv/acharh/ 7 | CMD ["node","server.js"] 8 | -------------------------------------------------------------------------------- /app/components/404/404.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | export const NoMatchContainer = (props) => { 4 | return ( 5 |
6 |

NOT FOUND!

7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /app/components/home/css/home.css: -------------------------------------------------------------------------------- 1 | .container { 2 | overflow:auto; 3 | margin-left:10px; 4 | margin-right:10px; 5 | } 6 | 7 | table { 8 | border-collapse: separate; 9 | border-spacing: 20px 20px; 10 | } 11 | -------------------------------------------------------------------------------- /internal/test/jestSetup.js: -------------------------------------------------------------------------------- 1 | const enzyme = require('enzyme'); 2 | global.shallow = enzyme.shallow; 3 | global.render = enzyme.render; 4 | global.mount = enzyme.mount; 5 | // Fail tests on any warning 6 | console.error = message => { 7 | throw new Error(message); 8 | }; 9 | -------------------------------------------------------------------------------- /shared/components/toastrCSS.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Styler } from "./styler" 3 | const rules = require("-!raw-loader!react-redux-toastr/lib/css/react-redux-toastr.min.css") 4 | export const ToastrCSS = () => 5 | -------------------------------------------------------------------------------- /internal/kubernetes/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | namespace: boil 6 | name: boil-svc 7 | spec: 8 | selector: 9 | name: boil-pods 10 | ports: 11 | - name: web 12 | port: 5000 13 | targetPort: 5000 14 | protocol: TCP 15 | -------------------------------------------------------------------------------- /app/components/home/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as CSS from "./css/home.css" 3 | const test = require("../../../README.org") 4 | 5 | export const HomeComponent = ({ }) => { 6 | return
7 | } 8 | -------------------------------------------------------------------------------- /shared/components/scripter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | export const Scripter = ({ rules, async, id }) => { 3 | return ( 4 | '; 44 | if (htmlPluginData.html.indexOf('') !== -1) { 45 | htmlPluginData.html = htmlPluginData.html.replace( 46 | '', 47 | filesToInclude + '' 48 | ); 49 | } else { 50 | htmlPluginData.html = htmlPluginData.html.replace( 51 | '', 52 | '' + filesToInclude + '' 53 | ); 54 | } 55 | cb(null, htmlPluginData); 56 | } 57 | ); 58 | }); 59 | } 60 | } 61 | 62 | module.exports = PreloadPlugin; 63 | -------------------------------------------------------------------------------- /app/components/user/item/__snapshots__/item.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Render an Item 1`] = ` 4 | 5 | 6 | 15 | } 16 | title="Email" 17 | value="teste@example.com" 18 | > 19 |
22 |
25 | 32 | 42 | 59 | 62 | 63 | 64 | 65 |
66 | 84 |
85 |
86 |
87 |
88 | `; 89 | -------------------------------------------------------------------------------- /internal/webpack/loaders.js: -------------------------------------------------------------------------------- 1 | const ExtractCssChunks = require('extract-css-chunks-webpack-plugin'); 2 | 3 | const SVG = { 4 | exclude: /node_modules/, 5 | loader: 'svg-react-loader', 6 | test: /\.svg$/ 7 | }; 8 | 9 | const postCSS = { 10 | loader: 'postcss-loader', 11 | options: { 12 | plugins: loader => [ 13 | require('postcss-import')({ root: loader.resourcePath }), 14 | require('postcss-cssnext')({ 15 | browsers: '> 0%', 16 | colorFunction: true, 17 | customProperties: true, 18 | customSelectors: true 19 | }) 20 | ] 21 | } 22 | }; 23 | 24 | const images = (client = false) => { 25 | return { 26 | test: /\.(gif|png|jpe?g)$/i, 27 | loaders: [ 28 | { 29 | loader: 'file-loader', 30 | query: { 31 | emitFile: client, 32 | name: 'images/img-[sha512:hash:base64:7].[ext]' 33 | } 34 | }, 35 | { 36 | loader: 'image-webpack-loader', 37 | query: { 38 | mozjpeg: { 39 | progressive: true 40 | }, 41 | gifsicle: { 42 | interlaced: false 43 | }, 44 | optipng: { 45 | optimizationLevel: 4 46 | }, 47 | pngquant: { 48 | quality: '75-90', 49 | speed: 3 50 | } 51 | } 52 | } 53 | ] 54 | }; 55 | }; 56 | 57 | const typeScript = () => ({ 58 | exclude: /node_modules/, 59 | use: [ 60 | { 61 | loader: 'awesome-typescript-loader', 62 | options: { 63 | sourceMap: true, 64 | useBabel: false, 65 | useCache: true 66 | } 67 | } 68 | ], 69 | test: /\.tsx?$/ 70 | }); 71 | 72 | const cssHelper = client => { 73 | return { 74 | loader: client ? 'css-loader' : 'css-loader/locals', 75 | options: { 76 | localIdentName: '[name]__[local]--[hash:base64:5]', 77 | modules: true 78 | } 79 | }; 80 | }; 81 | 82 | const css = (client = false) => { 83 | const local = [cssHelper(client), postCSS]; 84 | return { 85 | test: /\.css$/, 86 | use: client ? ExtractCssChunks.extract({ use: local }) : local 87 | }; 88 | }; 89 | 90 | const org = () => { 91 | return { 92 | test: /\.org/, 93 | loader: 'org-loader' 94 | }; 95 | }; 96 | 97 | const serverLoaders = env => ({ 98 | rules: [images(), SVG, typeScript(), css(), org()] 99 | }); 100 | 101 | const clientLoaders = env => ({ 102 | rules: [images(true), SVG, typeScript(), css(true), org()] 103 | }); 104 | 105 | module.exports = { 106 | clientLoaders: clientLoaders, 107 | serverLoaders: serverLoaders 108 | }; 109 | -------------------------------------------------------------------------------- /shared/images/girl.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 11 | 15 | 16 | 18 | 20 | 21 | 23 | 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 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/components/shell/index.tsx: -------------------------------------------------------------------------------- 1 | import Subheader from "material-ui/Subheader" 2 | import * as cs from "classnames" 3 | import * as React from "react" 4 | import AppBar from "material-ui/AppBar" 5 | import * as CSS from "./shell.css" 6 | import Drawer from "material-ui/Drawer" 7 | import MenuItem from "material-ui/MenuItem" 8 | const BoilLogo = require("../../../shared/images/boil.svg") 9 | const Cancel = require("../../../shared/images/cancel.svg") 10 | const Boy = require("../../../shared/images/boy.svg") 11 | const Girl = require("../../../shared/images/girl.svg") 12 | import ReduxToastr from "react-redux-toastr" 13 | 14 | export const Shell = (props) => { 15 | const closeOnClick = (open) => { props.DRAWER_ACTION(open) } 16 | const boilLogo = ( 17 | 21 | ) 22 | const goBack = () => { 23 | props.GO_HOME_ACTION() 24 | props.DRAWER_ACTION(false) 25 | } 26 | const goUser = (id) => () => { 27 | props.USER_ACTION(id) 28 | props.DRAWER_ACTION(false) 29 | } 30 | return ( 31 |
32 | 38 |
39 | {props.children} 40 |
41 | 50 | 55 |
56 | 60 |
61 | React-boil 62 | } 64 | onClick={goUser(432)} 65 | > 66 | User 123 67 | 68 | } 70 | onClick={goUser(324)} 71 | > 72 | User 456 73 | 74 | } 77 | onClick={props.DRAWER_TOGGLE_ACTION} 78 | > 79 | Close 80 | 81 |
82 |
83 | ) 84 | } 85 | -------------------------------------------------------------------------------- /app/components/user/user.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as CSS from "./css/teste.css" 3 | import { Card } from "material-ui/Card" 4 | import Subheader from "material-ui/Subheader" 5 | import { ProfileClass } from "../../../store/reducers" 6 | import Code from "material-ui/svg-icons/action/code" 7 | import Terrain from "material-ui/svg-icons/maps/terrain" 8 | import LocationCity from "material-ui/svg-icons/social/location-city" 9 | import AccountCircle from "material-ui/svg-icons/action/account-circle" 10 | import GpsFixed from "material-ui/svg-icons/device/gps-fixed" 11 | import Divider from "material-ui/Divider" 12 | import { Item } from "./item/item" 13 | import { compose } from "recompose" 14 | import sizeMe from "react-sizeme" 15 | import Country from "./country/country" 16 | 17 | export class UserComponent extends React.Component { 18 | public render() { 19 | const profile: ProfileClass = new ProfileClass(this.props.profiles[this.props.profile.id]) 20 | const grey = { fill: "grey" } 21 | return ( 22 |
23 | 24 |
25 | 300 ? profile.picture.large : profile.picture.medium} 29 | width={150} 30 | /> 31 | 34 |
35 | } 39 | /> 40 | } 44 | /> 45 | Address 46 | } 50 | /> 51 | } 55 | /> 56 | } 60 | /> 61 | } 65 | /> 66 | 67 | 68 |
69 |
70 | ) 71 | } 72 | } 73 | 74 | export default compose(sizeMe())(UserComponent) 75 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: React-boil 2 | #+OPTIONS: toc:nil 3 | 4 | Cutting edge PWA ready React.js Boilerplate. This is created as a 5 | template for my cookie cutter called [[http://github.com/cescoferraro/react-boiler][react-boiler]]. The goal here is 6 | to enable developers, a.k.a. me, deliver tomorrow's web today. 7 | 8 | | 👀 | [[https://github.com/facebook/react][react]] as the view | 9 | | 🔥 | [[http://redux.js.org/docs/introduction/][Redux]] store ready! All the cool tooling and extensions. | 10 | | 🔀 | [[https://github.com/faceyspacey/redux-first-router][redux-first-router]] as the router. | 11 | | 🚄 | [[https://expressjs.com/][express]] server. | 12 | | 🎛 | Offilne first. Try going offline for a bit. | 13 | | 🔥 | [[https://onesignal.com][OneSignal]] gives us web push Notifications to keep in touch with our customers | 14 | | 🖌 | [[https://github.com/michaelcontento/redux-storage][ReduxStorage]] makes the app remember where the user was last time with ALL THE DATA! Native app experience | 15 | | 🔥 | [[https://firebase.google.com/][Firebase]] totally integrated Redux store ready! Google Infrastructure ready to ship! | 16 | | 🚀 | [[https://github.com/redux-observable/redux-observable][Redux-Observable]] to perform asynchronous redux actions. | 17 | | 🌍 | [[https://facebook.github.io/react/docs/react-dom-server.html][Server Side Rendering]] because its 2017. | 18 | | 💩 | [[https://github.com/facespacey/webpack-flush-chunks][webpack-flush-chunks]] framework less code splitting & SSR FULL CONTROL | 19 | | 🖌 | [[https://github.com/postcss/postcss][PostCSS]] lets you use next css syntax now. | 20 | | 👼 | [[https://github.com/kriasoft/isomorphic-style-loader][Extract-Css-Chunks]] injects only css critical path to the website. | 21 | | 📦 | All source is bundled using [[https://webpack.js.org/configuration/][Webpack v3]]. | 22 | | 🔥 | Extreme live development using [[https://webpack.js.org/configuration/][webpack]] standard tooling like [[https://github.com/60frames/webpack-hot-server-middleware][webpack-hot-server-middleware]] & [[https://github.com/glenjamin/webpack-hot-middleware][webpack-hot-middleware]]. | 23 | | 🍃 | Tree-shaking, courtesy of Webpack. | 24 | | 🎛 | Pre-configured to support development and optimized production builds. | 25 | | 🤖 | [[https://github.com/webpack/docs/wiki/list-of-plugins#dllplugin][Vendor DLL]] for smooth development experiences. | 26 | | 💩 | Code splitting Thanks to [[https://www.npmjs.com/package/react-universal-component][react-universal-component]] | 27 | | 😎 | Progressive Web Application ready, with offline support, via a Service Worker. | 28 | | 🕸 | Is this reality? Believe at the web https://boil.cescoferraro.xyz | 29 | | 🎭 | `jest` as the test framework. Snapshot for life! 30 | 31 | 32 | 33 | 34 | # LocalWords: Pre redux PWA js SSR css LocalWords 35 | -------------------------------------------------------------------------------- /server/helpers.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Helmet } from "react-helmet" 3 | 4 | const CachedFs = require("cachedfs") 5 | const fs = new CachedFs() 6 | 7 | const path = require("path") 8 | 9 | declare module "react" { 10 | /* tslint:disable */ 11 | interface HTMLAttributes extends React.DOMAttributes { 12 | /* tslint:enable */ 13 | as?: string 14 | } 15 | } 16 | 17 | export const BaseStyle = () => ( 18 | 21 | ) 22 | 23 | export const OneSignalCDN = ({ production }) => { 24 | return ( 25 | production ? 26 | ( 15 | React-boil 16 | 23 | 24 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | --------------------------------------------------------------------------------