1 import { defineConfig } from 'vite';
2 import { svelte } from '@sveltejs/vite-plugin-svelte';
3 import { copyFileSync } from 'node:fs';
4 import { dirname, resolve } from 'node:path';
5 import { fileURLToPath } from 'node:url';
7 const __dirname = dirname(fileURLToPath(import.meta.url));
9 // The app is a single SPA. Multiple HTML entry points exist only so the
10 // distribution can be served as a static directory and users can bookmark
11 // /search.html, /reverse.html, etc.; all of them load the same SPA, and
12 // AppState reads window.location.pathname to pick the page to render.
14 // We keep a single source HTML (search.html) and copy it after the build to
15 // the other page names. In dev mode, a middleware rewrites those URLs to
16 // /search.html so Vite serves the SPA.
17 const PAGES = ['reverse', 'details', 'deletable', 'polygons', 'status', 'about'];
19 function nominatimPages() {
21 name: 'nominatim-pages',
23 configureServer(server) {
24 server.middlewares.use((req, res, next) => {
25 const url = (req.url || '').split('?')[0];
26 const slug = url.replace(/^\//, '').replace(/\.html$/, '');
27 if (PAGES.includes(slug)) {
28 const qs = req.url.includes('?') ? '?' + req.url.split('?')[1] : '';
29 req.url = '/search.html' + qs;
36 const distDir = resolve('dist');
37 const src = resolve(distDir, 'search.html');
38 for (const page of PAGES) {
39 copyFileSync(src, resolve(distDir, `${page}.html`));
45 export default defineConfig({
47 plugins: [svelte(), nominatimPages()],
52 index: resolve(__dirname, 'index.html'),
53 search: resolve(__dirname, 'search.html')