refactor: rename Fabled Assistant to Fabled Scribe

Updates user-visible branding across frontend (PWA manifest, page title,
Settings, push fallback), backend (email templates and subjects, LLM
system prompt, CalDAV displayname, SMTP from-name default), README,
quickstart compose, and MCP server description.

Also updates the CI image path and quickstart image reference to
git.fabledsword.com/bvandeusen/fabledscribe in preparation for the
Forgejo repo rename. Internal Python package, env vars, and database
schema unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 16:28:25 -04:00
parent 96a44886ef
commit e652dece9b
13 changed files with 28 additions and 28 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ permissions:
env: env:
REGISTRY: git.fabledsword.com REGISTRY: git.fabledsword.com
IMAGE: git.fabledsword.com/bvandeusen/fabledassistant IMAGE: git.fabledsword.com/bvandeusen/fabledscribe
jobs: jobs:
typecheck: typecheck:
+1 -1
View File
@@ -1,4 +1,4 @@
# Fabled Assistant # Fabled Scribe
A self-hosted second brain and project management application with integrated LLM capabilities. Write, organise, and act on your notes and tasks with the help of a local AI assistant — all running on your own hardware. A self-hosted second brain and project management application with integrated LLM capabilities. Write, organise, and act on your notes and tasks with the help of a local AI assistant — all running on your own hardware.
+2 -2
View File
@@ -1,4 +1,4 @@
# Fabled Assistant — Quick Start # Fabled Scribe — Quick Start
# #
# No build required. Pulls the latest pre-built image from the registry. # No build required. Pulls the latest pre-built image from the registry.
# #
@@ -13,7 +13,7 @@
services: services:
app: app:
image: git.fabledsword.com/bvandeusen/fabledassistant:latest image: git.fabledsword.com/bvandeusen/fabledscribe:latest
ports: ports:
- "5000:5000" - "5000:5000"
environment: environment:
+1 -1
View File
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "fable-mcp" name = "fable-mcp"
version = "0.2.6" version = "0.2.6"
description = "MCP server for Fabled Assistant" description = "MCP server for Fabled Scribe"
requires-python = ">=3.12" requires-python = ">=3.12"
dependencies = [ dependencies = [
"mcp[cli]>=1.0", "mcp[cli]>=1.0",
+2 -2
View File
@@ -9,8 +9,8 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Fabled"> <meta name="apple-mobile-web-app-title" content="Scribe">
<title>Fabled Assistant</title> <title>Fabled Scribe</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "Fabled Assistant", "name": "Fabled Scribe",
"short_name": "Fabled", "short_name": "Scribe",
"description": "Your self-hosted second brain with AI assistance", "description": "Your self-hosted second brain with AI assistance",
"start_url": "/", "start_url": "/",
"display": "standalone", "display": "standalone",
+1 -1
View File
@@ -12,7 +12,7 @@ self.addEventListener('push', event => {
return; return;
} }
} }
return self.registration.showNotification(data.title || 'Fabled Assistant', { return self.registration.showNotification(data.title || 'Scribe', {
body: data.body || '', body: data.body || '',
icon: '/favicon.ico', icon: '/favicon.ico',
badge: '/favicon.ico', badge: '/favicon.ico',
+3 -3
View File
@@ -501,7 +501,7 @@ const smtp = ref({
smtp_username: "", smtp_username: "",
smtp_password: "", smtp_password: "",
smtp_from_address: "", smtp_from_address: "",
smtp_from_name: "Fabled Assistant", smtp_from_name: "Fabled Scribe",
smtp_use_tls: "true", smtp_use_tls: "true",
}); });
const savingSmtp = ref(false); const savingSmtp = ref(false);
@@ -1981,7 +1981,7 @@ function formatUserDate(iso: string): string {
<section class="settings-section full-width"> <section class="settings-section full-width">
<h2>About</h2> <h2>About</h2>
<p class="version-line">Fabled Assistant <span class="version-badge">{{ appVersion }}</span></p> <p class="version-line">Fabled Scribe <span class="version-badge">{{ appVersion }}</span></p>
</section> </section>
</div> </div>
@@ -2741,7 +2741,7 @@ FABLE_API_KEY={{ effectiveApiKey }}</pre>
</div> </div>
<div class="field"> <div class="field">
<label for="smtp-from-name">From Name</label> <label for="smtp-from-name">From Name</label>
<input id="smtp-from-name" v-model="smtp.smtp_from_name" type="text" placeholder="Fabled Assistant" class="input" /> <input id="smtp-from-name" v-model="smtp.smtp_from_name" type="text" placeholder="Fabled Scribe" class="input" />
</div> </div>
</div> </div>
<div class="checkbox-field"> <div class="checkbox-field">
+1 -1
View File
@@ -52,7 +52,7 @@ class Config:
SMTP_USERNAME: str = os.environ.get("SMTP_USERNAME", "") SMTP_USERNAME: str = os.environ.get("SMTP_USERNAME", "")
SMTP_PASSWORD: str = _read_secret("SMTP_PASSWORD", "SMTP_PASSWORD_FILE", "") SMTP_PASSWORD: str = _read_secret("SMTP_PASSWORD", "SMTP_PASSWORD_FILE", "")
SMTP_FROM_ADDRESS: str = os.environ.get("SMTP_FROM_ADDRESS", "") SMTP_FROM_ADDRESS: str = os.environ.get("SMTP_FROM_ADDRESS", "")
SMTP_FROM_NAME: str = os.environ.get("SMTP_FROM_NAME", "Fabled Assistant") SMTP_FROM_NAME: str = os.environ.get("SMTP_FROM_NAME", "Fabled Scribe")
SMTP_USE_TLS: bool = os.environ.get("SMTP_USE_TLS", "true").lower() in ("1", "true", "yes") SMTP_USE_TLS: bool = os.environ.get("SMTP_USE_TLS", "true").lower() in ("1", "true", "yes")
BASE_URL: str = os.environ.get("BASE_URL", "http://localhost:5000").rstrip("/") BASE_URL: str = os.environ.get("BASE_URL", "http://localhost:5000").rstrip("/")
TRUST_PROXY_HEADERS: bool = os.environ.get("TRUST_PROXY_HEADERS", "").lower() in ("1", "true", "yes") TRUST_PROXY_HEADERS: bool = os.environ.get("TRUST_PROXY_HEADERS", "").lower() in ("1", "true", "yes")
@@ -66,7 +66,7 @@ async def setup_user_calendar(user_id: int) -> bool:
<set> <set>
<prop> <prop>
<resourcetype><collection/><C:calendar/></resourcetype> <resourcetype><collection/><C:calendar/></resourcetype>
<displayname>Fabled Assistant</displayname> <displayname>Fabled Scribe</displayname>
</prop> </prop>
</set> </set>
</mkcol>""", </mkcol>""",
+6 -6
View File
@@ -38,7 +38,7 @@ _EMAIL_LOGO_SVG = (
def _email_html(title: str, body: str) -> str: def _email_html(title: str, body: str) -> str:
"""Wrap email body content in the standard Fabled Assistant template.""" """Wrap email body content in the standard Fabled Scribe template."""
return f"""<!DOCTYPE html> return f"""<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@@ -56,7 +56,7 @@ def _email_html(title: str, body: str) -> str:
<!-- Header --> <!-- Header -->
<div style="background:linear-gradient(135deg,#7c3aed 0%,#6d28d9 100%);padding:24px 28px;text-align:center;"> <div style="background:linear-gradient(135deg,#7c3aed 0%,#6d28d9 100%);padding:24px 28px;text-align:center;">
<div style="margin-bottom:8px;"> <div style="margin-bottom:8px;">
{_EMAIL_LOGO_SVG}<span style="display:inline-block;vertical-align:middle;color:#ffffff;font-size:18px;font-weight:700;letter-spacing:0.01em;">Fabled Assistant</span> {_EMAIL_LOGO_SVG}<span style="display:inline-block;vertical-align:middle;color:#ffffff;font-size:18px;font-weight:700;letter-spacing:0.01em;">Fabled Scribe</span>
</div> </div>
<p style="margin:0;color:#ede9fe;font-size:13px;letter-spacing:0.03em;">{title}</p> <p style="margin:0;color:#ede9fe;font-size:13px;letter-spacing:0.03em;">{title}</p>
</div> </div>
@@ -68,7 +68,7 @@ def _email_html(title: str, body: str) -> str:
<!-- Footer --> <!-- Footer -->
<div style="border-top:1px solid #ede9fe;padding:16px 28px;text-align:center;background:#faf5ff;"> <div style="border-top:1px solid #ede9fe;padding:16px 28px;text-align:center;background:#faf5ff;">
<p style="margin:0;color:#a78bfa;font-size:12px;">Sent by your Fabled Assistant instance.</p> <p style="margin:0;color:#a78bfa;font-size:12px;">Sent by your Fabled Scribe instance.</p>
</div> </div>
</div> </div>
@@ -146,7 +146,7 @@ async def send_email(to: str, subject: str, html_body: str) -> None:
username = config.get("smtp_username", "") username = config.get("smtp_username", "")
password = config.get("smtp_password", "") password = config.get("smtp_password", "")
from_address = config.get("smtp_from_address", "") from_address = config.get("smtp_from_address", "")
from_name = config.get("smtp_from_name", "Fabled Assistant") from_name = config.get("smtp_from_name", "Fabled Scribe")
use_tls = config.get("smtp_use_tls", "true") == "true" use_tls = config.get("smtp_use_tls", "true") == "true"
msg = EmailMessage() msg = EmailMessage()
@@ -176,6 +176,6 @@ async def send_test_email(to: str) -> None:
"""Send a branded test email.""" """Send a branded test email."""
body = """ body = """
<p style="margin:0 0 12px;color:#1e1b4b;font-size:15px;font-weight:600;">SMTP is configured correctly</p> <p style="margin:0 0 12px;color:#1e1b4b;font-size:15px;font-weight:600;">SMTP is configured correctly</p>
<p style="margin:0;color:#6b7280;font-size:14px;">Your Fabled Assistant instance can send email notifications.</p> <p style="margin:0;color:#6b7280;font-size:14px;">Your Fabled Scribe instance can send email notifications.</p>
""" """
await send_email(to, "Fabled Assistant - Test Email", _email_html("Test Email", body)) await send_email(to, "Fabled Scribe - Test Email", _email_html("Test Email", body))
+1 -1
View File
@@ -632,7 +632,7 @@ async def build_context(
tool_guidance = "\n".join(tool_lines) tool_guidance = "\n".join(tool_lines)
static_block = ( static_block = (
f"You are a helpful assistant named {assistant_name}, integrated into a note-taking and task-tracking app called Fabled Assistant. " f"You are a helpful assistant named {assistant_name}, integrated into a note-taking and task-tracking app called Fabled Scribe. "
"Help users with their notes, tasks, and general questions. " "Help users with their notes, tasks, and general questions. "
"When note context is provided, use it to give relevant answers.\n\n" "When note context is provided, use it to give relevant answers.\n\n"
f"{tool_guidance}" f"{tool_guidance}"
@@ -91,7 +91,7 @@ async def notify_security_event(
</table> </table>
<p style="margin:16px 0 0;color:#9ca3af;font-size:12px;">If this wasn't you, change your password immediately.</p> <p style="margin:16px 0 0;color:#9ca3af;font-size:12px;">If this wasn't you, change your password immediately.</p>
""" """
await send_email(email, f"Fabled Assistant - {label}", _email_html("Security Alert", body)) await send_email(email, f"Fabled Scribe - {label}", _email_html("Security Alert", body))
except Exception: except Exception:
logger.exception("Failed to send security notification for user %d", user_id) logger.exception("Failed to send security notification for user %d", user_id)
@@ -113,7 +113,7 @@ async def send_password_reset_email(email: str, reset_url: str) -> None:
<p style="margin:0;color:#9ca3af;font-size:12px;">If the button doesn't work, copy and paste this link:</p> <p style="margin:0;color:#9ca3af;font-size:12px;">If the button doesn't work, copy and paste this link:</p>
<p style="margin:4px 0 0;color:#9ca3af;font-size:12px;word-break:break-all;">{reset_url}</p> <p style="margin:4px 0 0;color:#9ca3af;font-size:12px;word-break:break-all;">{reset_url}</p>
""" """
await send_email(email, "Fabled Assistant - Password Reset", _email_html("Password Reset", body)) await send_email(email, "Fabled Scribe - Password Reset", _email_html("Password Reset", body))
async def send_password_reset_success_email(email: str) -> None: async def send_password_reset_success_email(email: str) -> None:
@@ -125,14 +125,14 @@ async def send_password_reset_success_email(email: str) -> None:
</p> </p>
<p style="margin:0;color:#6b7280;font-size:13px;">If you didn't make this change, please contact your administrator immediately.</p> <p style="margin:0;color:#6b7280;font-size:13px;">If you didn't make this change, please contact your administrator immediately.</p>
""" """
await send_email(email, "Fabled Assistant - Password Changed", _email_html("Password Changed", body)) await send_email(email, "Fabled Scribe - Password Changed", _email_html("Password Changed", body))
async def send_invitation_email(email: str, invite_url: str, invited_by_username: str) -> None: async def send_invitation_email(email: str, invite_url: str, invited_by_username: str) -> None:
"""Send a branded invitation email with a registration link.""" """Send a branded invitation email with a registration link."""
body = f""" body = f"""
<p style="margin:0 0 16px;color:#374151;font-size:15px;"> <p style="margin:0 0 16px;color:#374151;font-size:15px;">
<strong>{invited_by_username}</strong> has invited you to join Fabled Assistant. <strong>{invited_by_username}</strong> has invited you to join Fabled Scribe.
Click the button below to create your account. Click the button below to create your account.
</p> </p>
<div style="text-align:center;margin:24px 0;"> <div style="text-align:center;margin:24px 0;">
@@ -146,7 +146,7 @@ async def send_invitation_email(email: str, invite_url: str, invited_by_username
<p style="margin:0;color:#9ca3af;font-size:12px;">If the button doesn't work, copy and paste this link:</p> <p style="margin:0;color:#9ca3af;font-size:12px;">If the button doesn't work, copy and paste this link:</p>
<p style="margin:4px 0 0;color:#9ca3af;font-size:12px;word-break:break-all;">{invite_url}</p> <p style="margin:4px 0 0;color:#9ca3af;font-size:12px;word-break:break-all;">{invite_url}</p>
""" """
await send_email(email, "Fabled Assistant - You're Invited!", _email_html("You're Invited!", body)) await send_email(email, "Fabled Scribe - You're Invited!", _email_html("You're Invited!", body))
async def check_due_tasks() -> None: async def check_due_tasks() -> None:
@@ -225,7 +225,7 @@ async def check_due_tasks() -> None:
{task_rows} {task_rows}
</table> </table>
""" """
await send_email(email, f"Fabled Assistant - {len(user_tasks)} Task(s) Due", _email_html("Task Reminders", body)) await send_email(email, f"Fabled Scribe - {len(user_tasks)} Task(s) Due", _email_html("Task Reminders", body))
await log_audit( await log_audit(
"task_reminder", "task_reminder",
user_id=user_id, user_id=user_id,