├── .config
├── webpack.main.config.js
├── webpack.plugins.js
├── webpack.renderer.config.js
└── webpack.rules.js
├── .gitignore
├── README.md
├── package.json
├── src
├── main
│ └── main.ts
└── renderer
│ ├── App.tsx
│ ├── index.html
│ ├── renderer.tsx
│ ├── screens
│ └── Home.tsx
│ ├── store
│ └── store.ts
│ └── theme.ts
├── tsconfig.json
└── yarn.lock
/.config/webpack.main.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const FilterWarningsPlugin = require('webpack-filter-warnings-plugin')
3 | const plugins = require('./webpack.plugins')
4 |
5 | function srcPaths(src) {
6 | return path.join(__dirname, src)
7 | }
8 |
9 | module.exports = {
10 | /**
11 | * This is the main entry point for your application, it's the first file
12 | * that runs in the main process.
13 | */
14 | entry: './src/main/main.ts',
15 | resolve: {
16 | alias: {
17 | '@': srcPaths('src'),
18 | '@main': srcPaths('src/main'),
19 | '@renderer': srcPaths('src/renderer'),
20 | },
21 | extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
22 | },
23 | // Put your normal webpack config below here
24 | module: {
25 | rules: require('./webpack.rules'),
26 | },
27 | plugins: [
28 | // https://typeorm.io/#/faq/how-to-use-webpack-for-the-backend
29 | //ignore the drivers you don't want. This is the complete list of all drivers -- remove the suppressions for drivers you want to use.
30 | new FilterWarningsPlugin({
31 | // prettier-ignore
32 | exclude: [/mongodb/, /mssql/, /mysql/, /mysql2/, /oracledb/, /pg/, /pg-native/, /pg-query-stream/, /redis/, /sqlite3/]
33 | }),
34 | ...plugins,
35 | ],
36 |
37 | // for https://typeorm.io/#/faq/bundling-migration-files
38 | optimization: {
39 | minimize: false,
40 | },
41 | }
42 |
--------------------------------------------------------------------------------
/.config/webpack.plugins.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack')
2 | const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
3 |
4 | module.exports = [
5 | new webpack.DefinePlugin({
6 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
7 | }),
8 | new ForkTsCheckerWebpackPlugin({
9 | async: false,
10 | }),
11 | ]
12 |
--------------------------------------------------------------------------------
/.config/webpack.renderer.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const plugins = require('./webpack.plugins')
3 | const rules = require('./webpack.rules')
4 |
5 | function srcPaths(src) {
6 | return path.join(__dirname, src)
7 | }
8 |
9 | rules.push({
10 | test: /\.css$/,
11 | use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
12 | })
13 |
14 | module.exports = {
15 | resolve: {
16 | alias: {
17 | '@': srcPaths('src'),
18 | '@main': srcPaths('src/main'),
19 | '@renderer': srcPaths('src/renderer'),
20 | },
21 | extensions: ['.js', '.ts', '.jsx', '.tsx', '.css'],
22 | },
23 | // Put your normal webpack config below here
24 | module: {
25 | rules,
26 | },
27 | plugins,
28 | }
29 |
--------------------------------------------------------------------------------
/.config/webpack.rules.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | // Add support for native node modules
3 | {
4 | test: /\.node$/,
5 | use: 'node-loader',
6 | },
7 | {
8 | test: /\.(m?js|node)$/,
9 | parser: { amd: false },
10 | use: {
11 | loader: '@marshallofsound/webpack-asset-relocator-loader',
12 | options: {
13 | outputAssetBase: 'native_modules',
14 | },
15 | },
16 | },
17 | // Put your webpack loader rules in this array. This is where you would put
18 | // your ts-loader configuration for instance:
19 | {
20 | test: /\.tsx?$/,
21 | exclude: /(node_modules|.webpack)/,
22 | loaders: [
23 | {
24 | loader: 'ts-loader',
25 | options: {
26 | transpileOnly: true,
27 | },
28 | },
29 | ],
30 | },
31 | ]
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 | .DS_Store
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # TypeScript cache
43 | *.tsbuildinfo
44 |
45 | # Optional npm cache directory
46 | .npm
47 |
48 | # Optional eslint cache
49 | .eslintcache
50 |
51 | # Optional REPL history
52 | .node_repl_history
53 |
54 | # Output of 'npm pack'
55 | *.tgz
56 |
57 | # Yarn Integrity file
58 | .yarn-integrity
59 |
60 | # dotenv environment variables file
61 | .env
62 | .env.test
63 |
64 | # parcel-bundler cache (https://parceljs.org/)
65 | .cache
66 |
67 | # next.js build output
68 | .next
69 |
70 | # nuxt.js build output
71 | .nuxt
72 |
73 | # vuepress build output
74 | .vuepress/dist
75 |
76 | # Serverless directories
77 | .serverless/
78 |
79 | # FuseBox cache
80 | .fusebox/
81 |
82 | # DynamoDB Local files
83 | .dynamodb/
84 |
85 | # Webpack
86 | .webpack/
87 |
88 | # Electron-Forge
89 | out/
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Electron-Forge + React + TypeScript Boilerplate 🚀
2 |
3 | Based on https://ankitbko.github.io/2019/08/electron-forge-with-react-and-typescript/
4 | So thanks [@ankitbko](https://twitter.com/ankitbko) for this great and easy blog post. 🙏
5 |
6 | ### Features
7 |
8 | - [@emotion/core](https://www.npmjs.com/package/@emotion/core)
9 | - [@mdx-js/react](https://www.npmjs.com/package/@mdx-js/react)
10 | - [@reach/router](https://www.npmjs.com/package/@reach/router)
11 | - [cheerio](https://www.npmjs.com/package/cheerio)
12 | - [computer-name](https://www.npmjs.com/package/computer-name)
13 | - [cuid](https://www.npmjs.com/package/cuid)
14 | - [date-fns](https://www.npmjs.com/package/date-fns)
15 | - [electron-devtools-installer](https://www.npmjs.com/package/electron-devtools-installer)
16 | - [electron-is-dev](https://www.npmjs.com/package/electron-is-dev)
17 | - [electron-squirrel-startup](https://www.npmjs.com/package/electron-squirrel-startup)
18 | - [electron-store](https://www.npmjs.com/package/electron-store)
19 | - [filenamify](https://www.npmjs.com/package/filenamify)
20 | - [lodash](https://www.npmjs.com/package/lodash)
21 | - [node-machine-id](https://www.npmjs.com/package/node-machine-id)
22 | - [portfinder](https://www.npmjs.com/package/portfinder)
23 | - [query-string](https://www.npmjs.com/package/query-string)
24 | - [ramda](https://www.npmjs.com/package/ramda)
25 | - [react-dom](https://www.npmjs.com/package/react-dom)
26 | - [react-sweet-state](https://www.npmjs.com/package/react-sweet-state)
27 | - [react](https://www.npmjs.com/package/react)
28 | - [theme-ui](https://www.npmjs.com/package/theme-ui) waiting for [#423](https://github.com/system-ui/theme-ui/issues/423)
29 | - [typeorm](https://www.npmjs.com/package/typeorm)
30 | - [sqlite3](https://www.npmjs.com/package/sqlite3)
31 |
32 | ### Inspiration
33 |
34 | - https://github.com/sindresorhus/tsconfig/blob/master/tsconfig.json
35 | - https://github.com/LekoArts/gatsby-themes/blob/master/tsconfig.json
36 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-forge-react-typescript-boilerplate",
3 | "productname": "electron-forge-react-typescript-boilerplate",
4 | "version": "1.0.0",
5 | "description": "My Electron application description",
6 | "main": ".webpack/main",
7 | "scripts": {
8 | "start": "electron-forge start",
9 | "package": "electron-forge package",
10 | "make": "electron-forge make",
11 | "publish": "electron-forge publish",
12 | "lint": "echo \"No linting configured\""
13 | },
14 | "keywords": [],
15 | "author": {
16 | "name": "CanRau",
17 | "email": "cansrau@gmail.com",
18 | "url": "https://www.canrau.com"
19 | },
20 | "license": "MIT",
21 | "config": {
22 | "forge": {
23 | "packagerConfig": {},
24 | "makers": [
25 | {
26 | "name": "@electron-forge/maker-squirrel",
27 | "config": {
28 | "name": "desktop_electron_forge"
29 | }
30 | },
31 | {
32 | "name": "@electron-forge/maker-zip",
33 | "platforms": [
34 | "darwin"
35 | ]
36 | },
37 | {
38 | "name": "@electron-forge/maker-deb",
39 | "config": {}
40 | },
41 | {
42 | "name": "@electron-forge/maker-rpm",
43 | "config": {}
44 | }
45 | ],
46 | "plugins": [
47 | [
48 | "@electron-forge/plugin-webpack",
49 | {
50 | "mainConfig": ".config/webpack.main.config.js",
51 | "renderer": {
52 | "config": ".config/webpack.renderer.config.js",
53 | "entryPoints": [
54 | {
55 | "html": "./src/renderer/index.html",
56 | "js": "./src/renderer/renderer.tsx",
57 | "name": "main_window"
58 | }
59 | ]
60 | }
61 | }
62 | ]
63 | ]
64 | }
65 | },
66 | "dependencies": {
67 | "@emotion/core": "^10.0.21",
68 | "@mdx-js/react": "^1.5.1",
69 | "@reach/router": "^1.2.1",
70 | "@types/cuid": "^1.3.0",
71 | "@types/lodash": "^4.14.144",
72 | "@types/node": "^12.11.7",
73 | "@types/ramda": "^0.26.33",
74 | "@types/reach__router": "^1.2.6",
75 | "@types/react": "^16.9.10",
76 | "@types/react-dom": "^16.9.2",
77 | "@types/theme-ui": "^0.2.3",
78 | "cheerio": "^1.0.0-rc.3",
79 | "computer-name": "^0.1.0",
80 | "cuid": "^2.1.6",
81 | "date-fns": "^2.5.0",
82 | "electron-devtools-installer": "^2.2.4",
83 | "electron-is-dev": "^1.1.0",
84 | "electron-squirrel-startup": "^1.0.0",
85 | "electron-store": "^5.0.0",
86 | "filenamify": "^4.1.0",
87 | "lodash": "^4.17.19",
88 | "node-machine-id": "^1.1.12",
89 | "portfinder": "^1.0.25",
90 | "query-string": "^6.8.3",
91 | "ramda": "^0.26.1",
92 | "react": "^16.11.0",
93 | "react-dom": "^16.11.0",
94 | "react-sweet-state": "^1.1.1",
95 | "reflect-metadata": "^0.1.13",
96 | "sqlite3": "^4.1.0",
97 | "theme-ui": "^0.2.44",
98 | "typeorm": "^0.2.20"
99 | },
100 | "devDependencies": {
101 | "@electron-forge/cli": "6.0.0-beta.45",
102 | "@electron-forge/maker-deb": "6.0.0-beta.45",
103 | "@electron-forge/maker-rpm": "6.0.0-beta.45",
104 | "@electron-forge/maker-squirrel": "6.0.0-beta.45",
105 | "@electron-forge/maker-zip": "6.0.0-beta.45",
106 | "@electron-forge/plugin-webpack": "6.0.0-beta.45",
107 | "@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
108 | "css-loader": "^3.0.0",
109 | "electron": "7.2.4",
110 | "node-loader": "^0.6.0",
111 | "style-loader": "^0.23.1",
112 | "webpack-filter-warnings-plugin": "^1.2.1"
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/main.ts:
--------------------------------------------------------------------------------
1 | import { app, BrowserWindow } from 'electron'
2 | declare var MAIN_WINDOW_WEBPACK_ENTRY: any
3 |
4 | // Handle creating/removing shortcuts on Windows when installing/uninstalling.
5 | if (require('electron-squirrel-startup')) {
6 | // eslint-disable-line global-require
7 | app.quit()
8 | }
9 |
10 | // Keep a global reference of the window object, if you don't, the window will
11 | // be closed automatically when the JavaScript object is garbage collected.
12 | let mainWindow: any
13 |
14 | const createWindow = () => {
15 | // Create the browser window.
16 | mainWindow = new BrowserWindow({
17 | width: 800,
18 | height: 600,
19 | })
20 |
21 | // and load the index.html of the app.
22 | mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY)
23 |
24 | // Open the DevTools.
25 | mainWindow.webContents.openDevTools()
26 |
27 | // Emitted when the window is closed.
28 | mainWindow.on('closed', () => {
29 | // Dereference the window object, usually you would store windows
30 | // in an array if your app supports multi windows, this is the time
31 | // when you should delete the corresponding element.
32 | mainWindow = null
33 | })
34 | }
35 |
36 | // This method will be called when Electron has finished
37 | // initialization and is ready to create browser windows.
38 | // Some APIs can only be used after this event occurs.
39 | app.on('ready', createWindow)
40 |
41 | // Quit when all windows are closed.
42 | app.on('window-all-closed', () => {
43 | // On OS X it is common for applications and their menu bar
44 | // to stay active until the user quits explicitly with Cmd + Q
45 | if (process.platform !== 'darwin') {
46 | app.quit()
47 | }
48 | })
49 |
50 | app.on('activate', () => {
51 | // On OS X it's common to re-create a window in the app when the
52 | // dock icon is clicked and there are no other windows open.
53 | if (mainWindow === null) {
54 | createWindow()
55 | }
56 | })
57 |
--------------------------------------------------------------------------------
/src/renderer/App.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { ThemeProvider } from 'theme-ui'
3 | import {
4 | Router,
5 | Link,
6 | createMemorySource,
7 | createHistory,
8 | LocationProvider,
9 | RouteComponentProps,
10 | } from '@reach/router'
11 | import Home from './screens/Home'
12 | import theme from './theme'
13 |
14 | const source = createMemorySource('/')
15 | const history = createHistory(source)
16 |
17 | export const App = () => {
18 | return (
19 |