feat(navi): config-driven tile source, defaults, and feature flags

Load deployment config from /api/config on startup:
- src/config.js: loader with 3s timeout + hardcoded fallback
- src/hooks/useConfig.js: useConfig() and useFeature() hooks
- MapView.jsx: tile URL, attribution, center, zoom from config
- main.jsx: loads config before first render

Falls back to home profile defaults if backend unavailable.
No visible behavior change — infrastructure for future features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-04-20 23:36:02 +00:00
commit edc5a9788d
4 changed files with 146 additions and 22 deletions

View file

@ -1,23 +1,27 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Toaster } from 'react-hot-toast'
import { loadConfig } from './config'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
<Toaster
position="bottom-center"
toastOptions={{
style: {
background: 'var(--bg-overlay)',
color: 'var(--text-primary)',
border: '1px solid var(--border)',
fontSize: 'var(--text-sm)',
fontFamily: 'var(--font-sans)',
},
}}
/>
</StrictMode>,
)
// Load deployment config before rendering non-blocking (fallback kicks in on failure)
loadConfig().then(() => {
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
<Toaster
position="bottom-center"
toastOptions={{
style: {
background: 'var(--bg-overlay)',
color: 'var(--text-primary)',
border: '1px solid var(--border)',
fontSize: 'var(--text-sm)',
fontFamily: 'var(--font-sans)',
},
}}
/>
</StrictMode>,
)
})