feat(setup): collect server base URL during first-run wizard

Add a Server URL field to the admin-account step of the setup wizard so
the public base URL (used for device sync, OPDS feed, and API endpoints)
is configured up front instead of requiring a later visit to admin
settings.

- setup.templ: base URL input on the admin step plus a summary entry
- setup.ts: default baseUrl to window.location.origin and persist it via
  PUT /system/config ({ base_url }) right after the admin account is
  created, with a non-fatal warning if the save fails
This commit is contained in:
2026-06-07 00:03:01 -04:00
parent f75d68bf66
commit 3170aa6b77
3 changed files with 34 additions and 4 deletions
+17
View File
@@ -49,6 +49,19 @@ templ Setup() {
<p class="mb-6" style="color: var(--text-secondary)">This first account will have full admin privileges.</p>
<form @submit.prevent="submitAdmin()">
<div class="mb-6 p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Server URL (Base URL)</label>
<input
type="url"
x-model="admin.baseUrl"
placeholder="https://books.example.com"
class="w-full px-3 py-2 border rounded mt-2"
style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)"
required
/>
<p class="text-sm mt-2" style="color: var(--text-secondary)">The public URL of your Bookhoard instance. Used for device sync, OPDS feed, and API endpoints.</p>
</div>
<div class="mb-4">
<label class="block text-sm font-medium mb-1" style="color: var(--text-secondary)">Email</label>
<input
@@ -289,6 +302,10 @@ templ Setup() {
<!-- Summary -->
<div class="space-y-3 mb-6">
<div class="p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
<p class="text-sm font-medium mb-1" style="color: var(--text-secondary)">Server URL</p>
<p style="color: var(--text-primary)" x-text="admin.baseUrl"></p>
</div>
<div class="p-4 rounded-lg border" style="background-color: var(--bg-primary); border-color: var(--border)">
<p class="text-sm font-medium mb-1" style="color: var(--text-secondary)">Administrator</p>
<p style="color: var(--text-primary)" x-text="admin.username + ' (' + admin.email + ')'"></p>
File diff suppressed because one or more lines are too long
+16 -3
View File
@@ -36,14 +36,13 @@ function initSetup(): void {
if (savedTheme && savedTheme !== "tokyo-night") {
applyTheme(savedTheme);
}
}
Alpine.data("setupWizard", () => ({
}Alpine.data("setupWizard", () => ({
currentStep: 1 as number,
loading: false as boolean,
errorMsg: "" as string,
admin: {
baseUrl: "",
email: "",
username: "",
password: "",
@@ -71,6 +70,7 @@ Alpine.data("setupWizard", () => ({
init() {
initSetup();
this.admin.baseUrl = window.location.origin;
setTimeout(() => {
initPasswordValidation();
}, 100);
@@ -128,6 +128,8 @@ Alpine.data("setupWizard", () => ({
setToken(data.token || data.access_token);
setRefreshToken(data.refresh_token);
await this.saveBaseUrl();
showToast("Admin account created successfully!", "success");
this.currentStep = 2;
} catch (err) {
@@ -137,6 +139,17 @@ Alpine.data("setupWizard", () => ({
}
},
async saveBaseUrl() {
if (!this.admin.baseUrl) return;
try {
await handleVoidResponse(
await apiPut("/system/config", { base_url: this.admin.baseUrl })
);
} catch {
showToast("Warning: could not save server URL. You can set it later in Admin Settings.", "warning");
}
},
async addLibrary() {
this.clearError();
this.loading = true;