├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── data └── .gitkeep ├── divshot.json ├── package.json ├── scripts └── babelRelayPlugin.js ├── src ├── Reindex.js ├── components │ ├── App.js │ ├── Login.js │ └── Profile.js ├── config.js ├── index.html ├── index.js └── routes │ └── ProfileRoute.js ├── webpack.local.config.js └── webpack.production.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "react", 5 | "stage-1" 6 | ], 7 | "plugins": [ 8 | "transform-runtime", 9 | "syntax-async-functions", 10 | "./scripts/babelRelayPlugin" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | data/schema.json 30 | 31 | public/static 32 | .divshot-cache 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-present, Reindex Software 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # reindex-starter-kit 2 | 3 | Sample code to get started with Reindex, React and Relay. 4 | 5 | Fork and clone the repository. 6 | 7 | Install Reindex CLI library 8 | 9 | ``` 10 | npm install -g reindex-cli 11 | ``` 12 | 13 | Login to Reindex with your url and token 14 | 15 | ``` 16 | reindex login 17 | ``` 18 | 19 | Add your REINDEX_URL to `./src/config.js`. 20 | 21 | ``` 22 | export default { 23 | REINDEX_URL: 'YOUR-REINDEX-URL', 24 | }; 25 | ``` 26 | 27 | Install dependencies 28 | 29 | ``` 30 | npm install 31 | ``` 32 | 33 | Fetch current version of your GraphQL schema (you can add `ReindexSchema.json`) 34 | to git after that. Also fetch Relay schema (saved as ./data/schema.json). 35 | 36 | ``` 37 | reindex schema-fetch 38 | reindex schema-relay ./data/schema.json 39 | ``` 40 | 41 | Run and open on localhost:3000 42 | 43 | ``` 44 | npm start 45 | ``` 46 | 47 | Play with GraphiQL 48 | 49 | ``` 50 | reindex graphiql 51 | ``` 52 | 53 | Note that authentication will work only once you [enable authentication providers](https://www.reindex.io/docs/security/authentication/#social-login-authentication-providers) 54 | inside your Reindex console. 55 | 56 | ## Deploying 57 | 58 | Build minified js and css 59 | 60 | ``` 61 | npm run build 62 | ``` 63 | 64 | You can now push `build/` directory to your favorite static page hosting. 65 | We recommend [Surge](https://www.surge.sh), but you can also use Github 66 | Pages or any kind of hosting like that. 67 | 68 | ### Surge 69 | 70 | With Surge CLI you can deploy your app with just a few commands: 71 | 72 | ```sh 73 | npm install -g surge 74 | surge 75 | ``` 76 | -------------------------------------------------------------------------------- /data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reindexio/reindex-starter-kit-react/9c29c975c29451f5af9f5df54f7195ec9bd3b649/data/.gitkeep -------------------------------------------------------------------------------- /divshot.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reindex-starter-kit", 3 | "root": "./public", 4 | "clean_urls": true 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reindex-starter-kit", 3 | "version": "1.0.0", 4 | "description": "A quickstart template for building an app with React, Relay and Reindex", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack-dev-server --config webpack.local.config.js", 8 | "build": "webpack --progress --config webpack.production.config.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/reindexio/reindex-starter-kit.git" 13 | }, 14 | "keywords": [ 15 | "babel", 16 | "boilerplate", 17 | "graphql", 18 | "react", 19 | "reactjs", 20 | "reindex", 21 | "relay", 22 | "webpack" 23 | ], 24 | "author": "Reindex (https://www.reindex.io)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/reindexio/reindex-starter-kit/issues" 28 | }, 29 | "homepage": "https://github.com/reindexio/reindex-starter-kit#readme", 30 | "dependencies": { 31 | "babel-polyfill": "^6.9.1", 32 | "babel-runtime": "^5.8.20", 33 | "react": "^0.14.0-rc1", 34 | "react-dom": "^0.14.0-rc1", 35 | "react-relay": "^0.8.1", 36 | "reindex-js": "^0.3.1" 37 | }, 38 | "devDependencies": { 39 | "babel": "^5.8.23", 40 | "babel-core": "^6.2.4", 41 | "babel-eslint": "^6.0.2", 42 | "babel-loader": "^6.2.4", 43 | "babel-plugin-react-transform": "^1.1.1", 44 | "babel-plugin-transform-runtime": "^6.9.0", 45 | "babel-preset-es2015": "^6.9.0", 46 | "babel-preset-react": "^6.11.0", 47 | "babel-preset-stage-1": "^6.5.0", 48 | "babel-relay-plugin": "^0.8.1", 49 | "css-loader": "^0.19.0", 50 | "express": "^4.13.3", 51 | "extract-text-webpack-plugin": "^1.0.1", 52 | "html-webpack-plugin": "^2.21.0", 53 | "postcss-nested": "^1.0.0", 54 | "react-hot-loader": "^1.3.0", 55 | "react-transform-catch-errors": "^1.0.0", 56 | "react-transform-hmr": "^1.0.0", 57 | "redbox-react": "^1.0.1", 58 | "style-loader": "^0.12.4", 59 | "webpack": "^1.12.0", 60 | "webpack-dev-middleware": "^1.2.0", 61 | "webpack-dev-server": "^1.14.1", 62 | "webpack-hot-middleware": "^2.0.0" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scripts/babelRelayPlugin.js: -------------------------------------------------------------------------------- 1 | var getBabelRelayPlugin = require('babel-relay-plugin'); 2 | var schema = require('../data/schema.json'); 3 | 4 | module.exports = getBabelRelayPlugin(schema.data); 5 | -------------------------------------------------------------------------------- /src/Reindex.js: -------------------------------------------------------------------------------- 1 | import Reindex from 'reindex-js'; 2 | import Config from './config'; 3 | 4 | const reindex = new Reindex(Config.REINDEX_URL); 5 | 6 | export default reindex; 7 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Relay from 'react-relay'; 4 | 5 | import Reindex from '../Reindex'; 6 | import Profile from './Profile'; 7 | import Login from './Login'; 8 | import ProfileRoute from '../routes/ProfileRoute'; 9 | 10 | export default class App extends Component { 11 | state = { isLoggedIn: Reindex.isLoggedIn() }; 12 | 13 | handleLogin = (type) => { 14 | Reindex.login(type).catch((error) => { 15 | alert(error.message); 16 | }); 17 | }; 18 | 19 | handleLogout = () => { 20 | Reindex.logout(); 21 | }; 22 | 23 | handleTokenChange = () => { 24 | this.setState({ isLoggedIn: Reindex.isLoggedIn() }); 25 | }; 26 | 27 | componentDidMount() { 28 | Reindex.addListener('tokenChange', this.handleTokenChange); 29 | } 30 | 31 | componentWillUnmount() { 32 | Reindex.removeListener('tokenChange', this.handleTokenChange); 33 | } 34 | 35 | render() { 36 | if (this.state.isLoggedIn) { 37 | return ( 38 | { 43 | return ( 44 | 45 | ); 46 | }} /> 47 | ); 48 | } else { 49 | return ( 50 | 51 | ); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/components/Login.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | export default class Login extends Component { 4 | handleLogin = (type) => { 5 | if (this.props.onLogin) { 6 | this.props.onLogin(type); 7 | } 8 | } 9 | 10 | render() { 11 | return ( 12 |
13 |

Welcome to Reindex!

14 |
15 | 18 |
19 |
20 | 23 |
24 |
25 | 28 |
29 |
30 | 33 |
34 |
35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/components/Profile.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import Relay from 'react-relay'; 3 | 4 | class Profile extends Component { 5 | handleLogout = () => { 6 | if (this.props.onLogout) { 7 | this.props.onLogout(); 8 | } 9 | } 10 | 11 | getActiveCredential() { 12 | const credentials = this.props.viewer.user.credentials; 13 | for (const provider of ['google', 'facebook', 'twitter', 'github']) { 14 | if (credentials[provider]) { 15 | return { 16 | type: provider, 17 | displayName: credentials[provider].displayName 18 | }; 19 | } 20 | } 21 | } 22 | 23 | render() { 24 | const credentials = this.getActiveCredential(); 25 | return ( 26 |
27 |

Welcome to Reindex!

28 |
29 | You are user {credentials.displayName} 30 |
31 |
32 | Your Reindex ID is {this.props.viewer.user.id} 33 |
34 |
You are logged in with {credentials.type}
35 |
36 | 39 |
40 |
41 | ); 42 | } 43 | } 44 | 45 | export default Relay.createContainer(Profile, { 46 | fragments: { 47 | viewer: () => Relay.QL` 48 | fragment on ReindexViewer { 49 | user { 50 | id, 51 | credentials { 52 | google { 53 | displayName 54 | }, 55 | twitter { 56 | displayName 57 | }, 58 | github { 59 | displayName 60 | }, 61 | facebook { 62 | displayName 63 | } 64 | } 65 | } 66 | } 67 | ` 68 | } 69 | }); 70 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | REINDEX_URL: 'http://localhost:5000', 3 | }; 4 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reindex React Starter Kit 5 | 6 | 7 | 8 |
9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Relay from 'react-relay'; 4 | 5 | import Reindex from './Reindex'; 6 | 7 | import App from './components/App'; 8 | 9 | Relay.injectNetworkLayer(Reindex.getRelayNetworkLayer()); 10 | 11 | ReactDOM.render( 12 | , 13 | document.getElementById('app') 14 | ); 15 | -------------------------------------------------------------------------------- /src/routes/ProfileRoute.js: -------------------------------------------------------------------------------- 1 | import Relay from 'react-relay'; 2 | 3 | export default class ProfileRoute extends Relay.Route { 4 | static queries = { 5 | viewer: (Component) => Relay.QL` 6 | query { 7 | viewer { 8 | ${Component.getFragment('viewer')} 9 | } 10 | } 11 | `, 12 | }; 13 | static routeName = 'ProfileRoute'; 14 | } 15 | -------------------------------------------------------------------------------- /webpack.local.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | /** 6 | * This is the Webpack configuration file for local development. It contains 7 | * local-specific configuration such as the React Hot Loader, as well as: 8 | * 9 | * - The entry point of the application 10 | * - Where the output file should be 11 | * - Which loaders to use on what files to properly transpile the source 12 | * 13 | * For more information, see: http://webpack.github.io/docs/configuration.html 14 | */ 15 | module.exports = { 16 | // Efficiently evaluate modules with source maps 17 | devtool: 'eval', 18 | 19 | // Set entry point to ./src/main and include necessary files for hot load 20 | entry: ['babel-polyfill', './src/index'], 21 | 22 | // This will not actually create a bundle.js file in ./build. It is used 23 | // by the dev server for dynamic hot loading. 24 | output: { 25 | path: __dirname + '/build/', 26 | filename: 'app.js', 27 | publicPath: '/' 28 | }, 29 | 30 | // Necessary plugins for hot load 31 | plugins: [ 32 | new webpack.HotModuleReplacementPlugin(), 33 | new webpack.NoErrorsPlugin(), 34 | new HtmlWebpackPlugin({ 35 | template: 'src/index.html', 36 | inject: 'body', 37 | }), 38 | ], 39 | 40 | // Transform source code using Babel and React Hot Loader 41 | module: { 42 | loaders: [ 43 | { 44 | test: /\.js$/, 45 | exclude: /node_modules/, 46 | loaders: ['react-hot', 'babel-loader'], 47 | }, 48 | { 49 | test: /\.css$/, 50 | loaders: [ 51 | 'style-loader', 52 | 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader', 53 | ], 54 | }, 55 | 56 | // auth0 lock 57 | { 58 | test: /node_modules[\\\/]auth0-lock[\\\/].*\.js$/, 59 | loaders: [ 60 | 'transform-loader/cacheable?brfs', 61 | 'transform-loader/cacheable?packageify', 62 | ], 63 | }, 64 | { 65 | test: /node_modules[\\\/]auth0-lock[\\\/].*\.ejs$/, 66 | loader: 'transform-loader/cacheable?ejsify', 67 | }, 68 | { 69 | test: /\.json$/, 70 | loader: 'json-loader', 71 | }, 72 | ], 73 | }, 74 | 75 | // Automatically transform files with these extensions 76 | resolve: { 77 | extensions: ['', '.js', '.jsx', '.css'], 78 | }, 79 | 80 | // Additional plugins for CSS post processing using postcss-loader 81 | postcss: [ 82 | require('autoprefixer'), // Automatically include vendor prefixes 83 | require('postcss-nested'), // Enable nested rules, like in Sass 84 | ], 85 | 86 | devServer: { 87 | host: '127.0.0.1', 88 | port: 3000, 89 | historyApiFallback: true, 90 | hot: true, 91 | inline: true, 92 | }, 93 | }; 94 | -------------------------------------------------------------------------------- /webpack.production.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | /** 6 | * This is the Webpack configuration file for production. 7 | */ 8 | module.exports = { 9 | devtool: 'source-map', 10 | 11 | entry: ['babel-polyfill', './src/index'], 12 | 13 | output: { 14 | path: __dirname + '/build/', 15 | filename: 'app.js?[hash]', 16 | }, 17 | 18 | plugins: [ 19 | new ExtractTextPlugin('app.css?[hash]', { allChunks: true }), 20 | new HtmlWebpackPlugin({ 21 | template: 'src/index.html', 22 | inject: 'body', 23 | }), 24 | new webpack.optimize.OccurrenceOrderPlugin(), 25 | new webpack.DefinePlugin({ 26 | 'process.env': { 27 | 'NODE_ENV': JSON.stringify('production'), 28 | }, 29 | }), 30 | new webpack.optimize.UglifyJsPlugin({ 31 | compressor: { 32 | warnings: false 33 | }, 34 | }), 35 | ], 36 | 37 | module: { 38 | loaders: [ 39 | { 40 | test: /\.js$/, 41 | exclude: /node_modules/, 42 | loader: 'babel-loader', 43 | }, 44 | { 45 | test: /\.css$/, 46 | loader: ExtractTextPlugin.extract( 47 | 'style-loader', 48 | 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader' 49 | ), 50 | }, 51 | 52 | // auth0 lock 53 | // auth0 lock 54 | { 55 | test: /node_modules[\\\/]auth0-lock[\\\/].*\.js$/, 56 | loaders: [ 57 | 'transform-loader/cacheable?brfs', 58 | 'transform-loader/cacheable?packageify', 59 | ], 60 | }, 61 | { 62 | test: /node_modules[\\\/]auth0-lock[\\\/].*\.ejs$/, 63 | loader: 'transform-loader/cacheable?ejsify', 64 | }, 65 | { 66 | test: /\.json$/, 67 | loader: 'json-loader', 68 | }, 69 | ], 70 | }, 71 | 72 | resolve: { 73 | extensions: ['', '.js', '.jsx', '.css'], 74 | }, 75 | 76 | postcss: [ 77 | require('autoprefixer'), 78 | require('postcss-nested'), 79 | ], 80 | }; 81 | --------------------------------------------------------------------------------