├── .gitattributes ├── .gitignore ├── .yo-rc.json ├── app ├── USAGE ├── templates │ ├── _bower.json │ ├── src │ │ ├── assets │ │ │ ├── robots.txt │ │ │ ├── tile.png │ │ │ ├── favicon.ico │ │ │ ├── tile-wide.png │ │ │ ├── apple-touch-icon-precomposed.png │ │ │ ├── humans.txt │ │ │ ├── browserconfig.xml │ │ │ └── crossdomain.xml │ │ ├── images │ │ │ ├── logo-small.png │ │ │ └── logo-small@2x.png │ │ ├── constants │ │ │ ├── PayloadSources.js │ │ │ └── ActionTypes.js │ │ ├── styles │ │ │ ├── mixins.less │ │ │ ├── jumbotron.less │ │ │ ├── utilities.less │ │ │ ├── .csslintrc │ │ │ ├── variables.less │ │ │ ├── navbar.less │ │ │ ├── bootstrap.less │ │ │ └── .csscomb.json │ │ ├── actions │ │ │ └── RouteActions.js │ │ ├── components │ │ │ ├── __tests__ │ │ │ │ └── Navbar-test.js │ │ │ ├── Navbar.jsx │ │ │ └── Link.jsx │ │ ├── AppDispatcher.js │ │ ├── pages │ │ │ ├── _template.html │ │ │ ├── 404.html │ │ │ ├── Index.jsx │ │ │ └── Privacy.jsx │ │ ├── layouts │ │ │ └── DefaultLayout.jsx │ │ └── app.js │ ├── _.gitignore │ ├── editorconfig │ ├── config │ │ ├── preprocessor.js │ │ └── webpack.js │ ├── jshintrc │ ├── LICENSE.txt │ ├── _package.json │ ├── README.md │ └── gulpfile.js └── index.js ├── .editorconfig ├── .travis.yml ├── .jshintrc ├── test └── test-app.js ├── package.json └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea 3 | .DS_STORE 4 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-generator": {} 3 | } -------------------------------------------------------------------------------- /app/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Creates an Flux/Reactjs WebApp. 3 | 4 | Example: 5 | yo flux-webapp 6 | -------------------------------------------------------------------------------- /app/templates/_bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "package", 3 | "version": "0.0.0", 4 | "dependencies": {} 5 | } 6 | 7 | -------------------------------------------------------------------------------- /app/templates/src/assets/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /app/templates/src/assets/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alduro/generator-flux-webapp/HEAD/app/templates/src/assets/tile.png -------------------------------------------------------------------------------- /app/templates/src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alduro/generator-flux-webapp/HEAD/app/templates/src/assets/favicon.ico -------------------------------------------------------------------------------- /app/templates/src/assets/tile-wide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alduro/generator-flux-webapp/HEAD/app/templates/src/assets/tile-wide.png -------------------------------------------------------------------------------- /app/templates/src/images/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alduro/generator-flux-webapp/HEAD/app/templates/src/images/logo-small.png -------------------------------------------------------------------------------- /app/templates/src/constants/PayloadSources.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | VIEW_ACTION: 'VIEW_ACTION', 3 | SERVER_ACTION: 'SERVER_ACTION' 4 | }; 5 | -------------------------------------------------------------------------------- /app/templates/src/images/logo-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alduro/generator-flux-webapp/HEAD/app/templates/src/images/logo-small@2x.png -------------------------------------------------------------------------------- /app/templates/src/constants/ActionTypes.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | // Route action types 4 | SET_CURRENT_ROUTE: 'SET_CURRENT_ROUTE' 5 | 6 | }; 7 | -------------------------------------------------------------------------------- /app/templates/src/assets/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alduro/generator-flux-webapp/HEAD/app/templates/src/assets/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /app/templates/_.gitignore: -------------------------------------------------------------------------------- 1 | # Git uses this file to determine which files and directories to ignore 2 | # https://help.github.com/articles/ignoring-files 3 | 4 | build 5 | bower_components 6 | node_modules 7 | npm-debug.log 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_install: 5 | - currentfolder=${PWD##*/} 6 | - if [ "$currentfolder" != 'generator-flux-webapp' ]; then cd .. && eval "mv $currentfolder generator-flux-webapp" && cd generator-flux-webapp; fi 7 | 8 | -------------------------------------------------------------------------------- /app/templates/editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /app/templates/src/styles/mixins.less: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Mixins 3 | // ============================================================================= 4 | 5 | @import "../../node_modules/bootstrap/less/mixins.less"; 6 | -------------------------------------------------------------------------------- /app/templates/src/assets/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3, JavaScript 15 | React, Director, Bootstrap 16 | -------------------------------------------------------------------------------- /app/templates/config/preprocessor.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ReactTools = require('react-tools'); 4 | 5 | module.exports = { 6 | process: function(src, path) { 7 | return ReactTools.transform( 8 | path.match(/\.jsx$/) ? '/**@jsx React.DOM*/' + src : src, 9 | {harmony: true}); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /app/templates/src/styles/jumbotron.less: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Jumbotron 3 | // ============================================================================= 4 | 5 | @import "../../node_modules/bootstrap/less/jumbotron.less"; 6 | 7 | .jumbotron { 8 | p { 9 | text-transform: uppercase; 10 | letter-spacing: 1px; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /app/templates/jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /app/templates/src/assets/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/templates/src/styles/utilities.less: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Utility classes 3 | // ============================================================================= 4 | 5 | @import "../../node_modules/bootstrap/less/utilities.less"; 6 | 7 | // 8 | // Browse Happy prompt 9 | // ----------------------------------------------------------------------------- 10 | 11 | .browsehappy { 12 | margin: 0.2em 0; 13 | background: #ccc; 14 | color: #000; 15 | padding: 0.2em 0; 16 | } 17 | -------------------------------------------------------------------------------- /app/templates/src/actions/RouteActions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var AppDispatcher = require('../AppDispatcher'); 4 | var ActionTypes = require('../constants/ActionTypes'); 5 | 6 | var AppActions = { 7 | 8 | /** 9 | * Set the current route. 10 | * @param {string} route Supply a route value, such as `todos/completed`. 11 | */ 12 | setRoute(route) { 13 | AppDispatcher.handleViewAction({ 14 | actionType: ActionTypes.SET_CURRENT_ROUTE, 15 | route 16 | }); 17 | } 18 | 19 | }; 20 | 21 | module.exports = AppActions; 22 | -------------------------------------------------------------------------------- /app/templates/src/styles/.csslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "adjoining-classes": false, 3 | "box-sizing": false, 4 | "box-model": false, 5 | "compatible-vendor-prefixes": false, 6 | "floats": false, 7 | "font-sizes": false, 8 | "gradients": false, 9 | "important": false, 10 | "known-properties": false, 11 | "outline-none": false, 12 | "qualified-headings": false, 13 | "regex-selectors": false, 14 | "shorthand": false, 15 | "text-indent": false, 16 | "unique-headings": false, 17 | "universal-selector": false, 18 | "unqualified-attributes": false 19 | } 20 | -------------------------------------------------------------------------------- /app/templates/src/components/__tests__/Navbar-test.js: -------------------------------------------------------------------------------- 1 | /* global jest, describe, it, expect */ 2 | 3 | 'use strict'; 4 | 5 | jest.dontMock('../Navbar.jsx'); 6 | 7 | describe('Navbar', function() { 8 | it('sets class name', function() { 9 | var React = require('react/addons'); 10 | var TestUtils = React.addons.TestUtils; 11 | 12 | var Navbar = require('../Navbar.jsx'); 13 | var Component = TestUtils.renderIntoDocument(new Navbar()); 14 | 15 | var element = TestUtils.findRenderedDOMComponentWithClass(Component, 'navbar-top'); 16 | expect(element).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /app/templates/src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jsx React.DOM 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var React = require('react'); 8 | var Link = require('./Link.jsx'); 9 | 10 | var Navbar = React.createClass({ 11 | render() { 12 | return ( 13 |
14 |
15 | 16 | 17 | React 18 | React.js Starter Kit 19 | 20 | 21 |
22 |
23 | ); 24 | } 25 | }); 26 | 27 | module.exports = Navbar; 28 | -------------------------------------------------------------------------------- /app/templates/src/assets/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/templates/src/components/Link.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jsx React.DOM 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var React = require('react'); 8 | var RouteActions = require('../actions/RouteActions'); 9 | 10 | var Link = React.createClass({ 11 | propTypes: { 12 | to: React.PropTypes.string.isRequired 13 | }, 14 | render() { 15 | this.props.href = 16 | this.props.to && this.props.to.lastIndexOf('/', 0) === 0 ? 17 | this.props.to : '/' + this.props.to; 18 | 19 | return this.transferPropsTo( 20 | {this.props.children} 21 | ); 22 | }, 23 | handleClick(e) { 24 | e.preventDefault(); 25 | RouteActions.setRoute(this.props.to); 26 | } 27 | }); 28 | 29 | module.exports = Link; 30 | -------------------------------------------------------------------------------- /test/test-app.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | var assert = require('yeoman-generator').assert; 6 | var helpers = require('yeoman-generator').test; 7 | var os = require('os'); 8 | 9 | describe('flux-webapp:app', function () { 10 | before(function (done) { 11 | helpers.run(path.join(__dirname, '../app')) 12 | .inDir(path.join(os.tmpdir(), './temp-test')) 13 | .withOptions({ 'skip-install': true }) 14 | .withPrompt({ 15 | someOption: true 16 | }) 17 | .on('end', done); 18 | }); 19 | 20 | it('creates files', function () { 21 | assert.file([ 22 | 'bower.json', 23 | 'package.json', 24 | '.editorconfig', 25 | '.jshintrc' 26 | ]); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /app/templates/src/styles/variables.less: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Variables 3 | // ============================================================================= 4 | 5 | @import "../../node_modules/bootstrap/less/variables.less"; 6 | 7 | // 8 | // Scaffolding 9 | // ----------------------------------------------------------------------------- 10 | 11 | // Background color for `` 12 | @body-bg: #f9f9f9; 13 | // Global text color on `` 14 | @text-color: #484848; 15 | // Global textual link color 16 | @link-color: #c05b4d; 17 | 18 | // 19 | // Jumbotron 20 | // ----------------------------------------------------------------------------- 21 | 22 | @jumbotron-heading-color: #61DAFB; 23 | @jumbotron-color: #E9E9E9; 24 | @jumbotron-bg: #2d2d2d; 25 | @jumbotron-font-size: @font-size-base; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-flux-webapp", 3 | "version": "0.1.3", 4 | "description": "Yeoman generator for creating Flux applications.", 5 | "license": "MIT", 6 | "main": "app/index.js", 7 | "repository": "alduro/generator-flux-webapp", 8 | "author": { 9 | "name": "Aldo Nievas", 10 | "email": "aldo@satio.com.ar", 11 | "url": "https://github.com/alduro" 12 | }, 13 | "engines": { 14 | "node": ">=0.10.0" 15 | }, 16 | "scripts": { 17 | "test": "mocha" 18 | }, 19 | "files": [ 20 | "app" 21 | ], 22 | "keywords": [ 23 | "yeoman-generator" 24 | ], 25 | "dependencies": { 26 | "yeoman-generator": "^0.17.0", 27 | "chalk": "^1.0.0", 28 | "yosay": "^0.3.0" 29 | }, 30 | "devDependencies": { 31 | "mocha": "*" 32 | }, 33 | "peerDependencies": { 34 | "yo": ">=1.0.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/templates/src/AppDispatcher.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A singleton that operates as the central hub for application updates. 3 | * For more information visit https://facebook.github.io/flux/ 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var {Dispatcher} = require('flux'); 9 | var PayloadSources = require('./constants/PayloadSources'); 10 | var copyProperties = require('react/lib/copyProperties'); 11 | 12 | var AppDispatcher = copyProperties(new Dispatcher(), { 13 | 14 | /** 15 | * @param {object} action The details of the action, including the action's 16 | * type and additional data coming from the server. 17 | */ 18 | handleServerAction() { 19 | var payload = { 20 | source: PayloadSources.SERVER_ACTION, 21 | action 22 | }; 23 | this.dispatch(payload); 24 | }, 25 | 26 | /** 27 | * @param {object} action The details of the action, including the action's 28 | * type and additional data coming from the view. 29 | */ 30 | handleViewAction(action) { 31 | var payload = { 32 | source: PayloadSources.VIEW_ACTION, 33 | action 34 | }; 35 | this.dispatch(payload); 36 | } 37 | 38 | }); 39 | 40 | module.exports = AppDispatcher; 41 | -------------------------------------------------------------------------------- /app/templates/src/styles/navbar.less: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Navigation Bar 3 | // ============================================================================= 4 | 5 | @import "../../node_modules/bootstrap/less/navbar.less"; 6 | 7 | body { 8 | padding: @navbar-height 0; 9 | overflow-y: scroll; 10 | } 11 | 12 | .navbar-top { 13 | &:extend(.navbar); 14 | &:extend(.navbar-inverse); 15 | &:extend(.navbar-fixed-top); 16 | } 17 | 18 | .navbar-brand { 19 | padding-top: 8px; 20 | padding-bottom: 8px; 21 | color: #00d8ff !important; 22 | font-size: 24px; 23 | 24 | img { 25 | margin-right: 10px; 26 | } 27 | } 28 | 29 | // 30 | // Navigation Footer 31 | // ----------------------------------------------------------------------------- 32 | 33 | .navbar-footer { 34 | &:extend(.navbar); 35 | &:extend(.navbar-fixed-bottom); 36 | 37 | background-color: darken(@body-bg, 2%); 38 | 39 | .text-muted { 40 | margin-top: 1em; 41 | 42 | span + span:before { 43 | content: "\2022\00a0"; // Unicode space added since inline-block means non-collapsing white-space 44 | padding: 0 3px 0 7px; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/templates/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014 Konstantin Tarkus (@koistya), KriaSoft LLC. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /app/templates/src/pages/_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= title %> 7 | 8 | 9 | 10 | 11 | 12 | 15 |
16 | 17 | 18 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/templates/src/pages/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found 6 | 7 | 53 | 54 | 55 |

Page Not Found

56 |

Sorry, but the page you were trying to view does not exist.

57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/templates/src/layouts/DefaultLayout.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jsx React.DOM 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var React = require('react'); 8 | var Link = require('../components/Link.jsx'); 9 | var Navbar = require('../components/Navbar.jsx'); 10 | 11 | var DefaultLayout = React.createClass({ 12 | propTypes: { 13 | title: React.PropTypes.string, 14 | breadcrumb: React.PropTypes.component 15 | }, 16 | getDefaultProps() { 17 | return { 18 | title: 'React.js Starter Kit', 19 | description: 'A skeleton for an isomorphic web application (SPA) built with React.js and Flux' 20 | }; 21 | }, 22 | render() { 23 | var header = this.props.breadcrumb ? ( 24 |
25 |

{this.props.title}

26 | {this.props.breadcrumb} 27 |
28 | ) : ( 29 |
30 |
31 |

React

32 |

Complex web apps made easy

33 |
34 |
35 | ); 36 | 37 | return ( 38 |
39 | 40 | {header} 41 | {this.props.children} 42 |
43 |
44 |

45 | © KriaSoft 46 | Home 47 | Privacy 48 |

49 |
50 |
51 |
52 | ); 53 | } 54 | }); 55 | 56 | module.exports = DefaultLayout; 57 | -------------------------------------------------------------------------------- /app/templates/src/app.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Facebook React Starter Kit | https://github.com/kriasoft/react-starter-kit 3 | * Copyright (c) KriaSoft, LLC. All rights reserved. See LICENSE.txt 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var React = require('react'); 9 | var copyProperties = require('react/lib/copyProperties'); 10 | var {Router} = require('director'); 11 | var AppDispatcher = require('./AppDispatcher'); 12 | var ActionTypes = require('./constants/ActionTypes'); 13 | 14 | // Export React so the dev tools can find it 15 | (window !== window.top ? window.top : window).React = React; 16 | 17 | /** 18 | * Check if Page component has a layout property; and if yes, wrap the page 19 | * into the specified layout, then mount to document.body. 20 | */ 21 | function render(page) { 22 | var child, props = {}; 23 | while (page.defaultProps.layout) { 24 | child = page(props, child); 25 | copyProperties(props, page.defaultProps); 26 | page = page.defaultProps.layout; 27 | } 28 | React.renderComponent(page(props, child), document.body); 29 | document.title = props.title; 30 | } 31 | 32 | // Define URL routes 33 | // See https://github.com/flatiron/director 34 | var routes = { 35 | '/': () => render(require('./pages/Index.jsx')), 36 | '/privacy': () => render(require('./pages/Privacy.jsx')) 37 | }; 38 | 39 | // Initialize a router 40 | var router = new Router(routes).configure({html5history: true}).init(); 41 | 42 | AppDispatcher.register((payload) => { 43 | 44 | var action = payload.action; 45 | 46 | if (action.actionType === ActionTypes.SET_CURRENT_ROUTE) { 47 | router.setRoute(action.route); 48 | } 49 | 50 | return true; // No errors. Needed by promise in Dispatcher. 51 | }); 52 | -------------------------------------------------------------------------------- /app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= _.slugify(_.humanize(appname)) %>", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "bootstrap": "^3.2.0", 6 | "director": "^1.2.3", 7 | "flux": "^2.0.1", 8 | "react": "^0.11.2" 9 | }, 10 | "devDependencies": { 11 | "browser-sync": "^1.5.8", 12 | "del": "^0.1.3", 13 | "gulp": "^3.8.8", 14 | "gulp-autoprefixer": "^1.0.1", 15 | "gulp-cache": "^0.2.4", 16 | "gulp-changed": "^1.0.0", 17 | "gulp-csscomb": "^3.0.3", 18 | "gulp-gh-pages": "^0.4.0", 19 | "gulp-htmlmin": "^0.2.0", 20 | "gulp-if": "^1.2.5", 21 | "gulp-imagemin": "^1.1.0", 22 | "gulp-jsbeautifier": "^0.0.3", 23 | "gulp-jshint": "^1.8.5", 24 | "gulp-less": "^1.3.6", 25 | "gulp-load-plugins": "^0.7.0", 26 | "gulp-minify-css": "^0.3.11", 27 | "gulp-plumber": "^0.6.6", 28 | "gulp-render": "^0.0.4", 29 | "gulp-replace": "^0.4.0", 30 | "gulp-size": "^1.1.0", 31 | "gulp-uglify": "^1.0.1", 32 | "gulp-util": "^3.0.1", 33 | "jest-cli": "^0.1.18", 34 | "jshint": "^2.5.6", 35 | "jshint-loader": "^0.8.0", 36 | "jshint-stylish": "^1.0.0", 37 | "jsx-loader": "^0.11.2", 38 | "merge-stream": "^0.1.6", 39 | "minimist": "^1.1.0", 40 | "protractor": "^1.3.1", 41 | "psi": "^0.1.4", 42 | "react-tools": "^0.11.2", 43 | "run-sequence": "^1.0.1", 44 | "url-loader": "^0.5.5", 45 | "webpack": "^1.4.8", 46 | "webpack-dev-server": "^1.6.5" 47 | }, 48 | "jest": { 49 | "rootDir": "src", 50 | "scriptPreprocessor": "../config/preprocessor.js", 51 | "unmockedModulePathPatterns": [ 52 | "react" 53 | ] 54 | }, 55 | "scripts": { 56 | "start": "gulp", 57 | "test": "jest", 58 | "preupdate-webdriver": "npm install", 59 | "update-webdriver": "webdriver-manager update" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/templates/src/pages/Index.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jsx React.DOM 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var React = require('react'); 8 | var DefaultLayout = require('../layouts/DefaultLayout.jsx'); 9 | 10 | var HomePage = React.createClass({ 11 | getDefaultProps() { 12 | return { 13 | title: 'React.js Starter Kit', 14 | layout: DefaultLayout 15 | }; 16 | }, 17 | render() { 18 | return ( 19 |
20 |
21 |
22 |

Runtime Components

23 |
24 |
React
25 |
A JavaScript library for building user interfaces, developed by Facebook
26 |
Director
27 |
A tiny and isomorphic URL router for JavaScript
28 |
Bootstrap
29 |
CSS framework for developing responsive, mobile first interfaces
30 |
31 |
32 |
33 |

Development Tools

34 |
35 |
Gulp
36 |
JavaScript streaming build system and task automation
37 |
Webpack
38 |
Compiles front-end source code into modules / bundles
39 |
BrowserSync
40 |
A lightweight HTTP server for development
41 |
42 |
43 |
44 |

Fork me on GitHub

45 |

github.com/kriasoft/react-starter-kit

46 |
47 |
48 |
49 | ); 50 | } 51 | }); 52 | 53 | module.exports = HomePage; 54 | -------------------------------------------------------------------------------- /app/templates/config/webpack.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Facebook React Starter Kit | https://github.com/kriasoft/react-starter-kit 3 | * Copyright (c) KriaSoft, LLC. All rights reserved. See LICENSE.txt 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var webpack = require('webpack'); 9 | 10 | /** 11 | * Get configuration for Webpack 12 | * 13 | * @see http://webpack.github.io/docs/configuration 14 | * https://github.com/petehunt/webpack-howto 15 | * 16 | * @param {boolean} release True if configuration is intended to be used in 17 | * a release mode, false otherwise 18 | * @return {object} Webpack configuration 19 | */ 20 | module.exports = function(release) { 21 | return { 22 | entry: './src/app.js', 23 | 24 | output: { 25 | filename: 'app.js', 26 | path: './build/', 27 | publicPatch: './build/' 28 | }, 29 | 30 | cache: !release, 31 | debug: !release, 32 | devtool: false, 33 | 34 | stats: { 35 | colors: true, 36 | reasons: !release 37 | }, 38 | 39 | plugins: release ? [ 40 | new webpack.DefinePlugin({'process.env.NODE_ENV': '"production"'}), 41 | new webpack.optimize.DedupePlugin(), 42 | new webpack.optimize.UglifyJsPlugin(), 43 | new webpack.optimize.OccurenceOrderPlugin(), 44 | new webpack.optimize.AggressiveMergingPlugin() 45 | ] : [], 46 | 47 | resolve: { 48 | extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx'] 49 | }, 50 | 51 | module: { 52 | preLoaders: [ 53 | { 54 | test: /\.js$/, 55 | exclude: /node_modules/, 56 | loader: 'jshint' 57 | } 58 | ], 59 | 60 | loaders: [ 61 | { 62 | test: /\.css$/, 63 | loader: 'style!css' 64 | }, 65 | { 66 | test: /\.less$/, 67 | loader: 'style!css!less' 68 | }, 69 | { 70 | test: /\.gif/, 71 | loader: 'url-loader?limit=10000&mimetype=image/gif' 72 | }, 73 | { 74 | test: /\.jpg/, 75 | loader: 'url-loader?limit=10000&mimetype=image/jpg' 76 | }, 77 | { 78 | test: /\.png/, 79 | loader: 'url-loader?limit=10000&mimetype=image/png' 80 | }, 81 | { 82 | test: /\.jsx?$/, 83 | loader: 'jsx-loader?harmony' 84 | } 85 | ] 86 | } 87 | }; 88 | }; 89 | -------------------------------------------------------------------------------- /app/templates/src/styles/bootstrap.less: -------------------------------------------------------------------------------- 1 | // ============================================================================= 2 | // Bootstrap CSS + Custom styles and overrides 3 | // ============================================================================= 4 | 5 | // Core variables and mixins 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | 9 | // Reset and dependencies 10 | @import "../../node_modules/bootstrap/less/normalize.less"; 11 | @import "../../node_modules/bootstrap/less/print.less"; 12 | @import "../../node_modules/bootstrap/less/glyphicons.less"; 13 | 14 | // Core CSS 15 | @import "../../node_modules/bootstrap/less/scaffolding.less"; 16 | @import "../../node_modules/bootstrap/less/type.less"; 17 | @import "../../node_modules/bootstrap/less/code.less"; 18 | @import "../../node_modules/bootstrap/less/grid.less"; 19 | @import "../../node_modules/bootstrap/less/tables.less"; 20 | @import "../../node_modules/bootstrap/less/forms.less"; 21 | @import "../../node_modules/bootstrap/less/buttons.less"; 22 | 23 | // Components 24 | @import "../../node_modules/bootstrap/less/component-animations.less"; 25 | @import "../../node_modules/bootstrap/less/dropdowns.less"; 26 | @import "../../node_modules/bootstrap/less/button-groups.less"; 27 | @import "../../node_modules/bootstrap/less/input-groups.less"; 28 | @import "../../node_modules/bootstrap/less/navs.less"; 29 | @import "navbar.less"; 30 | @import "../../node_modules/bootstrap/less/breadcrumbs.less"; 31 | @import "../../node_modules/bootstrap/less/pagination.less"; 32 | @import "../../node_modules/bootstrap/less/pager.less"; 33 | @import "../../node_modules/bootstrap/less/labels.less"; 34 | @import "../../node_modules/bootstrap/less/badges.less"; 35 | @import "jumbotron.less"; 36 | @import "../../node_modules/bootstrap/less/thumbnails.less"; 37 | @import "../../node_modules/bootstrap/less/alerts.less"; 38 | @import "../../node_modules/bootstrap/less/progress-bars.less"; 39 | @import "../../node_modules/bootstrap/less/media.less"; 40 | @import "../../node_modules/bootstrap/less/list-group.less"; 41 | @import "../../node_modules/bootstrap/less/panels.less"; 42 | @import "../../node_modules/bootstrap/less/responsive-embed.less"; 43 | @import "../../node_modules/bootstrap/less/wells.less"; 44 | @import "../../node_modules/bootstrap/less/close.less"; 45 | 46 | // Components w/ JavaScript 47 | @import "../../node_modules/bootstrap/less/modals.less"; 48 | @import "../../node_modules/bootstrap/less/tooltip.less"; 49 | @import "../../node_modules/bootstrap/less/popovers.less"; 50 | @import "../../node_modules/bootstrap/less/carousel.less"; 51 | 52 | // Utility classes 53 | @import "utilities.less"; 54 | @import "../../node_modules/bootstrap/less/responsive-utilities.less"; 55 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var path = require('path'); 4 | var yeoman = require('yeoman-generator'); 5 | var yosay = require('yosay'); 6 | 7 | var FluxWebappGenerator = yeoman.generators.Base.extend({ 8 | initializing: function () { 9 | this.pkg = require('../package.json'); 10 | }, 11 | 12 | prompting: function () { 13 | var done = this.async(); 14 | 15 | // Have Yeoman greet the user. 16 | this.log(yosay( 17 | 'Welcome to the incredible FluxWebapp generator!' 18 | )); 19 | 20 | var prompts = [{ 21 | type : 'input', 22 | name : 'name', 23 | message : 'Your project name', 24 | default : this.appname 25 | }]; 26 | this.prompt(prompts, function (props) { 27 | this.name = props.name; 28 | done(); 29 | }.bind(this)); 30 | }, 31 | 32 | writing: { 33 | app: function () { 34 | 35 | var context = { 36 | title: this.name, 37 | description: 'Flux Webapp application', 38 | appname: this.name 39 | }; 40 | 41 | this.template('_package.json', 'package.json', context); 42 | this.src.copy('_bower.json', 'bower.json'); 43 | this.dest.mkdir('config'); 44 | this.dest.mkdir('src'); 45 | this.dest.mkdir('src/actions'); 46 | this.dest.mkdir('src/assets'); 47 | this.dest.mkdir('src/components'); 48 | this.dest.mkdir('src/constants'); 49 | this.dest.mkdir('src/images'); 50 | this.dest.mkdir('src/layouts'); 51 | this.dest.mkdir('src/pages'); 52 | this.template('src/pages/404.html'); 53 | this.template('src/pages/_template.html', 'src/pages/_template.html', context); 54 | this.src.copy('src/actions/RouteActions.js', 'src/actions/RouteActions.js'); 55 | this.src.copy('src/pages/Index.jsx', 'src/pages/Index.jsx'); 56 | this.src.copy('src/pages/Privacy.jsx', 'src/pages/Privacy.jsx'); 57 | this.directory('src/assets/', 'src/assets/'); 58 | this.directory('src/components/', 'src/components/'); 59 | this.directory('src/constants/', 'src/constants/'); 60 | this.directory('src/images/', 'src/images/'); 61 | this.directory('src/layouts/', 'src/layouts/'); 62 | this.directory('src/styles/', 'src/styles/'); 63 | this.directory('config/', 'config/'); 64 | this.src.copy('src/app.js', 'src/app.js'); 65 | this.src.copy('src/AppDispatcher.js', 'src/AppDispatcher.js'); 66 | 67 | }, 68 | 69 | projectfiles: function () { 70 | this.src.copy('editorconfig', '.editorconfig'); 71 | this.src.copy('jshintrc', '.jshintrc'); 72 | this.src.copy('_.gitignore', '.gitignore'); 73 | this.src.copy('gulpfile.js', 'gulpfile.js'); 74 | this.src.copy('LICENSE.txt', 'LICENSE.txt'); 75 | this.src.copy('README.md', 'README.md'); 76 | } 77 | }, 78 | 79 | end: function () { 80 | this.installDependencies(); 81 | } 82 | }); 83 | 84 | module.exports = FluxWebappGenerator; 85 | -------------------------------------------------------------------------------- /app/templates/src/pages/Privacy.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @jsx React.DOM 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var React = require('react'); 8 | var Link = require('../components/Link.jsx'); 9 | var DefaultLayout = require('../layouts/DefaultLayout.jsx'); 10 | 11 | var PrivacyPage = React.createClass({ 12 | getDefaultProps() { 13 | return { 14 | title: 'Privacy Policy', 15 | layout: DefaultLayout, 16 | breadcrumb: ( 17 |
    18 |
  1. Home
  2. 19 |
  3. Privacy
  4. 20 |
21 | ) 22 | }; 23 | }, 24 | render() { 25 | return ( 26 |
27 |

28 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean consequat tortor fermentum mi 29 | fermentum dignissim. Nullam vel ipsum ut ligula elementum lobortis. Maecenas aliquam, massa laoreet 30 | lacinia pretium, nisi urna venenatis tortor, nec imperdiet tellus libero efficitur metus. Fusce 31 | semper posuere ligula, et facilisis metus bibendum interdum. Mauris at mauris sit amet sem pharetra 32 | commodo a eu leo. Nam at est non risus cursus maximus. Nam feugiat augue libero, id consectetur 33 | tortor bibendum non. Quisque nec fringilla lorem. Nullam efficitur vulputate mauris, nec maximus leo 34 | dignissim id. 35 |

36 |

37 | In hac habitasse platea dictumst. Duis sagittis dui ac ex suscipit maximus. Morbi pellentesque 38 | venenatis felis sed convallis. Nulla varius, nibh vitae placerat tempus, mauris sem elementum ipsum, 39 | eget sollicitudin nisl est vel purus. Fusce malesuada odio velit, non cursus leo fermentum id. Cras 40 | pharetra sodales fringilla. Etiam quis est a dolor egestas pellentesque. Maecenas non scelerisque 41 | purus, congue cursus arcu. Donec vel dapibus mi. Mauris maximus posuere placerat. Sed et libero eu 42 | nibh tristique mollis a eget lectus. Donec interdum augue sollicitudin vehicula hendrerit. Vivamus 43 | justo orci, molestie ac sollicitudin ac, lobortis at tellus. Etiam rhoncus ullamcorper risus eu 44 | tempor. Sed porttitor, neque ac efficitur gravida, arcu lacus pharetra dui, in consequat elit tellus 45 | auctor nulla. Donec placerat elementum diam, vitae imperdiet lectus luctus at. 46 |

47 |

48 | Nullam eu feugiat mi. Quisque nec tristique nisl, dignissim dictum leo. Nam non quam nisi. Donec 49 | rutrum turpis ac diam blandit, id pulvinar mauris suscipit. Pellentesque tincidunt libero ultricies 50 | risus iaculis, sit amet consequat velit blandit. Fusce quis varius nulla. Nullam nisi nisi, suscipit 51 | ut magna quis, feugiat porta nibh. Sed id enim lectus. Suspendisse elementum justo sapien, sit amet 52 | consequat orci accumsan et. Aliquam ornare ullamcorper sem sed finibus. Nullam ac lacus pulvinar, 53 | egestas felis ut, accumsan est. 54 |

55 |

56 | Pellentesque sagittis vehicula sem quis luctus. Proin sodales magna in lorem hendrerit aliquam. 57 | Integer eu varius orci. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere 58 | cubilia Curae; Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia 59 | Curae; Ut at mauris nibh. Suspendisse maximus ac eros at vestibulum. 60 |

61 |

62 | Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque egestas tortor et dui 63 | consequat faucibus. Nunc vitae odio ornare, venenatis ligula a, vulputate nisl. Aenean congue varius 64 | ex, sit amet bibendum odio posuere at. Nulla facilisi. In finibus, nulla vitae tincidunt ornare, 65 | sapien nulla fermentum mauris, sed consectetur tortor arcu eget arcu. Vestibulum vel quam enim. 66 |

67 |
68 | ); 69 | } 70 | }); 71 | 72 | module.exports = PrivacyPage; 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React / Flux  Starter Kit 2 | 3 | [![Build Status](http://img.shields.io/travis/kriasoft/react-starter-kit/master.svg?style=flat)](http://travis-ci.org/kriasoft/react-starter-kit) 4 | [![Dependency Status](https://david-dm.org/kriasoft/react-starter-kit.svg?style=flat)](https://david-dm.org/kriasoft/react-starter-kit) 5 | [![devDependency Status](https://david-dm.org/kriasoft/react-starter-kit/dev-status.svg?style=flat)](https://david-dm.org/kriasoft/react-starter-kit#info=devDependencies) 6 | [![Tips](http://img.shields.io/gratipay/koistya.svg?style=flat)](https://gratipay.com/koistya) 7 | [![Gitter](http://img.shields.io/badge/chat-online-brightgreen.svg?style=flat)](https://gitter.im/kriasoft/react-starter-kit) 8 | 9 | > This project template is a skeleton for an [isomorphic](http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/) 10 | > web application (SPA) based on Facebook's [React](https://facebook.github.io/react/) 11 | > library and [Flux](http://facebook.github.io/flux/) architecture. You can use 12 | > it to quickly bootstrap your web application projects. It contains only 13 | > client-side components and development tools. 14 | 15 | [![Facebook React Starter Kit](https://dl.dropboxusercontent.com/u/16006521/Screens/facebook-react-starter-kit.png)](https://github.com/kriasoft/react-starter-kit) 16 | 17 | **Demo**: http://reactjs.kriasoft.com 18 | 19 | ### Directory Layout 20 | 21 | ``` 22 | . 23 | ├── /build/ # The folder for compiled output 24 | ├── /config/ # Configuration files for Webpack, Jest etc. 25 | ├── /docs/ # Documentation files for the project 26 | ├── /node_modules/ # 3rd-party libraries and utilities 27 | ├── /src/ # The source code of the application 28 | │ ├── /actions/ # Action creators that allow to trigger a dispatch to stores 29 | │ ├── /assets/ # Static files which are copied to ./build on compile 30 | │ ├── /constants/ # Enumerations used in action creators and stores 31 | │ ├── /components/ # React components. E.g. Navbar.jsx, Calendar.jsx 32 | │ ├── /images/ # Graphics (.png, .jpg, .svg etc.) 33 | │ ├── /layouts/ # Shared layouts for top-level components 34 | │ ├── /pages/ # Top-level, URL-bound React components 35 | │ ├── /stores/ # Stores contain the application state and logic 36 | │ ├── /styles/ # CSS style sheets (or LESS, SASS, Stylus) 37 | │ ├── /app.js # The application's bootstrap file, entry point 38 | │ └── /AppDispatcher.js # The central hub that manages all data flow (see Flux) 39 | ├── /test/ # Unit, integration and load tests 40 | │ ├── /e2e/ # End-to-end tests 41 | │ └── /unit/ # Unit tests 42 | │── gulpfile.js # Configuration file for automated builds 43 | └── package.json # The list of 3rd party libraries and utilities 44 | ``` 45 | 46 | ### Getting Started 47 | 48 | This yeoman generator is based on https://github.com/kriasoft/react-starter-kit: 49 | 50 | ```shell 51 | $ npm install -g generator-flux-webapp 52 | ``` 53 | 54 | 55 | ```shell 56 | $ mkdir demo-app 57 | $ cd demo-app 58 | $ yo flux-webapp 59 | $ gulp 60 | ``` 61 | 62 | ### How to Build 63 | ```shell 64 | $ gulp build # or, `gulp build --release` 65 | ``` 66 | 67 | By default, it builds in debug mode. If you need to build in release mode, add 68 | `--release` flag. 69 | 70 | ### How to Run 71 | 72 | ```shell 73 | $ gulp # or, `gulp --release` 74 | ``` 75 | 76 | This will start a lightweight development server with LiveReload and 77 | synchronized browsing across multiple devices and browsers. 78 | 79 | ### How to Deploy 80 | 81 | ```shell 82 | $ gulp deploy # or, `gulp deploy --production` 83 | ``` 84 | 85 | You can deploy to different destinations by adding a corresponding flag. 86 | For example `--production` or `--staging` etc. See the 'deploy' task in 87 | `gulpfile.js`. 88 | -------------------------------------------------------------------------------- /app/templates/README.md: -------------------------------------------------------------------------------- 1 | # React / Flux  Starter Kit 2 | 3 | [![Build Status](http://img.shields.io/travis/kriasoft/react-starter-kit/master.svg?style=flat)](http://travis-ci.org/kriasoft/react-starter-kit) 4 | [![Dependency Status](https://david-dm.org/kriasoft/react-starter-kit.svg?style=flat)](https://david-dm.org/kriasoft/react-starter-kit) 5 | [![devDependency Status](https://david-dm.org/kriasoft/react-starter-kit/dev-status.svg?style=flat)](https://david-dm.org/kriasoft/react-starter-kit#info=devDependencies) 6 | [![Tips](http://img.shields.io/gratipay/koistya.svg?style=flat)](https://gratipay.com/koistya) 7 | [![Gitter](http://img.shields.io/badge/chat-online-brightgreen.svg?style=flat)](https://gitter.im/kriasoft/react-starter-kit) 8 | 9 | > This project template is a skeleton for an [isomorphic](http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/) 10 | > web application (SPA) based on Facebook's [React](https://facebook.github.io/react/) 11 | > library and [Flux](http://facebook.github.io/flux/) architecture. You can use 12 | > it to quickly bootstrap your web application projects. It contains only 13 | > client-side components and development tools. 14 | 15 | [![Facebook React Starter Kit](https://dl.dropboxusercontent.com/u/16006521/Screens/facebook-react-starter-kit.png)](https://github.com/kriasoft/react-starter-kit) 16 | 17 | **Demo**: http://reactjs.kriasoft.com 18 | 19 | ### Directory Layout 20 | 21 | ``` 22 | . 23 | ├── /build/ # The folder for compiled output 24 | ├── /config/ # Configuration files for Webpack, Jest etc. 25 | ├── /docs/ # Documentation files for the project 26 | ├── /node_modules/ # 3rd-party libraries and utilities 27 | ├── /src/ # The source code of the application 28 | │ ├── /actions/ # Action creators that allow to trigger a dispatch to stores 29 | │ ├── /assets/ # Static files which are copied to ./build on compile 30 | │ ├── /constants/ # Enumerations used in action creators and stores 31 | │ ├── /components/ # React components. E.g. Navbar.jsx, Calendar.jsx 32 | │ ├── /images/ # Graphics (.png, .jpg, .svg etc.) 33 | │ ├── /layouts/ # Shared layouts for top-level components 34 | │ ├── /pages/ # Top-level, URL-bound React components 35 | │ ├── /stores/ # Stores contain the application state and logic 36 | │ ├── /styles/ # CSS style sheets (or LESS, SASS, Stylus) 37 | │ ├── /app.js # The application's bootstrap file, entry point 38 | │ └── /AppDispatcher.js # The central hub that manages all data flow (see Flux) 39 | ├── /test/ # Unit, integration and load tests 40 | │ ├── /e2e/ # End-to-end tests 41 | │ └── /unit/ # Unit tests 42 | │── gulpfile.js # Configuration file for automated builds 43 | └── package.json # The list of 3rd party libraries and utilities 44 | ``` 45 | 46 | ### Getting Started 47 | 48 | This yeoman generator is based on https://github.com/kriasoft/react-starter-kit: 49 | 50 | ```shell 51 | $ npm install -g generator-flux-webapp 52 | ``` 53 | 54 | 55 | ```shell 56 | $ mkdir demo-app 57 | $ cd demo-app 58 | $ yo flux-webapp 59 | $ gulp 60 | ``` 61 | 62 | ### How to Build 63 | ```shell 64 | $ gulp build # or, `gulp build --release` 65 | ``` 66 | 67 | By default, it builds in debug mode. If you need to build in release mode, add 68 | `--release` flag. 69 | 70 | ### How to Run 71 | 72 | ```shell 73 | $ gulp # or, `gulp --release` 74 | ``` 75 | 76 | This will start a lightweight development server with LiveReload and 77 | synchronized browsing across multiple devices and browsers. 78 | 79 | ### How to Deploy 80 | 81 | ```shell 82 | $ gulp deploy # or, `gulp deploy --production` 83 | ``` 84 | 85 | You can deploy to different destinations by adding a corresponding flag. 86 | For example `--production` or `--staging` etc. See the 'deploy' task in 87 | `gulpfile.js`. 88 | -------------------------------------------------------------------------------- /app/templates/gulpfile.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Facebook React Starter Kit | https://github.com/kriasoft/react-starter-kit 3 | * Copyright (c) KriaSoft, LLC. All rights reserved. See LICENSE.txt 4 | */ 5 | 6 | 'use strict'; 7 | 8 | // Include Gulp and other build automation tools and utilities 9 | // See: https://github.com/gulpjs/gulp/blob/master/docs/API.md 10 | var gulp = require('gulp'); 11 | var $ = require('gulp-load-plugins')(); 12 | var del = require('del'); 13 | var path = require('path'); 14 | var merge = require('merge-stream'); 15 | var runSequence = require('run-sequence'); 16 | var webpack = require('webpack'); 17 | var browserSync = require('browser-sync'); 18 | var pagespeed = require('psi'); 19 | var argv = require('minimist')(process.argv.slice(2)); 20 | 21 | // Settings 22 | var DEST = './build'; // The build output folder 23 | var RELEASE = !!argv.release; // Minimize and optimize during a build? 24 | var GOOGLE_ANALYTICS_ID = 'UA-XXXXX-X'; // https://www.google.com/analytics/web/ 25 | var AUTOPREFIXER_BROWSERS = [ // https://github.com/ai/autoprefixer 26 | 'ie >= 10', 27 | 'ie_mob >= 10', 28 | 'ff >= 30', 29 | 'chrome >= 34', 30 | 'safari >= 7', 31 | 'opera >= 23', 32 | 'ios >= 7', 33 | 'android >= 4.4', 34 | 'bb >= 10' 35 | ]; 36 | 37 | var src = {}; 38 | var watch = false; 39 | var pkgs = (function() { 40 | var pkgs = {}; 41 | var map = function(source) { 42 | for (var key in source) { 43 | pkgs[key.replace(/[^a-z0-9]/gi, '')] = source[key].substring(1); 44 | } 45 | }; 46 | map(require('./package.json').dependencies); 47 | return pkgs; 48 | }()); 49 | 50 | // The default task 51 | gulp.task('default', ['serve']); 52 | 53 | // Clean up 54 | gulp.task('clean', del.bind(null, [DEST])); 55 | 56 | // 3rd party libraries 57 | gulp.task('vendor', function() { 58 | return merge( 59 | gulp.src('./node_modules/jquery/dist/**') 60 | .pipe(gulp.dest(DEST + '/vendor/jquery-' + pkgs.jquery)), 61 | gulp.src('./node_modules/bootstrap/dist/fonts/**') 62 | .pipe(gulp.dest(DEST + '/fonts')) 63 | ); 64 | }); 65 | 66 | // Static files 67 | gulp.task('assets', function() { 68 | src.assets = 'src/assets/**'; 69 | return gulp.src(src.assets) 70 | .pipe($.changed(DEST)) 71 | .pipe(gulp.dest(DEST)) 72 | .pipe($.size({title: 'assets'})); 73 | }); 74 | 75 | // Images 76 | gulp.task('images', function() { 77 | src.images = 'src/images/**'; 78 | return gulp.src(src.images) 79 | .pipe($.changed(DEST + '/images')) 80 | .pipe($.imagemin({ 81 | progressive: true, 82 | interlaced: true 83 | })) 84 | .pipe(gulp.dest(DEST + '/images')) 85 | .pipe($.size({title: 'images'})); 86 | }); 87 | 88 | // HTML pages 89 | gulp.task('pages', function() { 90 | src.pages = { jsx: 'src/pages/**/*.jsx', html: 'src/pages/404.html'}; 91 | // create pages array for gulp src 92 | var pages = Object 93 | .keys(src.pages) 94 | .map(function (key) { return src.pages[key]; }); 95 | var render = $.render({template: './src/pages/_template.html'}) 96 | .on('error', function(err) { console.log(err); render.end(); }); 97 | return gulp.src(src.pages) 98 | .pipe($.changed(DEST, {extension: '.html'})) 99 | .pipe($.if('*.jsx', render)) 100 | .pipe($.replace('UA-XXXXX-X', GOOGLE_ANALYTICS_ID)) 101 | .pipe($.if(RELEASE, $.htmlmin({ 102 | removeComments: true, 103 | collapseWhitespace: true, 104 | minifyJS: true 105 | }), $.jsbeautifier())) 106 | .pipe(gulp.dest(DEST)) 107 | .pipe($.size({title: 'pages'})); 108 | }); 109 | 110 | // CSS style sheets 111 | gulp.task('styles', function() { 112 | src.styles = 'src/styles/**/*.{css,less}'; 113 | return gulp.src('src/styles/bootstrap.less') 114 | .pipe($.plumber()) 115 | .pipe($.less({ 116 | sourceMap: !RELEASE, 117 | sourceMapBasepath: __dirname 118 | })) 119 | .on('error', console.error.bind(console)) 120 | .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS})) 121 | .pipe($.csscomb()) 122 | .pipe($.if(RELEASE, $.minifyCss())) 123 | .pipe(gulp.dest(DEST + '/css')) 124 | .pipe($.size({title: 'styles'})); 125 | }); 126 | 127 | // Bundle 128 | gulp.task('bundle', function(cb) { 129 | var started = false; 130 | var config = require('./config/webpack.js')(RELEASE); 131 | var bundler = webpack(config); 132 | 133 | function bundle(err, stats) { 134 | if (err) { 135 | throw new $.util.PluginError('webpack', err); 136 | } 137 | 138 | !!argv.verbose && $.util.log('[webpack]', stats.toString({colors: true})); 139 | 140 | if (!started) { 141 | started = true; 142 | return cb(); 143 | } 144 | } 145 | 146 | if (watch) { 147 | bundler.watch(200, bundle); 148 | } else { 149 | bundler.run(bundle); 150 | } 151 | }); 152 | 153 | // Build the app from source code 154 | gulp.task('build', ['clean'], function(cb) { 155 | runSequence(['vendor', 'assets', 'images', 'pages', 'styles', 'bundle'], cb); 156 | }); 157 | 158 | // Launch a lightweight HTTP Server 159 | gulp.task('serve', function(cb) { 160 | 161 | var url = require('url'); 162 | var fs = require('fs'); 163 | watch = true; 164 | 165 | runSequence('build', function() { 166 | browserSync({ 167 | notify: false, 168 | // Customize the BrowserSync console logging prefix 169 | logPrefix: 'RSK', 170 | // Run as an https by uncommenting 'https: true' 171 | // Note: this uses an unsigned certificate which on first access 172 | // will present a certificate warning in the browser. 173 | // https: true, 174 | server: { 175 | baseDir: DEST, 176 | // Allow web page requests without .html file extension in URLs 177 | middleware: function(req, res, cb) { 178 | var uri = url.parse(req.url); 179 | if (uri.pathname.length > 1 && 180 | path.extname(uri.pathname) === '' && 181 | fs.existsSync(DEST + uri.pathname + '.html')) { 182 | req.url = uri.pathname + '.html' + (uri.search || ''); 183 | } 184 | cb(); 185 | } 186 | } 187 | }); 188 | 189 | gulp.watch(src.assets, ['assets']); 190 | gulp.watch(src.images, ['images']); 191 | gulp.watch(src.pages.html, ['pages']); 192 | gulp.watch(src.pages.jsx, ['pages', 'bundle']); 193 | gulp.watch(src.styles, ['styles']); 194 | gulp.watch(DEST + '/**/*.*', function(file) { 195 | browserSync.reload(path.relative(__dirname, file.path)); 196 | }); 197 | cb(); 198 | }); 199 | }); 200 | 201 | // Deploy to GitHub Pages 202 | gulp.task('deploy', function() { 203 | 204 | // Remove temp folder 205 | if (argv.clean) { 206 | var os = require('os'); 207 | var path = require('path'); 208 | var repoPath = path.join(os.tmpdir(), 'tmpRepo'); 209 | $.util.log('Delete ' + $.util.colors.magenta(repoPath)); 210 | del.sync(repoPath, {force: true}); 211 | } 212 | 213 | return gulp.src(DEST + '/**/*') 214 | .pipe($.if('**/robots.txt', !argv.production ? $.replace('Disallow:', 'Disallow: /') : $.util.noop())) 215 | .pipe($.ghPages({ 216 | remoteUrl: 'https://github.com/{name}/{name}.github.io.git', 217 | branch: 'master' 218 | })); 219 | }); 220 | 221 | // Run PageSpeed Insights 222 | // Update `url` below to the public URL for your site 223 | gulp.task('pagespeed', pagespeed.bind(null, { 224 | // By default, we use the PageSpeed Insights 225 | // free (no API key) tier. You can use a Google 226 | // Developer API key if you have one. See 227 | // http://goo.gl/RkN0vE for info key: 'YOUR_API_KEY' 228 | url: 'https://example.com', 229 | strategy: 'mobile' 230 | })); 231 | -------------------------------------------------------------------------------- /app/templates/src/styles/.csscomb.json: -------------------------------------------------------------------------------- 1 | { 2 | "always-semicolon": true, 3 | "block-indent": 2, 4 | "colon-space": [0, 1], 5 | "color-case": "lower", 6 | "color-shorthand": true, 7 | "combinator-space": true, 8 | "element-case": "lower", 9 | "eof-newline": true, 10 | "leading-zero": false, 11 | "remove-empty-rulesets": true, 12 | "rule-indent": 2, 13 | "stick-brace": " ", 14 | "strip-spaces": true, 15 | "unitless-zero": true, 16 | "vendor-prefix-align": true, 17 | "sort-order": [ 18 | [ 19 | "position", 20 | "top", 21 | "right", 22 | "bottom", 23 | "left", 24 | "z-index", 25 | "display", 26 | "float", 27 | "width", 28 | "min-width", 29 | "max-width", 30 | "height", 31 | "min-height", 32 | "max-height", 33 | "-webkit-box-sizing", 34 | "-moz-box-sizing", 35 | "box-sizing", 36 | "-webkit-appearance", 37 | "padding", 38 | "padding-top", 39 | "padding-right", 40 | "padding-bottom", 41 | "padding-left", 42 | "margin", 43 | "margin-top", 44 | "margin-right", 45 | "margin-bottom", 46 | "margin-left", 47 | "overflow", 48 | "overflow-x", 49 | "overflow-y", 50 | "-webkit-overflow-scrolling", 51 | "-ms-overflow-x", 52 | "-ms-overflow-y", 53 | "-ms-overflow-style", 54 | "clip", 55 | "clear", 56 | "font", 57 | "font-family", 58 | "font-size", 59 | "font-style", 60 | "font-weight", 61 | "font-variant", 62 | "font-size-adjust", 63 | "font-stretch", 64 | "font-effect", 65 | "font-emphasize", 66 | "font-emphasize-position", 67 | "font-emphasize-style", 68 | "font-smooth", 69 | "-webkit-hyphens", 70 | "-moz-hyphens", 71 | "hyphens", 72 | "line-height", 73 | "color", 74 | "text-align", 75 | "-webkit-text-align-last", 76 | "-moz-text-align-last", 77 | "-ms-text-align-last", 78 | "text-align-last", 79 | "text-emphasis", 80 | "text-emphasis-color", 81 | "text-emphasis-style", 82 | "text-emphasis-position", 83 | "text-decoration", 84 | "text-indent", 85 | "text-justify", 86 | "text-outline", 87 | "-ms-text-overflow", 88 | "text-overflow", 89 | "text-overflow-ellipsis", 90 | "text-overflow-mode", 91 | "text-shadow", 92 | "text-transform", 93 | "text-wrap", 94 | "-webkit-text-size-adjust", 95 | "-ms-text-size-adjust", 96 | "letter-spacing", 97 | "-ms-word-break", 98 | "word-break", 99 | "word-spacing", 100 | "-ms-word-wrap", 101 | "word-wrap", 102 | "-moz-tab-size", 103 | "-o-tab-size", 104 | "tab-size", 105 | "white-space", 106 | "vertical-align", 107 | "list-style", 108 | "list-style-position", 109 | "list-style-type", 110 | "list-style-image", 111 | "pointer-events", 112 | "cursor", 113 | "visibility", 114 | "zoom", 115 | "flex-direction", 116 | "flex-order", 117 | "flex-pack", 118 | "flex-align", 119 | "table-layout", 120 | "empty-cells", 121 | "caption-side", 122 | "border-spacing", 123 | "border-collapse", 124 | "content", 125 | "quotes", 126 | "counter-reset", 127 | "counter-increment", 128 | "resize", 129 | "-webkit-user-select", 130 | "-moz-user-select", 131 | "-ms-user-select", 132 | "-o-user-select", 133 | "user-select", 134 | "nav-index", 135 | "nav-up", 136 | "nav-right", 137 | "nav-down", 138 | "nav-left", 139 | "background", 140 | "background-color", 141 | "background-image", 142 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", 143 | "filter:progid:DXImageTransform.Microsoft.gradient", 144 | "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", 145 | "filter", 146 | "background-repeat", 147 | "background-attachment", 148 | "background-position", 149 | "background-position-x", 150 | "background-position-y", 151 | "-webkit-background-clip", 152 | "-moz-background-clip", 153 | "background-clip", 154 | "background-origin", 155 | "-webkit-background-size", 156 | "-moz-background-size", 157 | "-o-background-size", 158 | "background-size", 159 | "border", 160 | "border-color", 161 | "border-style", 162 | "border-width", 163 | "border-top", 164 | "border-top-color", 165 | "border-top-style", 166 | "border-top-width", 167 | "border-right", 168 | "border-right-color", 169 | "border-right-style", 170 | "border-right-width", 171 | "border-bottom", 172 | "border-bottom-color", 173 | "border-bottom-style", 174 | "border-bottom-width", 175 | "border-left", 176 | "border-left-color", 177 | "border-left-style", 178 | "border-left-width", 179 | "border-radius", 180 | "border-top-left-radius", 181 | "border-top-right-radius", 182 | "border-bottom-right-radius", 183 | "border-bottom-left-radius", 184 | "-webkit-border-image", 185 | "-moz-border-image", 186 | "-o-border-image", 187 | "border-image", 188 | "-webkit-border-image-source", 189 | "-moz-border-image-source", 190 | "-o-border-image-source", 191 | "border-image-source", 192 | "-webkit-border-image-slice", 193 | "-moz-border-image-slice", 194 | "-o-border-image-slice", 195 | "border-image-slice", 196 | "-webkit-border-image-width", 197 | "-moz-border-image-width", 198 | "-o-border-image-width", 199 | "border-image-width", 200 | "-webkit-border-image-outset", 201 | "-moz-border-image-outset", 202 | "-o-border-image-outset", 203 | "border-image-outset", 204 | "-webkit-border-image-repeat", 205 | "-moz-border-image-repeat", 206 | "-o-border-image-repeat", 207 | "border-image-repeat", 208 | "outline", 209 | "outline-width", 210 | "outline-style", 211 | "outline-color", 212 | "outline-offset", 213 | "-webkit-box-shadow", 214 | "-moz-box-shadow", 215 | "box-shadow", 216 | "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", 217 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", 218 | "opacity", 219 | "-ms-interpolation-mode", 220 | "-webkit-transition", 221 | "-moz-transition", 222 | "-ms-transition", 223 | "-o-transition", 224 | "transition", 225 | "-webkit-transition-delay", 226 | "-moz-transition-delay", 227 | "-ms-transition-delay", 228 | "-o-transition-delay", 229 | "transition-delay", 230 | "-webkit-transition-timing-function", 231 | "-moz-transition-timing-function", 232 | "-ms-transition-timing-function", 233 | "-o-transition-timing-function", 234 | "transition-timing-function", 235 | "-webkit-transition-duration", 236 | "-moz-transition-duration", 237 | "-ms-transition-duration", 238 | "-o-transition-duration", 239 | "transition-duration", 240 | "-webkit-transition-property", 241 | "-moz-transition-property", 242 | "-ms-transition-property", 243 | "-o-transition-property", 244 | "transition-property", 245 | "-webkit-transform", 246 | "-moz-transform", 247 | "-ms-transform", 248 | "-o-transform", 249 | "transform", 250 | "-webkit-transform-origin", 251 | "-moz-transform-origin", 252 | "-ms-transform-origin", 253 | "-o-transform-origin", 254 | "transform-origin", 255 | "-webkit-animation", 256 | "-moz-animation", 257 | "-ms-animation", 258 | "-o-animation", 259 | "animation", 260 | "-webkit-animation-name", 261 | "-moz-animation-name", 262 | "-ms-animation-name", 263 | "-o-animation-name", 264 | "animation-name", 265 | "-webkit-animation-duration", 266 | "-moz-animation-duration", 267 | "-ms-animation-duration", 268 | "-o-animation-duration", 269 | "animation-duration", 270 | "-webkit-animation-play-state", 271 | "-moz-animation-play-state", 272 | "-ms-animation-play-state", 273 | "-o-animation-play-state", 274 | "animation-play-state", 275 | "-webkit-animation-timing-function", 276 | "-moz-animation-timing-function", 277 | "-ms-animation-timing-function", 278 | "-o-animation-timing-function", 279 | "animation-timing-function", 280 | "-webkit-animation-delay", 281 | "-moz-animation-delay", 282 | "-ms-animation-delay", 283 | "-o-animation-delay", 284 | "animation-delay", 285 | "-webkit-animation-iteration-count", 286 | "-moz-animation-iteration-count", 287 | "-ms-animation-iteration-count", 288 | "-o-animation-iteration-count", 289 | "animation-iteration-count", 290 | "-webkit-animation-direction", 291 | "-moz-animation-direction", 292 | "-ms-animation-direction", 293 | "-o-animation-direction", 294 | "animation-direction" 295 | ] 296 | ] 297 | } 298 | --------------------------------------------------------------------------------