2026-01-24 22:59:20 +00:00
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'
import path from 'path'
// https://vite.dev/config/
export default defineConfig ({
plugins : [
vue (),
VitePWA ({
registerType : 'autoUpdate' ,
2026-03-06 01:11:00 +00:00
includeAssets : [ 'assets/icon/favico-black-v2.svg' , 'assets/icon/pwa-64x64-v2.png' , 'assets/icon/pwa-192x192-v2.png' , 'assets/icon/pwa-512x512-v2.png' , 'assets/icon/maskable-icon-512x512-v2.png' , 'assets/icon/apple-touch-icon-180x180-v2.png' , 'favicon-v2.ico' ],
2026-01-24 22:59:20 +00:00
manifest : {
name : 'Archipelago' ,
short_name : 'Archipelago' ,
description : 'Your sovereign personal server' ,
theme_color : '#000000' ,
background_color : '#000000' ,
display : 'standalone' ,
2026-02-18 13:48:45 +00:00
display_override : [ 'standalone' , 'minimal-ui' ],
2026-01-24 22:59:20 +00:00
orientation : 'any' ,
scope : '/' ,
start_url : '/' ,
2026-02-18 13:48:45 +00:00
id : '/' ,
2026-02-01 18:46:35 +00:00
categories : [ 'productivity' , 'utilities' ],
prefer_related_applications : false ,
2026-01-24 22:59:20 +00:00
icons : [
2026-03-06 01:11:00 +00:00
{ src : '/assets/icon/pwa-64x64-v2.png' , sizes : '64x64' , type : 'image/png' , purpose : 'any' },
{ src : '/assets/icon/pwa-192x192-v2.png' , sizes : '192x192' , type : 'image/png' , purpose : 'any' },
{ src : '/assets/icon/pwa-512x512-v2.png' , sizes : '512x512' , type : 'image/png' , purpose : 'any' },
{ src : '/assets/icon/maskable-icon-512x512-v2.png' , sizes : '512x512' , type : 'image/png' , purpose : 'maskable' }
2026-01-24 22:59:20 +00:00
],
shortcuts : [
2026-03-06 01:11:00 +00:00
{ name : 'Dashboard' , short_name : 'Dashboard' , description : 'Open the dashboard' , url : '/dashboard' , icons : [{ src : '/assets/icon/pwa-192x192-v2.png' , sizes : '192x192' }] },
{ name : 'My Apps' , short_name : 'Apps' , description : 'Manage your apps' , url : '/dashboard/apps' , icons : [{ src : '/assets/icon/pwa-192x192-v2.png' , sizes : '192x192' }] },
{ name : 'App Store' , short_name : 'Store' , description : 'Browse and install apps' , url : '/dashboard/marketplace' , icons : [{ src : '/assets/icon/pwa-192x192-v2.png' , sizes : '192x192' }] }
2026-01-24 22:59:20 +00:00
]
},
workbox : {
2026-03-05 08:24:56 +00:00
navigateFallbackDenylist : [ /^\/app\// , /^\/rpc\// , /^\/ws/ , /^\/aiui\// ],
2026-05-17 17:30:04 -04:00
cleanupOutdatedCaches : true ,
2026-01-24 22:59:20 +00:00
globPatterns : [ '**/*.{js,css,html,ico,png,svg,jpg,jpeg,mp4,webp}' ],
globIgnores : [
'**/*-backup-*.mp4' ,
'**/*-1.47mb.mp4' ,
'**/bg-*.mp4' , // Exclude large background videos from precache
2026-03-14 17:12:41 +00:00
'**/video-intro*.mp4' , // Exclude all intro video variants from precache
2026-03-08 00:02:37 +00:00
'**/assets/icon/**' , // Icons are in includeAssets — don't duplicate in glob precache
2026-01-24 22:59:20 +00:00
],
2026-03-14 17:12:41 +00:00
maximumFileSizeToCacheInBytes : 10 * 1024 * 1024 , // 10MB limit
2026-01-24 22:59:20 +00:00
skipWaiting : false , // Wait for user to accept update
clientsClaim : false , // Don't claim clients immediately
runtimeCaching : [
{
urlPattern : /^https:\/\/fonts\.googleapis\.com\/.*/i ,
handler : 'CacheFirst' ,
options : {
cacheName : 'google-fonts-cache' ,
expiration : {
maxEntries : 10 ,
maxAgeSeconds : 60 * 60 * 24 * 365 // 1 year
},
cacheableResponse : {
statuses : [ 0 , 200 ]
}
}
},
{
urlPattern : /^https:\/\/fonts\.gstatic\.com\/.*/i ,
handler : 'CacheFirst' ,
options : {
cacheName : 'gstatic-fonts-cache' ,
expiration : {
maxEntries : 10 ,
maxAgeSeconds : 60 * 60 * 24 * 365 // 1 year
},
cacheableResponse : {
statuses : [ 0 , 200 ]
}
}
},
{
urlPattern : /\/rpc\/v1\/.*/i ,
handler : 'NetworkFirst' ,
options : {
cacheName : 'api-cache' ,
expiration : {
maxEntries : 50 ,
maxAgeSeconds : 60 * 5 // 5 minutes
},
networkTimeoutSeconds : 10
}
},
{
urlPattern : /\/assets\/.*/i ,
handler : 'CacheFirst' ,
options : {
2026-04-22 04:45:33 -04:00
cacheName : 'assets-cache-v3' ,
2026-01-24 22:59:20 +00:00
expiration : {
maxEntries : 100 ,
maxAgeSeconds : 60 * 60 * 24 * 30 // 30 days
}
}
}
]
},
devOptions : {
2026-03-28 17:01:17 +00:00
enabled : false ,
2026-01-24 22:59:20 +00:00
}
})
],
resolve : {
alias : {
'@' : path . resolve ( __dirname , './src' )
}
},
server : {
port : 8100 ,
proxy : {
'/rpc/v1' : {
target : process.env.BACKEND_URL || 'http://localhost:5959' ,
changeOrigin : true ,
secure : false ,
},
'/ws' : {
target : process.env.BACKEND_URL || 'http://localhost:5959' ,
ws : true ,
changeOrigin : true ,
secure : false ,
rewrite : ( path ) => path , // Don't rewrite the path
2026-01-27 23:06:18 +00:00
timeout : 0 , // No timeout for WebSocket connections
2026-01-24 22:59:20 +00:00
},
'/public' : {
target : process.env.BACKEND_URL || 'http://localhost:5959' ,
changeOrigin : true ,
secure : false ,
},
'/rest' : {
target : process.env.BACKEND_URL || 'http://localhost:5959' ,
changeOrigin : true ,
secure : false ,
},
2026-03-05 08:24:56 +00:00
'/app/filebrowser' : {
target : 'http://192.168.1.228' ,
changeOrigin : true ,
secure : false ,
},
2026-06-11 00:24:40 -04:00
'/app/bitcoin-ui' : {
target : process.env.BACKEND_URL || 'http://localhost:5959' ,
changeOrigin : true ,
secure : false ,
},
2026-06-13 01:23:32 -04:00
// Serve the node's deployed AIUI same-origin like production (set VITE_AIUI_URL=/aiui/)
'/aiui' : {
target : process.env.AIUI_PROXY_TARGET || 'http://127.0.0.1:80' ,
changeOrigin : true ,
secure : false ,
},
2026-01-24 22:59:20 +00:00
},
},
build : {
// Output to dist for Docker builds, or to ../web/dist/neode-ui for local development
outDir : process.env.DOCKER_BUILD === 'true' ? 'dist' : '../web/dist/neode-ui' ,
emptyOutDir : true ,
2026-03-21 01:57:05 +00:00
rollupOptions : {
output : {
manualChunks : {
vendor : [ 'vue' , 'vue-router' , 'pinia' ],
}
}
}
2026-01-24 22:59:20 +00:00
},
})