├── public
├── favicon.ico
├── index.html
└── electron.js
├── src
├── index.css
├── components
│ ├── Home
│ │ ├── Home.css
│ │ ├── Home.test.js
│ │ └── Home.js
│ ├── About
│ │ ├── About.css
│ │ ├── About.test.js
│ │ └── About.js
│ └── Header
│ │ ├── Header.test.js
│ │ ├── Header.css
│ │ ├── Header.js
│ │ └── logo.svg
└── index.js
├── .gitignore
├── README.md
└── package.json
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mcmunder/electron-create-react-app/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | text-align: center;
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Home/Home.css:
--------------------------------------------------------------------------------
1 | .link-container {
2 | margin-top: 50px;
3 | }
4 |
5 | .link {
6 | padding: 10px;
7 | border: 1px solid black;
8 | border-radius: 3px;
9 | color: black;
10 | text-decoration: none;
11 | }
12 |
--------------------------------------------------------------------------------
/src/components/About/About.css:
--------------------------------------------------------------------------------
1 | .link-container {
2 | margin-top: 50px;
3 | }
4 |
5 | .link {
6 | padding: 10px;
7 | border: 1px solid black;
8 | border-radius: 3px;
9 | color: black;
10 | text-decoration: none;
11 | }
12 |
--------------------------------------------------------------------------------
/src/components/Header/Header.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import Header from './Header'
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div')
7 | ReactDOM.render(, div)
8 | })
9 |
--------------------------------------------------------------------------------
/src/components/Header/Header.css:
--------------------------------------------------------------------------------
1 | .logo {
2 | animation: logo infinite 20s linear;
3 | height: 80px;
4 | }
5 |
6 | .header {
7 | background-color: #222;
8 | height: 150px;
9 | padding: 20px;
10 | color: white;
11 | }
12 |
13 | @keyframes logo {
14 | from { transform: rotate(0deg); }
15 | to { transform: rotate(360deg); }
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/Header/Header.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import logo from './logo.svg'
3 | import './Header.css'
4 |
5 | const Header = props => {
6 | return (
7 |
8 |

9 |
{props.headerText}
10 |
11 | )
12 | }
13 |
14 | export default Header
15 |
--------------------------------------------------------------------------------
/src/components/About/About.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import {MemoryRouter} from 'react-router-dom'
4 | import About from './About'
5 |
6 | it('renders without crashing', () => {
7 | const div = document.createElement('div')
8 | ReactDOM.render(
9 |
10 |
11 | ,
12 | div
13 | )
14 | })
15 |
--------------------------------------------------------------------------------
/src/components/Home/Home.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import {MemoryRouter} from 'react-router-dom'
4 | import Home from './Home'
5 |
6 | it('renders without crashing', () => {
7 | const div = document.createElement('div')
8 |
9 | ReactDOM.render(
10 |
11 |
12 | ,
13 | div
14 | )
15 | })
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 |
13 | # misc
14 | .DS_Store
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 | .idea
24 |
--------------------------------------------------------------------------------
/src/components/Home/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import Header from '../Header/Header'
4 | import './Home.css'
5 |
6 | const Home = props => (
7 |
8 |
9 |
10 |
13 | Go to About
14 |
15 |
16 |
17 | )
18 |
19 | export default Home
20 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import Home from './components/Home/Home'
4 | import About from './components/About/About'
5 | import {HashRouter as Router, Route} from 'react-router-dom'
6 | import './index.css'
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 |
13 |
14 | ,
15 | document.getElementById('root')
16 | )
17 |
--------------------------------------------------------------------------------
/src/components/About/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Link} from 'react-router-dom'
3 | import Header from '../Header/Header'
4 | import './About.css'
5 |
6 | const About = props => {
7 | return (
8 |
9 |
10 |
11 |
14 | Go to Home
15 |
16 |
17 |
18 | )
19 | }
20 |
21 | export default About
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # electron-create-react-app
2 |
3 | Boilerplate linking [electron](http://electron.atom.io/) with [create-react-app](https://github.com/facebookincubator/create-react-app).
4 |
5 | **Many things were shamelessly copied from
6 | [here](https://github.com/kitze/react-electron-example). See [this article](https://medium.com/@kitze/%EF%B8%8F-from-react-to-an-electron-app-ready-for-production-a0468ecb1da3)
7 | for very good background information.**
8 |
9 | ## Usage
10 |
11 | Run tests:
12 |
13 | ```bash
14 | npm test
15 | ```
16 |
17 | Run in dev mode:
18 |
19 | ```bash
20 | npm run electron-dev
21 | ```
22 |
23 | Build:
24 |
25 | ```bash
26 | npm run build
27 | ```
28 |
29 | Package:
30 |
31 | ```bash
32 | npm run electron-pack
33 | ```
34 |
35 | ## Copyright and license
36 |
37 | Copyright 2017, Matthias Munder.
38 | Licensed under the [MIT license](./LICENSE).
39 |
40 | [](https://github.com/feross/standard)
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-create-react-app",
3 | "description": "Boilerplate linking electron and create-react-app",
4 | "version": "0.1.0",
5 | "private": true,
6 | "author": {
7 | "name": "mcmunder",
8 | "email": "matthiasmunder@gmail.com",
9 | "url": "https://mcmunder.de"
10 | },
11 | "dependencies": {
12 | "cross-env": "5.1.3",
13 | "electron-is-dev": "0.3.0",
14 | "react": "16.2.0",
15 | "react-dom": "16.2.0",
16 | "react-router-dom": "^4.2.2"
17 | },
18 | "devDependencies": {
19 | "chalk": "^2.3.1",
20 | "concurrently": "3.5.1",
21 | "electron": "1.8.2",
22 | "electron-builder": "20.2.0",
23 | "electron-devtools-installer": "^2.2.3",
24 | "react-scripts": "1.1.1",
25 | "wait-on": "2.1.0"
26 | },
27 | "main": "public/electron.js",
28 | "homepage": "./",
29 | "build": {
30 | "appId": "com.example.electron-create-react-app"
31 | },
32 | "scripts": {
33 | "start": "react-scripts start",
34 | "debug": "npm run electron-dev -- --inspect=5858",
35 | "build": "react-scripts build",
36 | "test": "react-scripts test --env=jsdom",
37 | "eject": "react-scripts eject",
38 | "electron-dev":
39 | "concurrently \"cross-env BROWSER=none npm start\" \"wait-on http://localhost:3000 && electron .\"",
40 | "electron-pack": "build -- --em.main=build/electron.js",
41 | "preelectron-pack": "npm run build"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/public/electron.js:
--------------------------------------------------------------------------------
1 | const electron = require('electron')
2 | const path = require('path')
3 | const url = require('url')
4 | const isDev = require('electron-is-dev')
5 | const chalk = require('chalk')
6 | const installExtension = require('electron-devtools-installer').default
7 | const {
8 | REACT_DEVELOPER_TOOLS,
9 | REDUX_DEVTOOLS
10 | } = require('electron-devtools-installer')
11 |
12 | const app = electron.app
13 | const BrowserWindow = electron.BrowserWindow
14 |
15 | // Keep a global reference of the window object, if you don't, the window will
16 | // be closed automatically when the JavaScript object is garbage collected.
17 | let mainWindow
18 |
19 | const createWindow = () => {
20 | mainWindow = new BrowserWindow({width: 900, height: 680})
21 |
22 | mainWindow.loadURL(
23 | isDev
24 | ? 'http://localhost:3000'
25 | : `file://${path.join(__dirname, '../build/index.html')}`
26 | )
27 |
28 | if (isDev) {
29 | mainWindow.webContents.openDevTools()
30 | }
31 |
32 | mainWindow.on('closed', () => {
33 | // Dereference the window object, usually you would store windows
34 | // in an array if your app supports multi windows, this is the time
35 | // when you should delete the corresponding element.
36 | mainWindow = null
37 | })
38 | }
39 |
40 | const installExtensions = async () => {
41 | try {
42 | const extensions = {
43 | REACT_DEVELOPER_TOOLS: REACT_DEVELOPER_TOOLS,
44 | REDUX_DEVTOOLS: REACT_DEVELOPER_TOOLS
45 | }
46 |
47 | await Object.keys(extensions).forEach(extensionName => {
48 | installExtension(extensions[extensionName])
49 | console.log(chalk.green(`Added Extension: ${extensionName}`))
50 | })
51 |
52 | console.log(chalk.green('All extensions installed successfully!'))
53 | createWindow()
54 | } catch (err) {
55 | console.log(chalk.red(err))
56 | }
57 | }
58 |
59 | app.on('ready', isDev ? installExtensions : createWindow)
60 |
61 | app.on('window-all-closed', () => {
62 | if (process.platform !== 'darwin') {
63 | app.quit()
64 | }
65 | })
66 |
67 | app.on('activate', () => {
68 | if (mainWindow === null) {
69 | createWindow()
70 | }
71 | })
72 |
--------------------------------------------------------------------------------
/src/components/Header/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------