diff --git a/Cargo.lock b/Cargo.lock
index 2c5bbb9..f666c06 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -339,9 +339,9 @@ dependencies = [
 
 [[package]]
 name = "bberry"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9413ba3ccb3dfc908093b3e2cdb7b39acc2127fe0b29268df4708cfa06c6ce30"
+checksum = "d73b8674872fdd2eb09463fc9e3d15c4510a3abd8a1f8ef0a9e918065913aed5"
 
 [[package]]
 name = "bit_field"
diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml
index 15e868f..117a1cb 100644
--- a/crates/app/Cargo.toml
+++ b/crates/app/Cargo.toml
@@ -48,4 +48,4 @@ async-stripe = { version = "0.41.0", features = [
 ] }
 emojis = "0.6.4"
 webp = "0.3.0"
-bberry = "0.1.1"
+bberry = "0.1.2"
diff --git a/crates/app/src/assets.rs b/crates/app/src/assets.rs
index e5be918..121e3a3 100644
--- a/crates/app/src/assets.rs
+++ b/crates/app/src/assets.rs
@@ -36,7 +36,7 @@ pub const ME_JS: &str = include_str!("./public/js/me.js");
 pub const STREAMS_JS: &str = include_str!("./public/js/streams.js");
 
 // html
-pub const ROOT: &str = include_str!("./public/html/root.html");
+pub const ROOT: &str = include_str!("./public/html/root.lisp");
 pub const MACROS: &str = include_str!("./public/html/macros.html");
 pub const COMPONENTS: &str = include_str!("./public/html/components.html");
 
@@ -140,7 +140,13 @@ pub(crate) async fn pull_icon(icon: &str, icons_dir: &str) {
     }
 
     println!("download icon: {icon}");
-    let svg = reqwest::get(icon_url).await.unwrap().text().await.unwrap();
+    let svg = reqwest::get(icon_url)
+        .await
+        .unwrap()
+        .text()
+        .await
+        .unwrap()
+        .replace("\n", "");
 
     write(&file_path, &svg).unwrap();
     writer.insert(icon.to_string(), svg);
@@ -245,7 +251,7 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
     // ...
     let html_path = PathBufD::current().join(&config.dirs.templates);
 
-    write_template!(html_path->"root.html"(crate::assets::ROOT) --config=config);
+    write_template!(html_path->"root.html"(crate::assets::ROOT) --config=config --lisp);
     write_template!(html_path->"macros.html"(crate::assets::MACROS) --config=config);
     write_template!(html_path->"components.html"(crate::assets::COMPONENTS) --config=config);
 
diff --git a/crates/app/src/public/html/misc/error.lisp b/crates/app/src/public/html/misc/error.lisp
index 1a46af0..e7b4f16 100644
--- a/crates/app/src/public/html/misc/error.lisp
+++ b/crates/app/src/public/html/misc/error.lisp
@@ -3,24 +3,24 @@
 (text "{% endblock %} {% block body %} {{ macros::nav() }}")
 
 (main
-    (: "class" "flex flex-col gap-2")
+    ("class" "flex flex-col gap-2")
     (div
-        (: "class" "card-nest")
+        ("class" "card-nest")
         (div
-            (: "class" "card")
+            ("class" "card")
             (b (text "Error 😦")))
 
         (div
-            (: "class" "card flex flex-col gap-4")
+            ("class" "card flex flex-col gap-4")
             (span (text "{{ error_text }}"))
 
             (div
-                (: "class" "w-full flex gap-2")
+                ("class" "w-full flex gap-2")
                 (a
-                    (: "class" "button primary") (: "href" "/")
+                    ("class" "button primary") ("href" "/")
                     (text "Home"))
                 (a
-                    (: "class" "button secondary") (: "href" "javascript:history.back()")
+                    ("class" "button secondary") ("href" "javascript:history.back()")
                     (text "Back"))))))
 
 (text "{% endblock %}")
diff --git a/crates/app/src/public/html/misc/markdown.lisp b/crates/app/src/public/html/misc/markdown.lisp
index f4312c9..2296fcd 100644
--- a/crates/app/src/public/html/misc/markdown.lisp
+++ b/crates/app/src/public/html/misc/markdown.lisp
@@ -3,18 +3,18 @@
 (text "{% endblock %} {% block body %} {{ macros::nav() }}")
 
 (main
-    (: "class" "flex flex-col gap-2")
+    ("class" "flex flex-col gap-2")
     (div
-        (: "class" "card-nest")
+        ("class" "card-nest")
         (div
-            (: "class" "card small flex items-center justify-between gap-2")
+            ("class" "card small flex items-center justify-between gap-2")
             (span
-                (: "class" "flex items-center gap-2")
+                ("class" "flex items-center gap-2")
                 (text "{{ icon scroll-text }}")
                 (span (text "{{ file_name }}"))))
 
         (div
-            (: "class" "card")
+            ("class" "card")
             (span (text "{{ file|markdown|safe }}")))))
 
 (text "{% endblock %}")
diff --git a/crates/app/src/public/html/root.html b/crates/app/src/public/html/root.html
deleted file mode 100644
index 5365c67..0000000
--- a/crates/app/src/public/html/root.html
+++ /dev/null
@@ -1,424 +0,0 @@
-{%- import "components.html" as components -%} {%- import "macros.html" as
-macros -%}
-<!doctype html>
-<html lang="en">
-    <head>
-        <meta charset="UTF-8" />
-        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
-
-        <meta
-            http-equiv="content-security-policy"
-            content="default-src 'self' blob: *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' blob: *; script-src 'self' 'unsafe-inline' blob: *; object-src 'self' blob: *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: data: *"
-        />
-
-        <link rel="icon" href="/public/favicon.svg" />
-
-        <link rel="stylesheet" href="/css/style.css" />
-
-        {% if user -%}
-        <script>
-            window.localStorage.setItem(
-                "tetratto:theme",
-                "{{ user.settings.theme_preference }}",
-            );
-        </script>
-        {%- endif %}
-
-        <script src="/js/loader.js"></script>
-        <script defer async src="/js/atto.js"></script>
-
-        <script>
-            globalThis.ns_verbose = false;
-            globalThis.ns_config = {
-                root: "/js/",
-                verbose: globalThis.ns_verbose,
-                version: "cache-breaker-{{ random_cache_breaker }}",
-            };
-
-            globalThis._app_base = {
-                name: "tetratto",
-                ns_store: {},
-                classes: {},
-            };
-
-            globalThis.no_policy = false;
-        </script>
-
-        <meta name="theme-color" content="{{ config.color }}" />
-        <meta name="description" content="{{ config.description }}" />
-        <meta property="og:type" content="website" />
-        <meta property="og:site_name" content="{{ config.name }}" />
-
-        <meta name="turbo-prefetch" content="false" />
-        <meta name="turbo-refresh-method" content="morph" />
-        <meta name="turbo-refresh-scroll" content="preserve" />
-
-        <script
-            src="https://unpkg.com/@hotwired/turbo@8.0.5/dist/turbo.es2017-esm.js"
-            type="module"
-            async
-            defer
-        ></script>
-
-        {% block head %}{% endblock %}
-    </head>
-
-    <body>
-        <div id="toast_zone"></div>
-
-        <div id="page">
-            <!-- prettier-ignore -->
-            {% if user and user.id == 0 -%}
-            <article>
-                <main>
-                    <div class="card-nest">
-                        <div class="card small flex items-center gap-2 red">
-                            {{ icon "frown" }}
-                            <span
-                                >{{ text "general:label.account_banned" }}</span
-                            >
-                        </div>
-
-                        <div class="card">
-                            <span
-                                >{{ text "general:label.account_banned_body"
-                                }}</span
-                            >
-                        </div>
-                    </div>
-                </main>
-            </article>
-            {% else %} {% block body %}{% endblock %} {%- endif %}
-            <!-- html_footer_goes_here -->
-        </div>
-
-        <script data-turbo-permanent="true" id="init-script">
-            document.documentElement.addEventListener("turbo:load", () => {
-                const atto = ns("atto");
-
-                atto.disconnect_observers();
-                atto.remove_false_options();
-                atto.clean_date_codes();
-                atto.link_filter();
-
-                atto["hooks::scroll"](document.body, document.documentElement);
-                atto["hooks::dropdown.init"](window);
-                atto["hooks::character_counter.init"]();
-                atto["hooks::long_text.init"]();
-                atto["hooks::alt"]();
-                atto["hooks::online_indicator"]();
-                atto["hooks::ips"]();
-                atto["hooks::check_reactions"]();
-                atto["hooks::tabs"]();
-                atto["hooks::spotify_time_text"](); // spotify durations
-                atto["hooks::verify_emoji"]();
-
-                if (document.getElementById("tokens")) {
-                    trigger("me::render_token_picker", [
-                        document.getElementById("tokens"),
-                    ]);
-                }
-
-                setTimeout(() => {
-                    trigger("me::notifications_stream");
-                }, 250);
-            });
-        </script>
-
-        {% if user -%}
-        <script data-turbo-permanent="true" id="update-seen-script">
-            document.documentElement.addEventListener("turbo:load", () => {
-                trigger("me::seen");
-                trigger("streams::user", ["{{ user.id }}"]);
-
-                if (!window.location.pathname.startsWith("/chats/")) {
-                    if (window.socket) {
-                        window.socket.send("Close");
-                        window.socket = undefined;
-                        console.log("socket disconnect");
-                    }
-                }
-            });
-        </script>
-        {%- endif %}
-
-        <!-- dialogs -->
-        <dialog id="link_filter">
-            <div class="inner flex flex-col gap-2">
-                <p>Pressing continue will bring you to the following URL:</p>
-                <pre><code id="link_filter_url"></code></pre>
-                <p>Are sure you want to go there?</p>
-
-                <hr class="margin" />
-                <div class="flex gap-2">
-                    <a
-                        class="button primary"
-                        id="link_filter_continue"
-                        rel="noopener noreferrer"
-                        target="_blank"
-                        onclick="document.getElementById('link_filter').close()"
-                    >
-                        {{ icon "external-link" }}
-                        <span>{{ text "dialog:action.continue" }}</span>
-                    </a>
-                    <button
-                        class="secondary"
-                        type="button"
-                        onclick="document.getElementById('link_filter').close()"
-                    >
-                        {{ icon "x" }}
-                        <span>{{ text "dialog:action.cancel" }}</span>
-                    </button>
-                </div>
-            </div>
-        </dialog>
-
-        <dialog id="web_api_prompt">
-            <div class="inner flex flex-col gap-2">
-                <form
-                    class="flex gap-2 flex-col"
-                    onsubmit="event.preventDefault()"
-                >
-                    <label for="prompt" id="web_api_prompt:msg"></label>
-                    <input id="prompt" name="prompt" />
-
-                    <div class="flex justify-between">
-                        <div></div>
-
-                        <div class="flex gap-2">
-                            <button
-                                class="primary bold circle"
-                                onclick="globalThis.web_api_prompt_submit(document.getElementById('prompt').value); document.getElementById('prompt').value = ''"
-                                type="button"
-                            >
-                                {{ icon "check" }} {{ text "dialog:action.okay"
-                                }}
-                            </button>
-
-                            <button
-                                class="bold red camo"
-                                onclick="globalThis.web_api_prompt_submit('')"
-                                type="button"
-                            >
-                                {{ icon "x" }} {{ text "dialog:action.cancel" }}
-                            </button>
-                        </div>
-                    </div>
-                </form>
-            </div>
-        </dialog>
-
-        <dialog id="web_api_prompt_long">
-            <div class="inner flex flex-col gap-2">
-                <form
-                    class="flex gap-2 flex-col"
-                    onsubmit="event.preventDefault()"
-                >
-                    <label
-                        for="prompt_long"
-                        id="web_api_prompt_long:msg"
-                    ></label>
-                    <textarea id="prompt_long" name="prompt_long"></textarea>
-
-                    <div class="flex justify-between">
-                        <div></div>
-
-                        <div class="flex gap-2">
-                            <button
-                                class="primary bold circle"
-                                onclick="globalThis.web_api_prompt_long_submit(document.getElementById('prompt_long').value); document.getElementById('prompt_long').value = ''"
-                                type="button"
-                            >
-                                {{ icon "check" }} {{ text "dialog:action.okay"
-                                }}
-                            </button>
-
-                            <button
-                                class="bold red camo"
-                                onclick="globalThis.web_api_prompt_long_submit('')"
-                                type="button"
-                            >
-                                {{ icon "x" }} {{ text "dialog:action.cancel" }}
-                            </button>
-                        </div>
-                    </div>
-                </form>
-            </div>
-        </dialog>
-
-        <dialog id="web_api_confirm">
-            <div class="inner flex flex-col gap-2">
-                <form
-                    class="flex gap-2 flex-col"
-                    onsubmit="event.preventDefault()"
-                >
-                    <label id="web_api_confirm:msg"></label>
-
-                    <div class="flex justify-between">
-                        <div></div>
-
-                        <div class="flex gap-2">
-                            <button
-                                class="primary bold circle"
-                                onclick="globalThis.web_api_confirm_submit(true)"
-                                type="button"
-                            >
-                                {{ icon "check" }} {{ text "dialog:action.yes"
-                                }}
-                            </button>
-
-                            <button
-                                class="bold red camo"
-                                onclick="globalThis.web_api_confirm_submit(false)"
-                                type="button"
-                            >
-                                {{ icon "x" }} {{ text "dialog:action.no" }}
-                            </button>
-                        </div>
-                    </div>
-                </form>
-            </div>
-        </dialog>
-
-        <div class="lightbox hidden" id="lightbox">
-            <button
-                class="lightbox_exit small square quaternary red"
-                onclick="trigger('ui::lightbox_close')"
-            >
-                {{ icon "x" }}
-            </button>
-
-            <a href="" id="lightbox_img_a" target="_blank">
-                <img src="" alt="Image" id="lightbox_img" />
-            </a>
-        </div>
-
-        {% if user -%}
-        <dialog id="tokens_dialog">
-            <div class="inner flex flex-col gap-2">
-                <form
-                    class="flex gap-2 flex-col"
-                    onsubmit="event.preventDefault()"
-                >
-                    <div id="tokens" style="display: contents"></div>
-
-                    <a href="/auth/login" class="button" data-turbo="false">
-                        {{ icon "plus" }}
-                        <span>{{ text "general:action.add_account" }}</span>
-                    </a>
-
-                    <div class="flex justify-between">
-                        <div></div>
-
-                        <div class="flex gap-2">
-                            <button
-                                class="quaternary"
-                                onclick="document.getElementById('tokens_dialog').close()"
-                                type="button"
-                            >
-                                {{ icon "check" }}
-                                <span>{{ text "dialog:action.okay" }}</span>
-                            </button>
-                        </div>
-                    </div>
-                </form>
-            </div>
-        </dialog>
-        {%- endif %} {% if user and use_user_theme -%} {{
-        components::theme(user=user,
-        theme_preference=user.settings.theme_preference) }}
-        <script>
-            setTimeout(() => {
-                trigger("atto::use_theme_preference");
-            }, 150);
-        </script>
-        {%- endif %} {% if user and user.connections.Spotify and
-        config.connections.spotify_client_id and
-        user.connections.Spotify[0].data.token and
-        user.connections.Spotify[0].data.refresh_token %}
-        <script>
-            setTimeout(async () => {
-                if (window.spotify_init) {
-                    return;
-                }
-
-                window.spotify_init = true;
-                const client_id = "{{ config.connections.spotify_client_id }}";
-                let token = "{{ user.connections.Spotify[0].data.token }}";
-                let refresh_token =
-                    "{{ user.connections.Spotify[0].data.refresh_token }}";
-
-                if (token) {
-                    // we already have a token
-                    const pull_playing = async () => {
-                        const playing = await trigger("spotify::get_playing", [
-                            token,
-                        ]);
-
-                        if (playing.error) {
-                            // refresh token
-                            const [new_token, new_refresh_token, expires_in] =
-                                await trigger("spotify::refresh_token", [
-                                    client_id,
-                                    refresh_token,
-                                ]);
-
-                            await trigger("connections::push_con_data", [
-                                "Spotify",
-                                {
-                                    token: new_token,
-                                    expires_in: expires_in.toString(),
-                                    name: profile.display_name,
-                                },
-                            ]);
-
-                            token = new_token;
-                            refresh_token = new_refresh_token;
-                            return;
-                        }
-
-                        await trigger("spotify::publish_playing", [playing]);
-                    };
-
-                    await pull_playing();
-                    setInterval(pull_playing, 30_000);
-                } else {
-                    window.spotify_needs_token = true;
-                }
-            }, 150);
-        </script>
-        {% elif user and user.connections.LastFm and
-        config.connections.last_fm_key and
-        user.connections.LastFm[0].data.session_token %}
-        <script>
-            setTimeout(async () => {
-                if (window.last_fm_init) {
-                    return;
-                }
-
-                window.last_fm_init = true;
-                const user = "{{ user.connections.LastFm[0].data.name }}";
-                const session_token =
-                    "{{ user.connections.LastFm[0].data.session_token }}";
-
-                if (session_token) {
-                    // we already have a token
-                    const pull_playing = async () => {
-                        const playing = await trigger("last_fm::get_playing", [
-                            user,
-                            session_token,
-                        ]);
-                        await trigger("last_fm::publish_playing", [playing]);
-                    };
-
-                    await pull_playing();
-                    setInterval(pull_playing, 30_000);
-                } else {
-                    window.last_fm_needs_token = true;
-                }
-            }, 150);
-        </script>
-        {%- endif %}
-    </body>
-</html>
diff --git a/crates/app/src/public/html/root.lisp b/crates/app/src/public/html/root.lisp
new file mode 100644
index 0000000..d83d92a
--- /dev/null
+++ b/crates/app/src/public/html/root.lisp
@@ -0,0 +1,381 @@
+(text "{%- import \"components.html\" as components -%} {%- import \"macros.html\" as macros -%}")
+(text "<!doctype html>")
+
+(html
+    ("lang" "en")
+    (head
+        (meta ("charset" "UTF-8"))
+        (meta ("name" "viewport") ("content" "width=device-width, initial-scale=1.0"))
+        (meta ("http-equiv" "X-UA-Compatible") ("content" "ie=edge"))
+        (meta ("http-equiv" "content-security-policy") ("content" "default-src 'self' blob: *.spotify.com musicbrainz.org; img-src * data:; media-src *; font-src *; style-src 'unsafe-inline' 'self' blob: *; script-src 'self' 'unsafe-inline' blob: *; object-src 'self' blob: *; upgrade-insecure-requests; connect-src * localhost; frame-src 'self' blob: data: *"))
+
+        (link ("rel" "icon") ("href" "/public/favicon.svg"))
+        (link ("rel" "stylesheet") ("href" "/css/style.css"))
+
+        (text "{% if user -%}
+        <script>
+            window.localStorage.setItem(
+                \"tetratto:theme\",
+                \"{{ user.settings.theme_preference }}\",
+            );
+        </script>
+        {%- endif %}")
+
+        (text "<script>
+            globalThis.ns_verbose = false;
+            globalThis.ns_config = {
+                root: \"/js/\",
+                verbose: globalThis.ns_verbose,
+                version: \"cache-breaker-{{ random_cache_breaker }}\",
+            };
+
+            globalThis._app_base = {
+                name: \"tetratto\",
+                ns_store: {},
+                classes: {},
+            };
+
+            globalThis.no_policy = false;
+        </script>")
+
+        (script ("src" "/js/loader.js" ))
+        (script ("src" "/js/atto.js" ))
+
+        (meta ("name" "theme-color") ("content" "{{ config.color }}"))
+        (meta ("name" "description") ("content" "{{ config.description }}"))
+        (meta ("property" "og:type") ("content" "website"))
+        (meta ("property" "og:site_name") ("content" "{{ config.color }}"))
+
+        (meta ("name" "turbo-prefetch") ("content" "false"))
+        (meta ("name" "turbo-refresh-method") ("content" "morph"))
+        (meta ("name" "turbo-refresh-scroll") ("content" "preserve"))
+
+        (script ("src" "https://unpkg.com/@hotwired/turbo@8.0.5/dist/turbo.es2017-esm.js") ("type" "module") ("async" "") ("defer" ""))
+
+        (text "{% block head %}{% endblock %}"))
+
+    (body
+        (div ("id" "toast_zone"))
+
+        (div
+            ("id" "page")
+            (text "{% if user and user.id == 0 -%}")
+            ; account banned message
+            (article
+                (main
+                    (div
+                        ("class" "card-nest")
+                        (div
+                            ("class" "card small flex items-center gap-2 red")
+                            (text "{{ icon \"frown\" }}")
+                            (span (text "{{ text \"general:label.account_banned\" }}")))
+
+                        (div
+                            ("class" "card")
+                            (span (text "{{ text \"general:label.account_banned_body\" }}"))))))
+
+            ; if we aren't banned, just show the page body
+            (text "{% else %} {% block body %}{% endblock %} {%- endif %}")
+            (text "<!-- html_footer_goes_here -->"))
+
+        ; random js
+        (text "<script data-turbo-permanent=\"true\" id=\"init-script\">
+            document.documentElement.addEventListener(\"turbo:load\", () => {
+                const atto = ns(\"atto\");
+
+                atto.disconnect_observers();
+                atto.remove_false_options();
+                atto.clean_date_codes();
+                atto.link_filter();
+
+                atto[\"hooks::scroll\"](document.body, document.documentElement);
+                atto[\"hooks::dropdown.init\"](window);
+                atto[\"hooks::character_counter.init\"]();
+                atto[\"hooks::long_text.init\"]();
+                atto[\"hooks::alt\"]();
+                atto[\"hooks::online_indicator\"]();
+                atto[\"hooks::ips\"]();
+                atto[\"hooks::check_reactions\"]();
+                atto[\"hooks::tabs\"]();
+                atto[\"hooks::spotify_time_text\"](); // spotify durations
+                atto[\"hooks::verify_emoji\"]();
+
+                if (document.getElementById(\"tokens\")) {
+                    trigger(\"me::render_token_picker\", [
+                        document.getElementById(\"tokens\"),
+                    ]);
+                }
+
+                setTimeout(() => {
+                    trigger(\"me::notifications_stream\");
+                }, 250);
+            });
+        </script>")
+
+        (text "{% if user -%}
+        <script data-turbo-permanent=\"true\" id=\"update-seen-script\">
+            document.documentElement.addEventListener(\"turbo:load\", () => {
+                trigger(\"me::seen\");
+                trigger(\"streams::user\", [\"{{ user.id }}\"]);
+
+                if (!window.location.pathname.startsWith(\"/chats/\")) {
+                    if (window.socket) {
+                        window.socket.send(\"Close\");
+                        window.socket = undefined;
+                        console.log(\"socket disconnect\");
+                    }
+                }
+            });
+        </script>
+        {%- endif %}")
+
+        ; dialogs
+        (dialog
+            ("id" "link_filter")
+            (div
+                ("class" "inner flex flex-col gap-2")
+
+                ; warning stuff
+                (p (text "Pressing continue will bring you to the following URL:"))
+                (pre (code ("id" "link_filter_url")))
+                (p (text "Are sure you want to go there?"))
+
+                (hr ("class" "margin"))
+                (div
+                    ("class" "flex gap-2")
+
+                    (a
+                        ("class" "button primary")
+                        ("id" "link_filter_continue")
+                        ("rel" "noopener noreferrer")
+                        ("target" "_blank")
+                        ("onclick", "document.getElementById('link_filter').close()")
+                        (text "{{ icon \"external-link\" }}")
+                        (span (text "{{ text \"dialog:action.continue\" }}")))
+
+                    (button
+                        ("class" "secondary")
+                        ("type" "button")
+                        ("onclick", "document.getElementById('link_filter').close()")
+                        (text "{{ icon \"x\" }}" )
+                        (span (text "{{ text \"dialog:action.cancel\" }}"))))))
+
+        (dialog
+            ("id" "web_api_prompt")
+            (div
+                ("class" "inner flex flex-col gap-2")
+                (form
+                    ("class" "flex gap-2 flex-col")
+                    ("onsubmit" "event.preventDefault()")
+                    (label ("for" "prompt") ("id" "web_api_prompt:msg"))
+                    (input ("id" "prompt") ("name" "prompt"))
+
+                    (div
+                        ("class" "flex justify-between")
+                        (div null?)
+                        (div
+                            ("class" "flex gap-2")
+                            (button
+                                ("class" "primary bold circle")
+                                ("onclick", "globalThis.web_api_prompt_submit(document.getElementById('prompt').value); document.getElementById('prompt').value = ''")
+                                ("type" "button")
+                                (text "{{ icon \"check\" }}")
+                                (text "{{ text \"dialog:action.okay\" }}"))
+
+                            (button
+                                ("class" "bold red camo")
+                                ("onclick", "globalThis.web_api_prompt_submit('')")
+                                ("type" "button")
+                                (text "{{ icon \"x\" }}")
+                                (text "{{ text \"dialog:action.cancel\" }}")))))))
+
+        (dialog
+            ("id" "web_api_prompt_long")
+            (div
+                ("class" "inner flex flex-col gap-2")
+                (form
+                    ("class" "flex gap-2 flex-col")
+                    ("onsubmit" "event.preventDefault()")
+                    (label ("for" "prompt_long") ("id" "web_api_prompt_long:msg"))
+                    (input ("id" "prompt_long") ("name" "prompt_long"))
+
+                    (div
+                        ("class" "flex justify-between")
+                        (div null?)
+                        (div
+                            ("class" "flex gap-2")
+                            (button
+                                ("class" "primary bold circle")
+                                ("onclick", "globalThis.web_api_prompt_long_submit(document.getElementById('prompt_long').value); document.getElementById('prompt_long').value = ''")
+                                ("type" "button")
+                                (text "{{ icon \"check\" }}")
+                                (text "{{ text \"dialog:action.okay\" }}"))
+
+                            (button
+                                ("class" "bold red camo")
+                                ("onclick", "globalThis.web_api_prompt_long_submit('')")
+                                ("type" "button")
+                                (text "{{ icon \"x\" }}")
+                                (text "{{ text \"dialog:action.cancel\" }}")))))))
+
+        (dialog
+            ("id" "web_api_confirm")
+            (div
+                ("class" "inner flex flex-col gap-2")
+                (form
+                    ("class" "flex gap-2 flex-col")
+                    ("onsubmit" "event.preventDefault()")
+                    (span ("id" "web_api_confirm:msg"))
+
+                    (div
+                        ("class" "flex justify-between")
+                        (div null?)
+                        (div
+                            ("class" "flex gap-2")
+                            (button
+                                ("class" "primary bold circle")
+                                ("onclick", "globalThis.web_api_confirm_submit(true)")
+                                ("type" "button")
+                                (text "{{ icon \"check\" }}")
+                                (text "{{ text \"dialog:action.yes\" }}"))
+
+                            (button
+                                ("class" "bold red camo")
+                                ("onclick", "globalThis.web_api_confirm_submit(false)")
+                                ("type" "button")
+                                (text "{{ icon \"x\" }}")
+                                (text "{{ text \"dialog:action.no\" }}")))))))
+
+        (div
+            ("class" "lightbox hidden")
+            ("id" "lightbox")
+            (button
+                ("class" "lightbox_exit small square quaternary red")
+                ("onclick" "trigger('ui::lightbox_close')")
+                (text "{{ icon \"x\" }}"))
+
+            (a
+                ("href" "")
+                ("id" "lightbox_img_a")
+                ("target" "_blank")))
+
+        ; tokens dialog
+        (text "{% if user -%}")
+        (dialog
+            ("id" "tokens_dialog")
+            (div
+                ("class" "inner flex flex-col gap-2")
+                (form
+                    ("class" "flex gap-2 flex-col")
+                    ("onsubmit" "event.preventDefault()")
+                    (div ("id" "tokens") ("style" "display: contents"))
+
+                    (a
+                        ("href" "/auth/login")
+                        ("class" "button")
+                        ("data-turbo", "false")
+                        (text "{{ icon \"plus\" }}")
+                        (span (text "{{ text \"general:action.add_account\" }}")))
+
+                    (div
+                        ("class" "flex justify-between")
+                        (div null?)
+
+                        (div
+                            ("class" "flex gap-2")
+                            (button
+                                ("class" "quaternary")
+                                ("onclick" "document.getElementById('tokens_dialog').close()")
+                                ("type" "button")
+                                (text "{{ icon \"check \" }}")
+                                (span "{{ text \"dialog:action.okay\" }}")))))))
+
+        ; user scripts
+        (text "{%- endif %} {% if user and use_user_theme -%} {{ components::theme(user=user, theme_preference=user.settings.theme_preference) }}
+        <script>
+            setTimeout(() => {
+                trigger(\"atto::use_theme_preference\");
+            }, 150);
+        </script>
+        {%- endif %} {% if user and user.connections.Spotify and config.connections.spotify_client_id and user.connections.Spotify[0].data.token and user.connections.Spotify[0].data.refresh_token %}
+        <script>
+            setTimeout(async () => {
+                if (window.spotify_init) {
+                    return;
+                }
+
+                window.spotify_init = true;
+                const client_id = \"{{ config.connections.spotify_client_id }}\";
+                let token = \"{{ user.connections.Spotify[0].data.token }}\";
+                let refresh_token =
+                    \"{{ user.connections.Spotify[0].data.refresh_token }}\";
+
+                if (token) {
+                    // we already have a token
+                    const pull_playing = async () => {
+                        const playing = await trigger(\"spotify::get_playing\", [
+                            token,
+                        ]);
+
+                        if (playing.error) {
+                            // refresh token
+                            const [new_token, new_refresh_token, expires_in] =
+                                await trigger(\"spotify::refresh_token\", [
+                                    client_id,
+                                    refresh_token,
+                                ]);
+
+                            await trigger(\"connections::push_con_data\", [
+                                \"Spotify\",
+                                {
+                                    token: new_token,
+                                    expires_in: expires_in.toString(),
+                                    name: profile.display_name,
+                                },
+                            ]);
+
+                            token = new_token;
+                            refresh_token = new_refresh_token;
+                            return;
+                        }
+
+                        await trigger(\"spotify::publish_playing\", [playing]);
+                    };
+
+                    await pull_playing();
+                    setInterval(pull_playing, 30_000);
+                } else {
+                    window.spotify_needs_token = true;
+                }
+            }, 150);
+        </script>
+        {% elif user and user.connections.LastFm and config.connections.last_fm_key and user.connections.LastFm[0].data.session_token %}
+        <script>
+            setTimeout(async () => {
+                if (window.last_fm_init) {
+                    return;
+                }
+
+                window.last_fm_init = true;
+                const user = \"{{ user.connections.LastFm[0].data.name }}\";
+                const session_token =
+                    \"{{ user.connections.LastFm[0].data.session_token }}\";
+
+                if (session_token) {
+                    // we already have a token
+                    const pull_playing = async () => {
+                        const playing = await trigger(\"last_fm::get_playing\", [
+                            user,
+                            session_token,
+                        ]);
+                        await trigger(\"last_fm::publish_playing\", [playing]);
+                    };
+
+                    await pull_playing();
+                    setInterval(pull_playing, 30_000);
+                } else {
+                    window.last_fm_needs_token = true;
+                }
+            }, 150);
+        </script>
+        {%- endif %}")))