refactor: move studio to frontends workspace

- Move studio from root to frontends/studio/
- Add owner-tools frontend for live blog admin UI
- Add shared ui component library
- Set up npm workspaces for frontends
- Add enhanced code block extension for editor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Josh 2026-01-12 01:59:56 +02:00
parent c662e41b97
commit bef5dd4437
108 changed files with 8650 additions and 441 deletions

View file

@ -0,0 +1,64 @@
import { atom, map, onMount } from 'nanostores'
import { getSettings, getSettingsSchema, saveSettings as apiSaveSettings } from '../api'
import type { Settings, SettingDefinition } from '../api'
export const $panelOpen = atom(false)
export const $regenerating = atom(false)
export const $error = atom<string | null>(null)
export const $settings = map<Settings>({})
export const $schema = atom<SettingDefinition[]>([])
export const $dirty = atom(false)
export function openPanel() {
$panelOpen.set(true)
}
export function closePanel() {
$panelOpen.set(false)
}
export function updateSetting(key: string, value: string) {
$settings.setKey(key, value)
$dirty.set(true)
}
async function softReload() {
const res = await fetch(window.location.href)
if (!res.ok) throw new Error('Failed to fetch page')
const html = await res.text()
const parser = new DOMParser()
const newDoc = parser.parseFromString(html, 'text/html')
const currentPage = document.getElementById('page')
const newPage = newDoc.getElementById('page')
if (currentPage && newPage) {
currentPage.outerHTML = newPage.outerHTML
}
}
export async function saveSettings() {
$regenerating.set(true)
$error.set(null)
try {
await apiSaveSettings($settings.get())
await softReload()
$regenerating.set(false)
$dirty.set(false)
} catch {
$regenerating.set(false)
$error.set('Failed to save')
}
}
onMount($settings, () => {
getSettings()
.then(data => $settings.set(data))
.catch(() => $error.set('Failed to load settings'))
getSettingsSchema()
.then(data => $schema.set(data))
.catch(() => {})
})