├── .gitignore
├── chat.png
├── .DS_Store
├── assets
├── icon.ico
├── icon.png
└── icon.icns
├── settings.json
├── .github
└── workflows
│ ├── main.yml
│ ├── flow1
│ └── static.yml
├── preload.js
├── README.md
├── Index.html
├── package.json
├── forge.config.js
├── main.js
├── home.html
├── styles.css
└── script.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 |
3 | /out
--------------------------------------------------------------------------------
/chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TopMyster/IsleBrowser/HEAD/chat.png
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TopMyster/IsleBrowser/HEAD/.DS_Store
--------------------------------------------------------------------------------
/assets/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TopMyster/IsleBrowser/HEAD/assets/icon.ico
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TopMyster/IsleBrowser/HEAD/assets/icon.png
--------------------------------------------------------------------------------
/assets/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TopMyster/IsleBrowser/HEAD/assets/icon.icns
--------------------------------------------------------------------------------
/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "searchEngine": "Bing",
3 | "theme": "light",
4 | "homepage": "home.html",
5 | "chatbot": "default",
6 | "version": "1.0.0"
7 | }
8 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | tags:
5 | - 'v*'
6 | workflow_dispatch:
7 | jobs:
8 | publish:
9 | permissions:
10 | contents: write
11 | strategy:
12 | matrix:
13 | os: [windows-latest, macos-latest]
14 | runs-on: ${{ matrix.os }}
15 | steps:
16 | - uses: actions/checkout@v4
17 | - uses: actions/setup-node@v4
18 | with:
19 | node-version: 18
20 | - name: Generate short SHA
21 | id: short-sha
22 | run: echo "sha=${GITHUB_SHA:0:5}" >> $GITHUB_OUTPUT
23 | - name: Install dependencies
24 | run: npm install
25 | - name: Publish with Electron Forge
26 | env:
27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 | run: npm run forge-publish
29 | - name: Create GitHub Release
30 | uses: actions/create-release@v1
31 | env:
32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33 | with:
34 | tag_name: ${{ steps.short-sha.outputs.sha }}
35 | release_name: Release ${{ github.ref_name }}
36 | draft: false
37 |
--------------------------------------------------------------------------------
/preload.js:
--------------------------------------------------------------------------------
1 | const { contextBridge, ipcRenderer } = require('electron');
2 |
3 | contextBridge.exposeInMainWorld('electronAPI', {
4 | navigateTo: (url) => ipcRenderer.invoke('navigate-to', url),
5 | goBack: () => ipcRenderer.invoke('go-back'),
6 | goForward: () => ipcRenderer.invoke('go-forward'),
7 | showBrowserView: (show) => ipcRenderer.invoke('show-browserview', show),
8 | // Context menu functions
9 | openContextMenu: (x, y, options) => ipcRenderer.invoke('show-context-menu', x, y, options),
10 | // Engine selection communication
11 | setEngine: (engineName) => {
12 | localStorage.setItem('selectedEngine', engineName);
13 | // Communicate with parent window
14 | if (window.parent && window.parent !== window) {
15 | window.parent.postMessage({ type: 'ENGINE_CHANGED', engine: engineName }, '*');
16 | }
17 | },
18 | getEngine: () => {
19 | return localStorage.getItem('selectedEngine') || 'Bing';
20 | },
21 | // Session persistence
22 | saveBrowserState: (state) => ipcRenderer.invoke('save-browser-state', state),
23 | loadBrowserState: () => ipcRenderer.invoke('load-browser-state'),
24 | // Webview reload
25 | reloadWebview: () => ipcRenderer.send('reload-webview')
26 | });
27 |
--------------------------------------------------------------------------------
/.github/workflows/flow1:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI
4 |
5 | # Controls when the workflow will run
6 | on:
7 | # Triggers the workflow on push or pull request events but only for the "main" branch
8 | push:
9 | branches: [ "main" ]
10 | pull_request:
11 | branches: [ "main" ]
12 |
13 | # Allows you to run this workflow manually from the Actions tab
14 | workflow_dispatch:
15 |
16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
17 | jobs:
18 | # This workflow contains a single job called "build"
19 | build:
20 | # The type of runner that the job will run on
21 | runs-on: ubuntu-latest
22 |
23 | # Steps represent a sequence of tasks that will be executed as part of the job
24 | steps:
25 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
26 | - uses: actions/checkout@v4
27 |
28 | # Runs a single command using the runners shell
29 | - name: Run a one-line script
30 | run: echo Hello, world!
31 |
32 | # Runs a set of commands using the runners shell
33 | - name: Run a multi-line script
34 | run: |
35 | echo Add other actions to build,
36 | echo test, and deploy your project.
37 |
--------------------------------------------------------------------------------
/.github/workflows/static.yml:
--------------------------------------------------------------------------------
1 | # Simple workflow for deploying static content to GitHub Pages
2 | name: Deploy static content to Pages
3 |
4 | on:
5 | # Runs on pushes targeting the default branch
6 | push:
7 | branches: ["main"]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13 | permissions:
14 | contents: read
15 | pages: write
16 | id-token: write
17 |
18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
20 | concurrency:
21 | group: "pages"
22 | cancel-in-progress: false
23 |
24 | jobs:
25 | # Single deploy job since we're just deploying
26 | deploy:
27 | environment:
28 | name: github-pages
29 | url: ${{ steps.deployment.outputs.page_url }}
30 | runs-on: ubuntu-latest
31 | steps:
32 | - name: Checkout
33 | uses: actions/checkout@v4
34 | - name: Setup Pages
35 | uses: actions/configure-pages@v5
36 | - name: Upload artifact
37 | uses: actions/upload-pages-artifact@v3
38 | with:
39 | # Upload entire repository
40 | path: '.'
41 | - name: Deploy to GitHub Pages
42 | id: deployment
43 | uses: actions/deploy-pages@v4
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Isle Browser prioritizes the websites you visit over controls and tab viewing, while still keeping those features accessible. Keep in mind, Isle Browser Nova is still a work in progress and is nearly twice as fast as the original Isle Browser. ENJOY!😁
2 |
3 | Screenshots (For a more news go to https://www.reddit.com/r/IsleBrowser/ and subsribe to https://www.youtube.com/@Islebrowser)
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Isle Browser Nova is the non vibe coded version of the browser. It is better designed and more well maintained. Please do not shame or mock my creation in the issues bar. The bar is only to be used for an issue with the software. Isle browser Nova is created by me alone and I would prefer if people won't mock it. I only vibe coded the original isle browser as an experimental browser to see how efficient and well ai could code.
14 |
--------------------------------------------------------------------------------
/Index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Isle Browser
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
+
13 |
<
14 |
>
15 |
16 |

17 |
★
18 |
19 |
20 |
21 |
29 |
30 |
31 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "isle-nova",
3 | "version": "1.0.0",
4 | "description": "A new innovative browser",
5 | "author": "TopMyster",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/TopMyster/IsleBrowser"
9 | },
10 | "main": "main.js",
11 | "scripts": {
12 | "start": "electron-forge start",
13 | "package": "electron-forge package",
14 | "make": "electron-forge make",
15 | "forge-publish": "electron-forge publish",
16 | "build-all": "node build-all.js",
17 | "build-optimized": "node build-optimized.js",
18 | "build-windows-200mb": "node build-windows-200mb.cjs",
19 | "build-windows-simple": "node build-windows-simple.cjs",
20 | "build-debian-200mb": "node build-debian-200mb.cjs",
21 | "build-macos-200mb": "node build-macos-200mb.cjs",
22 | "build-all-functional": "node build-all-functional.cjs",
23 | "build-all-200mb": "node build-all-optimized.js",
24 | "build-minimal": "node build-minimal.js",
25 | "build-cross-platform": "node build-cross-platform.js",
26 | "build-simple": "node build-simple.js",
27 | "build-all-platforms-200mb": "node build-all-platforms.js",
28 | "clean": "rm -rf out dist temp-build temp-optimize dist-minimal dist-optimized temp-cross-build temp-simple dist-simple electron-builder.json"
29 | },
30 | "devDependencies": {
31 | "@electron-forge/cli": "^7.8.1",
32 | "@electron-forge/maker-deb": "^7.8.1",
33 | "@electron-forge/maker-rpm": "^7.8.1",
34 | "@electron-forge/maker-squirrel": "^7.8.1",
35 | "@electron-forge/maker-zip": "^7.8.1",
36 | "@electron-forge/plugin-auto-unpack-natives": "^7.8.1",
37 | "@electron-forge/plugin-fuses": "^7.8.1",
38 | "@electron-forge/publisher-electron-release-server": "^7.8.1",
39 | "@electron/fuses": "^1.8.0",
40 | "electron": "^30.0.0",
41 | "electron-builder": "^26.0.12",
42 | "electron-packager": "^17.1.2"
43 | },
44 | "dependencies": {
45 | "electron-is-dev": "^3.0.1",
46 | "update-electron-app": "^3.1.1"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/forge.config.js:
--------------------------------------------------------------------------------
1 | const { FusesPlugin } = require('@electron-forge/plugin-fuses');
2 | const { FuseV1Options, FuseVersion } = require('@electron/fuses');
3 |
4 | // Get the target platform from command line args or use current platform
5 | const getTargetPlatform = () => {
6 | const args = process.argv;
7 | const platformIndex = args.findIndex(arg => arg === '--platform');
8 | return platformIndex !== -1 && args[platformIndex + 1] ? args[platformIndex + 1] : process.platform;
9 | };
10 |
11 | const targetPlatform = getTargetPlatform();
12 |
13 | module.exports = {
14 | packagerConfig: {
15 | asar: true,
16 | name: 'Isle Nova',
17 | executableName: 'Isle Nova',
18 | icon: './assets/icon',
19 | appBundleId: 'com.topmyster.islenovabrowser',
20 | appCategoryType: 'public.app-category.productivity',
21 | osxSign: false,
22 | osxNotarize: false,
23 | // Size optimization settings - being more conservative to avoid breaking dependencies
24 | ignore: [
25 | // Test directories and files
26 | /\/node_modules\/.*\/test\//,
27 | /\/node_modules\/.*\/tests\//,
28 | /\/node_modules\/.*\/__tests__\//,
29 | /\/node_modules\/.*\/.*\.spec\.(js|ts|jsx|tsx)$/,
30 | /\/node_modules\/.*\/.*\.test\.(js|ts|jsx|tsx)$/,
31 |
32 | // Documentation and examples
33 | /\/node_modules\/.*\/example\//,
34 | /\/node_modules\/.*\/examples\//,
35 | /\/node_modules\/.*\/docs?\//,
36 | /\/node_modules\/.*\/demo\//,
37 | /\/node_modules\/.*\/demos\//,
38 |
39 | // VCS files
40 | /\/node_modules\/.*\/.git\//,
41 | /\/node_modules\/.*\/\.travis\.yml$/,
42 |
43 | // Documentation files
44 | /\/node_modules\/.*\/README\.(md|txt|rst)$/i,
45 | /\/node_modules\/.*\/CHANGELOG\.(md|txt|rst)$/i,
46 | /\/node_modules\/.*\/LICENSE/i,
47 |
48 | // Source maps
49 | /\/node_modules\/.*\/.*\.map$/
50 | ],
51 | // Include only English locale to save space
52 | afterCopy: [(buildPath, electronVersion, platform, arch, callback) => {
53 | const fs = require('fs');
54 | const path = require('path');
55 |
56 | const localesPath = path.join(buildPath, 'locales');
57 | if (fs.existsSync(localesPath)) {
58 | const files = fs.readdirSync(localesPath);
59 | files.forEach(file => {
60 | if (!file.startsWith('en-US') && file.endsWith('.pak')) {
61 | try {
62 | fs.unlinkSync(path.join(localesPath, file));
63 | } catch (e) {
64 | // Ignore errors
65 | }
66 | }
67 | });
68 | }
69 | callback();
70 | }],
71 | win32metadata: {
72 | CompanyName: 'TopMyster',
73 | FileDescription: 'Isle Nova Browser',
74 | OriginalFilename: 'Isle Nova.exe',
75 | ProductName: 'Isle Nova',
76 | InternalName: 'Isle Nova'
77 | }
78 | },
79 | rebuildConfig: {},
80 | makers: [
81 | // Windows x64
82 | {
83 | name: '@electron-forge/maker-zip',
84 | config: {
85 | name: 'Isle.Nova-win32-x64'
86 | },
87 | platforms: ['win32'],
88 | arch: ['x64']
89 | },
90 | // Windows ARM64
91 | {
92 | name: '@electron-forge/maker-zip',
93 | config: {
94 | name: 'Isle.Nova-win32-arm64'
95 | },
96 | platforms: ['win32'],
97 | arch: ['arm64']
98 | },
99 | // macOS Intel (x64)
100 | {
101 | name: '@electron-forge/maker-zip',
102 | config: {
103 | name: 'Isle.Nova-macOS-intel'
104 | },
105 | platforms: ['darwin'],
106 | arch: ['x64']
107 | },
108 | // macOS ARM64
109 | {
110 | name: '@electron-forge/maker-zip',
111 | config: {
112 | name: 'Isle.Nova-macOS-arm64'
113 | },
114 | platforms: ['darwin'],
115 | arch: ['arm64']
116 | },
117 | // Linux DEB package
118 | {
119 | name: '@electron-forge/maker-deb',
120 | config: {
121 | name: 'Isle-nova-1.0.0-amd64.deb',
122 | options: {
123 | bin: 'Isle Nova',
124 | maintainer: 'TopMyster',
125 | homepage: 'https://github.com/TopMyster/IsleBrowser',
126 | description: 'A modern, innovative browser built with Electron',
127 | categories: ['Network', 'WebBrowser']
128 | }
129 | },
130 | platforms: ['linux'],
131 | arch: ['x64']
132 | },
133 | // Linux ZIP
134 | {
135 | name: '@electron-forge/maker-zip',
136 | config: {
137 | name: 'Isle-nova-1.0.0-linux-x64'
138 | },
139 | platforms: ['linux'],
140 | arch: ['x64']
141 | }
142 | ],
143 | plugins: [
144 | {
145 | name: '@electron-forge/plugin-auto-unpack-natives',
146 | config: {},
147 | },
148 |
149 | new FusesPlugin({
150 | version: FuseVersion.V1,
151 | [FuseV1Options.RunAsNode]: false,
152 | [FuseV1Options.EnableCookieEncryption]: true,
153 | [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
154 | [FuseV1Options.EnableNodeCliInspectArguments]: false,
155 | [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
156 | [FuseV1Options.OnlyLoadAppFromAsar]: true,
157 | }),
158 | ],
159 | };
160 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | const { app, BrowserWindow, ipcMain, globalShortcut, Menu, dialog, shell } = require('electron');
2 | const { join } = require('path');
3 | const { writeFileSync, readFileSync } = require('fs');
4 | const { updateElectronApp } = require('update-electron-app');
5 |
6 | // __dirname is available in CommonJS
7 | // Check if we're in development mode
8 | const isDev = process.env.NODE_ENV === 'development' || process.defaultApp || /[\\|/]electron-prebuilt[\\|/]/.test(process.execPath) || /[\\|/]electron[\\|/]/.test(process.execPath);
9 |
10 | if (!isDev) {
11 | updateElectronApp();
12 | }
13 |
14 | // Handle Squirrel startup events on Windows
15 | if (process.platform === 'win32') {
16 | const squirrelCommand = process.argv[1];
17 | if (squirrelCommand) {
18 | switch (squirrelCommand) {
19 | case '--squirrel-install':
20 | case '--squirrel-updated':
21 | case '--squirrel-uninstall':
22 | case '--squirrel-obsolete':
23 | app.quit();
24 | return;
25 | }
26 | }
27 | }
28 |
29 | function getIconPath() {
30 | // Use appropriate icon format for each platform
31 | if (process.platform === 'win32') {
32 | return join(__dirname, 'assets', 'icon.ico'); // Windows prefers .ico
33 | } else if (process.platform === 'darwin') {
34 | return join(__dirname, 'assets', 'icon.icns'); // macOS uses .icns
35 | } else {
36 | return join(__dirname, 'assets', 'icon.png'); // Linux uses .png
37 | }
38 | }
39 |
40 | function createWindow () {
41 | const win = new BrowserWindow({
42 | width: 1400,
43 | height: 850,
44 | transparent: true, // Temporarily disabled for testing
45 | frame: false, // Temporarily enabled for testing
46 | show: false, // Don't show until ready
47 | icon: getIconPath(),
48 | vibrancy: 'ultra-dark',
49 | blur: 50,
50 | backgroundColor: 'rgba(211, 211, 211, 0.65)',
51 | webPreferences: {
52 | nodeIntegration: true,
53 | contextIsolation: false,
54 | webviewTag: true,
55 | preload: join(__dirname, 'preload.js')
56 | }
57 | });
58 |
59 | // Show window when ready to prevent white flash
60 | win.once('ready-to-show', () => {
61 | win.show();
62 | });
63 |
64 | win.loadFile('index.html');
65 | }
66 |
67 | app.whenReady().then(() => {
68 | createWindow();
69 |
70 | // Register global shortcuts
71 | // Cmd+L: Toggle chat panel
72 | globalShortcut.register('CommandOrControl+L', () => {
73 | const focusedWindow = BrowserWindow.getFocusedWindow();
74 | if (focusedWindow) {
75 | console.log('Global Cmd+L shortcut triggered');
76 | focusedWindow.webContents.send('toggle-chat-panel');
77 | }
78 | });
79 |
80 | // Cmd+K: Toggle tabbar
81 | globalShortcut.register('CommandOrControl+K', () => {
82 | const focusedWindow = BrowserWindow.getFocusedWindow();
83 | if (focusedWindow) {
84 | console.log('Global Cmd+K shortcut triggered');
85 | focusedWindow.webContents.send('toggle-tabbar');
86 | }
87 | });
88 | });
89 |
90 | // IPC handlers for browser functionality
91 | ipcMain.handle('navigate-to', async (event, url) => {
92 | // Handle navigation logic here
93 | console.log('Navigate to:', url);
94 | });
95 |
96 | ipcMain.handle('go-back', async (event) => {
97 | // Handle back navigation
98 | console.log('Go back');
99 | });
100 |
101 | ipcMain.handle('go-forward', async (event) => {
102 | // Handle forward navigation
103 | console.log('Go forward');
104 | });
105 |
106 | ipcMain.handle('show-browserview', async (event, show) => {
107 | console.log('Show browser view:', show);
108 | });
109 |
110 | // Global variable to store context menu info
111 | let contextMenuInfo = { linkURL: '', srcURL: '', selectionText: '' };
112 |
113 | // Session persistence handlers
114 | ipcMain.handle('save-browser-state', async (event, state) => {
115 | try {
116 | const sessionPath = join(__dirname, 'session.json');
117 | writeFileSync(sessionPath, JSON.stringify(state, null, 2));
118 | return { success: true };
119 | } catch (error) {
120 | console.error('Failed to save session:', error);
121 | return { success: false, error: error.message };
122 | }
123 | });
124 |
125 | ipcMain.handle('load-browser-state', async (event) => {
126 | try {
127 | const sessionPath = join(__dirname, 'session.json');
128 | const data = readFileSync(sessionPath, 'utf8');
129 | return { success: true, data: JSON.parse(data) };
130 | } catch (error) {
131 | console.log('No session file found or failed to load:', error.message);
132 | return { success: false, error: error.message };
133 | }
134 | });
135 |
136 | // Webview reload handler
137 | ipcMain.on('reload-webview', (event) => {
138 | event.sender.send('reload-webview-response');
139 | });
140 |
141 | // Function to create new browser window
142 | function createNewBrowserWindow(url) {
143 | const newWin = new BrowserWindow({
144 | width: 1200,
145 | height: 800,
146 | icon: getIconPath(),
147 | webPreferences: {
148 | nodeIntegration: true,
149 | contextIsolation: false,
150 | webviewTag: true,
151 | preload: join(__dirname, 'preload.js')
152 | }
153 | });
154 |
155 | newWin.loadFile('index.html');
156 |
157 | if (url) {
158 | newWin.webContents.once('dom-ready', () => {
159 | newWin.webContents.send('navigate-to-url', url);
160 | });
161 | }
162 | }
163 |
164 | app.on('window-all-closed', function () {
165 | if (process.platform !== 'darwin') app.quit();
166 | });
167 |
168 | app.on('will-quit', () => {
169 | // Unregister all shortcuts
170 | globalShortcut.unregisterAll();
171 | });
172 |
--------------------------------------------------------------------------------
/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
Settings
8 |
______________________________________________
9 |
10 |
18 |
19 |
20 |
24 |
25 |
26 |
32 |
33 |
34 |
Isle
35 |
The browser you deserve
36 |
⚙︎
37 |
38 |
39 |
40 |
41 |
130 |
131 |
132 |
133 |