`
758 | - Three columns: `
`
759 |
760 | ### Removing a Page
761 |
762 | 1. Remove item from `src/config/navigation.tsx`
763 | 2. Remove page from `src/components/PageRouter.tsx`
764 | 3. Delete page file from `src/pages/`
765 |
766 | The navigation system is fully type-safe - TypeScript will error if page IDs don't match.
767 |
768 | ### Advanced: Multi-Level Navigation
769 |
770 | For complex apps needing sub-navigation:
771 |
772 | 1. **Option A**: Use tabs within a page (shadcn/ui Tabs component)
773 | 2. **Option B**: Create nested context with sub-routes
774 | 3. **Option C**: Use state-based views within a single page
775 |
776 | **Example with Tabs:**
777 |
778 | ```typescript
779 | import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
780 |
781 | export function SettingsPage() {
782 | return (
783 |
784 |
785 | General
786 | Appearance
787 | Advanced
788 |
789 |
790 | {/* General settings */}
791 | {/* Appearance settings */}
792 | {/* Advanced settings */}
793 |
794 | )
795 | }
796 | ```
797 |
798 | ## Testing Strategy
799 |
800 | **Framework**: Vitest + React Testing Library
801 |
802 | **Test Location**: `src/test/`
803 |
804 | **Setup**: `src/test/setup.ts` - Global test configuration and mocks
805 |
806 | **Running Tests**:
807 | - `npm test` - Run all tests
808 | - `npm run test:ui` - Visual test runner
809 | - `npx vitest path/to/test.tsx` - Run specific test
810 |
811 | **Mocking Electron APIs**:
812 | ```typescript
813 | global.window.electron = {
814 | yourMethod: async () => ({ success: true, data: mockData })
815 | }
816 | ```
817 |
818 | **Best Practices**:
819 | - Test user interactions, not implementation details
820 | - Mock IPC calls in tests
821 | - Use `screen.getByRole` over `getByTestId`
822 | - Test error states and loading states
823 |
824 | ## Code Quality
825 |
826 | ### ESLint Configuration
827 |
828 | **Config**: `.eslintrc.json`
829 |
830 | **Rules**:
831 | - React hooks rules enforced
832 | - TypeScript recommended rules
833 | - No unused variables (warn)
834 | - Compatible with Prettier
835 |
836 | **Custom Rules**:
837 | - `react/react-in-jsx-scope`: off (React 18 auto-import)
838 | - Unused vars with `_` prefix are allowed
839 |
840 | ### Prettier Configuration
841 |
842 | **Config**: `.prettierrc`
843 |
844 | **Format**:
845 | - No semicolons
846 | - Single quotes
847 | - 2 space indentation
848 | - 100 character line width
849 | - ES5 trailing commas
850 |
851 | ### TypeScript
852 |
853 | **Config**: `tsconfig.json`
854 |
855 | **Path Aliases**:
856 | - `@/*` → `src/*`
857 | - `@main/*` → `electron/main/*`
858 | - `@preload/*` → `electron/preload/*`
859 |
860 | **Strict Mode**: Enabled for maximum type safety
861 |
862 | **When adding new paths**: Update `tsconfig.json`, `vite.config.ts`, and `vitest.config.ts`
863 |
864 | ## File Organization
865 |
866 | ### When Creating New Features
867 |
868 | 1. **Pages**: `src/pages/FeatureNamePage.tsx` (see Navigation System section)
869 | 2. **Navigation**: Add to `src/config/navigation.tsx` and `src/components/PageRouter.tsx`
870 | 3. **React Components**: `src/components/[feature]/ComponentName.tsx`
871 | 4. **UI Components**: `src/components/ui/` (via shadcn CLI)
872 | 5. **Redux Slices**: `src/store/slices/featureName.ts`
873 | 6. **IPC Handlers**: Add to `electron/main/ipc-handlers.ts` or create feature-specific file
874 | 7. **Types**: `electron/shared/types.ts` for IPC, inline for component-specific
875 | 8. **Tests**: `src/test/[feature]/ComponentName.test.tsx`
876 | 9. **Database Schema**: Define in `electron/main/schema.ts`, generate migrations with `npm run db:generate`
877 |
878 | ### Naming Conventions
879 |
880 | - **Components**: PascalCase (`UserProfile.tsx`)
881 | - **Utilities**: camelCase (`formatDate.ts`)
882 | - **Constants**: UPPER_SNAKE_CASE (`MAX_RETRY_COUNT`)
883 | - **IPC Channels**: `category:action` (`db:getUsers`, `app:quit`)
884 | - **Redux Actions**: `feature/actionName` (auto-generated by createSlice)
885 |
886 | ## Common Patterns
887 |
888 | ### Loading States with Redux
889 |
890 | ```typescript
891 | const [loading, setLoading] = useState(false)
892 | const response = await window.electron.fetchData()
893 | if (response.success) {
894 | dispatch(setData(response.data))
895 | }
896 | ```
897 |
898 | ### Error Handling
899 |
900 | ```typescript
901 | const response = await window.electron.riskyOperation()
902 | if (!response.success) {
903 | console.error(response.error)
904 | // Show user-friendly error
905 | toast({ title: 'Error', description: response.error })
906 | }
907 | ```
908 |
909 | ### Environment-Specific Code
910 |
911 | ```typescript
912 | // Development only
913 | if (VITE_DEV_SERVER_URL) {
914 | mainWindow.webContents.openDevTools()
915 | }
916 |
917 | // Production only
918 | if (!VITE_DEV_SERVER_URL) {
919 | // Production-specific logic
920 | }
921 | ```
922 |
923 | ### Accessing Main Process from Renderer
924 |
925 | **Never** try to `require('electron')` in renderer. Always use the exposed API:
926 |
927 | ```typescript
928 | // ❌ Wrong
929 | const { ipcRenderer } = require('electron')
930 |
931 | // ✅ Correct
932 | const result = await window.electron.yourMethod()
933 | ```
934 |
935 | ## Security Considerations
936 |
937 | 1. **Context Isolation**: Always enabled - don't disable it
938 | 2. **Node Integration**: Disabled in renderer - don't enable it
939 | 3. **IPC Validation**: Always validate renderer input in main process handlers
940 | 4. **External URLs**: Use `shell.openExternal()`, not `window.open()`
941 | 5. **Content Security Policy**: Consider adding CSP headers for production
942 | 6. **Sensitive Data**: Never log sensitive data; store securely using OS keychain
943 |
944 | ## Build & Distribution
945 |
946 | ### Build Process
947 |
948 | 1. TypeScript compiles to JavaScript
949 | 2. Vite bundles renderer process
950 | 3. electron-builder packages app with native modules
951 | 4. Output in `release/{version}/`
952 |
953 | ### Platform-Specific Builds
954 |
955 | - **macOS**: .dmg (installer), .zip (portable)
956 | - **Windows**: .exe (NSIS installer), .zip (portable)
957 | - **Linux**: .AppImage (universal), .deb (Debian/Ubuntu)
958 |
959 | ### Auto-Updater
960 |
961 | **Not included** in boilerplate. To add:
962 | 1. Install `electron-updater`
963 | 2. Configure in `electron/main/index.ts`
964 | 3. Set up update server or use GitHub releases
965 | 4. Add update checks in app lifecycle
966 |
967 | ## Troubleshooting
968 |
969 | ### Hot Reload Not Working
970 |
971 | - Check Vite dev server is running on port 5173
972 | - Restart dev server: `npm run dev`
973 | - Clear dist folders: `rm -rf dist dist-electron`
974 |
975 | ### IPC Not Working
976 |
977 | - Check channel name matches in handler, preload, and types
978 | - Verify handler is registered in `setupIPC()`
979 | - Check preload script is loaded: `console.log(window.electron)`
980 | - Ensure context isolation is enabled
981 |
982 | ### Database Errors
983 |
984 | - **Migration fails**: Check `drizzle/` folder for generated SQL, ensure schema.ts is valid
985 | - **Schema mismatch**: Run `npm run db:generate` to create new migration
986 | - **Reset database**: Delete `data/dev.db*` and restart app (migrations will recreate schema)
987 | - **Production database location**: `app.getPath('userData')/database.db`
988 | - **View database**: Run `npm run db:studio` to open Drizzle Studio GUI
989 |
990 | ### Build Errors
991 |
992 | - Clear caches: `rm -rf dist dist-electron node_modules/.vite`
993 | - Reinstall: `rm -rf node_modules && npm install`
994 | - Check native module compatibility with Electron version
995 |
996 | ### Native Module Errors
997 |
998 | If you encounter errors related to native modules (like `better-sqlite3`), especially after upgrading Electron:
999 |
1000 | - **Automatic rebuild**: The `postinstall` script automatically rebuilds native modules after `npm install`
1001 | - **Manual rebuild**: Run `npm run rebuild` to rebuild native modules for your current Electron version
1002 | - **Fresh install**: If problems persist, delete `node_modules` and run `npm install` again
1003 |
1004 | **Note**: This boilerplate includes `@electron/rebuild` which automatically handles native module compatibility across different Electron versions.
1005 |
1006 | ### Window Not Appearing
1007 |
1008 | - Check `windowStateManager.getState()` returns valid bounds
1009 | - Verify display is connected if using saved position
1010 | - Check console for errors in main process
1011 |
1012 | ## Deployment Checklist
1013 |
1014 | Before deploying new versions based on this boilerplate:
1015 |
1016 | 1. Update version in `package.json`
1017 | 2. Update app name and ID in `package.json` build config
1018 | 3. Replace placeholder icons with your app icons
1019 | 4. Remove example code from `App.tsx`
1020 | 5. Update database schema for your needs
1021 | 6. Configure production database connection
1022 | 7. Add error tracking (Sentry, etc.)
1023 | 8. Test build on all target platforms
1024 | 9. Set up code signing for macOS and Windows
1025 | 10. Configure auto-updater if needed
1026 |
1027 | ## Additional Resources
1028 |
1029 | - Check README.md for user-facing documentation
1030 | - See inline code comments for implementation details
1031 | - Refer to official docs for Electron, React, Vite, Redux, Prisma
1032 |
--------------------------------------------------------------------------------