├── .babelrc
├── .eslintrc.json
├── .gitignore
├── LICENSE
├── README.md
├── app
├── build
│ ├── .gitignore
│ └── README.md
└── src
│ └── main
│ ├── app.js
│ ├── index.html
│ ├── js
│ ├── actions
│ │ └── list_actions.js
│ ├── app.js
│ ├── components
│ │ ├── header.js
│ │ ├── home.js
│ │ ├── list_item_preview.js
│ │ ├── list_item_view.js
│ │ └── list_items.js
│ ├── consts
│ │ ├── action_types.js
│ │ ├── default_state.js
│ │ └── list_items.js
│ ├── containers
│ │ ├── list_item_preview.js
│ │ ├── list_item_view.js
│ │ └── list_items.js
│ ├── index.js
│ └── reducers
│ │ ├── index.js
│ │ └── list.js
│ └── res
│ ├── images
│ └── logo.png
│ └── scss
│ ├── home.scss
│ ├── main.scss
│ ├── palette.scss
│ └── view_item.scss
├── package-lock.json
├── package.json
└── webpack
├── dev.config.js
└── prod.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["es2015", { "modules": false }],
4 | "react",
5 | "stage-1"
6 | ]
7 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "env": {
4 | "es6": true,
5 | "node": true,
6 | "browser": true
7 | },
8 | "plugins": [
9 | "react",
10 | "jsx-a11y",
11 | "import"
12 | ],
13 | "parserOptions": {
14 | "ecmaFeatures": {
15 | "experimentalObjectRestSpread": true,
16 | "jsx": true
17 | },
18 | "sourceType": "module",
19 | "indent": ["error", 2]
20 | },
21 | "rules": {
22 | "react/sort-comp": [1, {
23 | "order": [
24 | "constructor",
25 | "lifecycle",
26 | "everything-else",
27 | "render"
28 | ]
29 | }],
30 | "react/jsx-filename-extension": [1, {
31 | "extensions": [".js", ".jsx"]
32 | }],
33 | "jsx-a11y/no-static-element-interactions": 0,
34 | "jsx-a11y/no-noninteractive-element-interactions": 0,
35 | "jsx-a11y/href-no-hash": "off",
36 | "import/no-dynamic-require": 0,
37 | "import/no-extraneous-dependencies": "off",
38 | "linebreak-style": ["error", "unix"],
39 | "react/forbid-prop-types": 0,
40 | "react/require-default-props": 0,
41 | "function-paren-newline": ["error", "consistent"],
42 | "jsx-a11y/anchor-is-valid": [ "error", {
43 | "components": [ "Link" ],
44 | "specialLink": [ "to" ],
45 | "aspects": ["invalidHref"]
46 | }]
47 | },
48 | "settings": {
49 | "import/resolver": {
50 | "webpack": {
51 | "config": "./webpack/dev.config.js"
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .vscode
3 | yarn.lock
4 | release
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Tahnik Mustasin
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ElectronJS + ReactJS boilerplate
2 |
3 | A simple and clean boilerplate for Electron and react. It includes:
4 |
5 | - State management with [Redux]
6 | - Routing with [React-Router v4]
7 | - [React] and [Redux devtools] for debugging
8 | - .eslint for [ESlint]
9 | - [Webpack 3] for bundling
10 | - [Babel] for compiling
11 |
12 | ## Usage
13 |
14 | NodeJS v8.3.0
15 |
16 | - Clone the repo
17 | `git clone https://github.com/tahnik/electron-react.git`
18 | - Edit the package.json to change the `name` to your project name and `description` to your project description. Change the `author` as well.
19 | - Run `npm i`
20 | - Then run the project as described in the section below
21 |
22 | ## How to
23 | - To run in development mode with hot reloading, open a terminal inside your project and run
24 | ```bash
25 | npm run dev
26 | ```
27 |
28 | This commands creates a webpack dev server which will watch and reload the bundle as you edit and will it available at https://localhost:8080.
29 | The command will also run the electron app in development mode. So it will open up devtools with React and Redux devtools initialized.
30 | - To build the app and test if it is working:
31 |
32 | ```bash
33 | npm start
34 | ```
35 |
36 | This command will compile the app in production mode and start the app. Here is you still toggle the developer tools from the menu and see if there is any errors
37 |
38 | - To package the app and create a distributable:
39 |
40 | ```bash
41 | npm run dist
42 | ```
43 |
44 | This will create a relevant distributable file. For example, if you are on Windows, it will create a .exe file in the release folder.
45 |
46 |
47 | # Contribute
48 | Awesome! Create a new issue or do a pull request.
49 |
50 |
51 | [Redux]:
52 | [React-Router v4]:
53 | [React]:
54 | [Redux devtools]:
55 | [Jest]:
56 | [ESlint]:
57 | [Webpack 3]:
58 | [Babel]:
59 | [Yeoman]:
60 |
61 |
62 |
--------------------------------------------------------------------------------
/app/build/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
5 | !README.md
--------------------------------------------------------------------------------
/app/build/README.md:
--------------------------------------------------------------------------------
1 | All the build files will be here
--------------------------------------------------------------------------------
/app/src/main/app.js:
--------------------------------------------------------------------------------
1 | const electron = require('electron');
2 | // Module to control application life.
3 | const { app } = electron;
4 | // Module to create native browser window.
5 | const { BrowserWindow } = electron;
6 |
7 | const path = require('path');
8 | const url = require('url');
9 |
10 |
11 | // Keep a global reference of the window object, if you don't, the window will
12 | // be closed automatically when the JavaScript object is garbage collected.
13 | let mainWindow;
14 |
15 | /** This function will create the mainWindow */
16 | function createWindow() {
17 | // Create the browser window.
18 | mainWindow = new BrowserWindow({ width: 1366, height: 768 });
19 |
20 | // and load the index.html of the app.
21 | mainWindow.loadURL(url.format({
22 | pathname: path.join(__dirname, 'index.html'),
23 | protocol: 'file:',
24 | slashes: true,
25 | }));
26 |
27 | if (process.env.NODE_ENV === 'development') {
28 | // Open the DevTools.
29 | mainWindow.webContents.openDevTools();
30 | const {
31 | default: installExtension,
32 | REACT_DEVELOPER_TOOLS,
33 | REDUX_DEVTOOLS,
34 | } = require('electron-devtools-installer'); // eslint-disable-line
35 | installExtension(REACT_DEVELOPER_TOOLS)
36 | .then(name => console.log(`Added Extension: ${name}`))
37 | .catch(err => console.log('An error occurred: ', err));
38 |
39 | installExtension(REDUX_DEVTOOLS)
40 | .then(name => console.log(`Added Extension: ${name}`))
41 | .catch(err => console.log('An error occurred: ', err));
42 | }
43 |
44 | // Emitted when the window is closed.
45 | mainWindow.on('closed', () => {
46 | // Dereference the window object, usually you would store windows
47 | // in an array if your app supports multi windows, this is the time
48 | // when you should delete the corresponding element.
49 | mainWindow = null;
50 | });
51 | }
52 |
53 | // This method will be called when Electron has finished
54 | // initialization and is ready to create browser windows.
55 | // Some APIs can only be used after this event occurs.
56 | app.on('ready', createWindow);
57 |
58 | // Quit when all windows are closed.
59 | app.on('window-all-closed', () => {
60 | // On OS X it is common for applications and their menu bar
61 | // to stay active until the user quits explicitly with Cmd + Q
62 | if (process.platform !== 'darwin') {
63 | app.quit();
64 | }
65 | });
66 |
67 | app.on('activate', () => {
68 | // On OS X it's common to re-create a window in the app when the
69 | // dock icon is clicked and there are no other windows open.
70 | if (mainWindow === null) {
71 | createWindow();
72 | }
73 | });
74 |
75 | // In this file you can include the rest of your app's specific main process
76 | // code. You can also put them in separate files and require them here.
77 |
--------------------------------------------------------------------------------
/app/src/main/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | React Router Redux
10 |
11 |
12 |
13 |
14 |
36 |
42 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/js/actions/list_actions.js:
--------------------------------------------------------------------------------
1 | import { LIST_ACTIONS } from '../consts/action_types';
2 |
3 | export const previewItem = name => ({
4 | type: LIST_ACTIONS.ITEM_PREVIEW,
5 | name, // shorthand for name: name
6 | });
7 |
8 | export const viewItem = name => ({
9 | type: LIST_ACTIONS.ITEM_VIEW,
10 | name,
11 | });
12 |
13 | export const addItem = item => ({
14 | type: LIST_ACTIONS.ITEM_ADD,
15 | item, // shorthand for item: item
16 | });
17 |
18 | export const clearItem = () => ({
19 | type: LIST_ACTIONS.ITEM_CLEAR,
20 | });
21 |
--------------------------------------------------------------------------------
/app/src/main/js/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route } from 'react-router-dom';
3 | import Header from './components/header';
4 | import Home from './components/home';
5 | import ItemView from './containers/list_item_view';
6 |
7 | const App = () => (
8 |