diff --git a/components/settings/EmailDigestToggle.tsx b/components/settings/EmailDigestToggle.tsx
new file mode 100644
index 00000000..0abc0ca0
--- /dev/null
+++ b/components/settings/EmailDigestToggle.tsx
@@ -0,0 +1,95 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+import { useTranslations } from 'next-intl'
+import { Switch } from '@/components/ui/switch'
+import { useToast } from '@/components/ui/use-toast'
+import { SettingsGroup, SettingsRow } from '@/components/settings/SettingsRows'
+import { createClient } from '@/lib/supabase/client'
+
+/**
+ * Per-user opt-in for the daily "nytt att bokfora" email digest
+ * (notification_settings.email_digest_enabled, default false; consumed by
+ * the bookkeeping-digest cron). Lives on the core account tab: the
+ * push-notifications extension has its own settings panel with the same
+ * toggle, but that extension is not enabled on hosted, so this is the
+ * reachable switch.
+ */
+export function EmailDigestToggle() {
+ const t = useTranslations('settings')
+ const { toast } = useToast()
+ const supabase = createClient()
+ const [enabled, setEnabled] = useState(false)
+ const [loading, setLoading] = useState(true)
+ const [saving, setSaving] = useState(false)
+
+ useEffect(() => {
+ let active = true
+ ;(async () => {
+ try {
+ const { data: { user } } = await supabase.auth.getUser()
+ if (!user) return
+ const { data } = await supabase
+ .from('notification_settings')
+ .select('email_digest_enabled')
+ .eq('user_id', user.id)
+ .maybeSingle()
+ if (active) setEnabled(data?.email_digest_enabled === true)
+ } catch (err) {
+ // Leave the default (off); a failed read must not block the page.
+ console.error('Could not read email digest setting:', err)
+ } finally {
+ if (active) setLoading(false)
+ }
+ })()
+ return () => {
+ active = false
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
+
+ async function handleChange(next: boolean) {
+ setEnabled(next)
+ setSaving(true)
+ try {
+ const { data: { user } } = await supabase.auth.getUser()
+ if (!user) throw new Error('Not signed in')
+ // Upsert on user_id: most users have no notification_settings row
+ // until they touch a notification preference for the first time.
+ const { error } = await supabase
+ .from('notification_settings')
+ .upsert(
+ { user_id: user.id, email_digest_enabled: next },
+ { onConflict: 'user_id' },
+ )
+ if (error) throw new Error(error.message)
+ toast({
+ title: next
+ ? t('digest_enabled_toast')
+ : t('digest_disabled_toast'),
+ })
+ } catch (err) {
+ console.error('Could not save email digest setting:', err)
+ setEnabled(!next)
+ toast({ title: t('digest_save_failed'), variant: 'destructive' })
+ } finally {
+ setSaving(false)
+ }
+ }
+
+ return (
+
+
+ void handleChange(value)}
+ disabled={loading || saving}
+ />
+
+
+
+ )
+}
diff --git a/components/settings/sections/AccountSettingsContent.tsx b/components/settings/sections/AccountSettingsContent.tsx
index 6d339758..9d6a089c 100644
--- a/components/settings/sections/AccountSettingsContent.tsx
+++ b/components/settings/sections/AccountSettingsContent.tsx
@@ -9,6 +9,7 @@ import { Sun, Moon, Monitor, LogOut, ExternalLink } from 'lucide-react'
import { useTheme } from 'next-themes'
import { createClient } from '@/lib/supabase/client'
import { SecuritySettings } from '@/components/settings/SecuritySettings'
+import { EmailDigestToggle } from '@/components/settings/EmailDigestToggle'
import { InstallAppSection } from '@/components/settings/InstallAppSection'
import { CalendarFeedSettings } from '@/components/settings/CalendarFeedSettings'
import { AccountDangerZone } from '@/components/settings/AccountDangerZone'
@@ -335,6 +336,9 @@ export function AccountSettingsContent() {
{/* Security: BankID, password, 2FA (renders its own group) */}
+ {/* Notifications: daily "nytt att bokfora" email digest opt-in */}
+
+
{/* Calendar feed (extension-gated) */}
{hasCalendarExtension && }
diff --git a/messages/en.json b/messages/en.json
index 2b033409..5f437869 100644
--- a/messages/en.json
+++ b/messages/en.json
@@ -582,6 +582,13 @@
"settings": {
"group_profile": "Profile",
"section_name": "Name",
+ "digest_group": "Notifications",
+ "digest_label": "New items to book",
+ "digest_description": "A daily email when new bank transactions or inbox documents are waiting to be booked. Counts only, never amounts.",
+ "digest_switch_label": "Daily summary by email",
+ "digest_enabled_toast": "Daily summary enabled",
+ "digest_disabled_toast": "Daily summary disabled",
+ "digest_save_failed": "Could not save the setting",
"name_label": "Your name",
"name_description": "Used when we address you and shown as the contact person on some documents.",
"name_placeholder": "First name Last name",
diff --git a/messages/sv.json b/messages/sv.json
index 588ac569..ec92336f 100644
--- a/messages/sv.json
+++ b/messages/sv.json
@@ -582,6 +582,13 @@
"settings": {
"group_profile": "Profil",
"section_name": "Namn",
+ "digest_group": "Aviseringar",
+ "digest_label": "Nytt att bokföra",
+ "digest_description": "Ett dagligt mejl när nya banktransaktioner eller underlag i inkorgen väntar på bokföring. Endast antal, aldrig belopp.",
+ "digest_switch_label": "Daglig sammanfattning via e-post",
+ "digest_enabled_toast": "Daglig sammanfattning aktiverad",
+ "digest_disabled_toast": "Daglig sammanfattning avstängd",
+ "digest_save_failed": "Kunde inte spara inställningen",
"name_label": "Ditt namn",
"name_description": "Används när vi tilltalar dig och visas som kontaktperson på vissa underlag.",
"name_placeholder": "Förnamn Efternamn",