Initial commit — Electron + React frontend, Express/Docker backend, members & project management

This commit is contained in:
Ryan Lancaster
2026-03-15 13:40:01 -07:00
commit a3949c32ee
24 changed files with 12583 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const fs = require('fs')
const isDev = process.env.NODE_ENV !== 'production'
const devUrl = 'http://localhost:5173'
let mainWindow
function getStoragePath() {
return path.join(app.getPath('userData'), 'storage.json')
}
function readStorage() {
try {
const p = getStoragePath()
if (!fs.existsSync(p)) return {}
const raw = fs.readFileSync(p, 'utf8') || '{}'
return JSON.parse(raw)
} catch (e) {
return {}
}
}
function writeStorage(obj) {
try {
fs.mkdirSync(path.dirname(getStoragePath()), { recursive: true })
fs.writeFileSync(getStoragePath(), JSON.stringify(obj, null, 2), 'utf8')
return true
} catch (e) {
return false
}
}
ipcMain.handle('storage-get', () => {
const s = readStorage()
return s
})
ipcMain.handle('storage-set', (event, key, value) => {
const s = readStorage()
s[key] = value
writeStorage(s)
return true
})
ipcMain.handle('storage-remove', (event, key) => {
const s = readStorage()
delete s[key]
writeStorage(s)
return true
})
ipcMain.handle('get-api-url', () => process.env.VITE_API_URL || 'http://localhost:4000/api')
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
preload: path.join(__dirname, 'preload.cjs'),
contextIsolation: true,
nodeIntegration: false
}
})
if (isDev) {
mainWindow.loadURL(devUrl)
mainWindow.webContents.openDevTools()
} else {
mainWindow.loadFile(path.join(__dirname, '..', 'dist', 'index.html'))
}
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})

View File

@@ -0,0 +1,14 @@
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('ENV', {
API_URL: process.env.VITE_API_URL || 'http://localhost:4000/api'
})
contextBridge.exposeInMainWorld('app', {
storage: {
get: (key) => ipcRenderer.invoke('storage-get', key),
set: (key, value) => ipcRenderer.invoke('storage-set', key, value),
remove: (key) => ipcRenderer.invoke('storage-remove', key)
},
getAPIUrl: () => ipcRenderer.invoke('get-api-url')
})