diff --git a/js/avatar.js b/js/avatar.js
index 919dd89..8679da4 100644
--- a/js/avatar.js
+++ b/js/avatar.js
@@ -1,67 +1,71 @@
 import * as DB from "./db.js";
-{
-    const DEFAULT_AVATAR_PATHS = [];
 
-    { // Generate default avatar paths
-        const MIN_CHAR = 0xF0040;
-        const MAX_CHAR = 0xF005C;
+export const DEFAULT_AVATAR_PATHS = [];
+export const DEFAULT_AVATAR_SVGS = [];
 
-        function generateHexStrings(min, max) {
-            const hexStrings = [];
-            for(let i = min; i <= max; i++) {
-                hexStrings.push(i.toString(16));
-            }
-            return hexStrings;
-        }
+{ // Generate default avatar paths
+    const MIN_CHAR = 0xF0040;
+    const MAX_CHAR = 0xF005C;
 
-        function getAvatarWithChar(hexCharCode) {
-            return `
-            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
-                <rect width="100" height="100" fill="black" />
-                <text font-family="techmino-proportional" fill="white" text-anchor="middle" transform="rotate(-11.46 50 50)">
-                    <tspan x="50%" y="50%" dy="0.3em" font-size="50">&#x${hexCharCode}</tspan>
-                </text>
-            </svg>`;
+    function generateHexStrings(min, max) {
+        const hexStrings = [];
+        for(let i = min; i <= max; i++) {
+            hexStrings.push(i.toString(16));
         }
+        return hexStrings;
+    }
 
-        function toDataURI(svgString) {
-            return `data:image/svg+xml;base64,${btoa(svgString)}`;
-        }
+    function getAvatarWithChar(hexCharCode) {
+        return `
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+            <rect width="100" height="100" fill="black" />
+            <text font-family="techmino-proportional" fill="white" text-anchor="middle" transform="rotate(-11.46 50 50)">
+                <tspan x="50%" y="50%" dy="0.3em" font-size="50">&#x${hexCharCode};</tspan>
+            </text>
+        </svg>`;
+    }
 
-        for(const hexString of generateHexStrings(MIN_CHAR, MAX_CHAR)) {
-            DEFAULT_AVATAR_PATHS.push(toDataURI(getAvatarWithChar(hexString)));
-        }
+    function toDataURI(svgString) {
+        return `data:image/svg+xml;base64,${btoa(svgString)}`;
     }
 
-    /** @param {string} id The user's UID */
-    function getDefaultAvatarPath(id) {
-        let counter = 0;
-        for(let i = 0; i < id.length; i++) {
-            counter += id.charCodeAt(i);
-        }
-        const index = counter % DEFAULT_AVATAR_PATHS.length;
-        return DEFAULT_AVATAR_PATHS[index];
+    for(const hexString of generateHexStrings(MIN_CHAR, MAX_CHAR)) {
+        const svg = getAvatarWithChar(hexString);
+        DEFAULT_AVATAR_SVGS.push(svg);
+        DEFAULT_AVATAR_PATHS.push(toDataURI(svg));
     }
+}
 
-    /** @param {string} id The user's UID */
-    async function getDefaultAvatar(id) {
-        const path = getDefaultAvatarPath(id);
-        const response = await fetch(path);
-        if(!response.ok) {
-            console.error("Failed to fetch default profile picture: ", response);
-            return null;
-        }
-        return await response.blob();
+/** @param {string} id The user's UID */
+export function getDefaultAvatarPath(id) {
+    let counter = 0;
+    for(let i = 0; i < id.length; i++) {
+        counter += id.charCodeAt(i);
     }
+    const index = counter % DEFAULT_AVATAR_PATHS.length;
+    return DEFAULT_AVATAR_PATHS[index];
+}
 
-    /** @param {string} id The user's UID */
-    async function getAvatar(id) {
-        try {
-            const avatar = await DB.getAvatarById(id);
-            if(avatar) return avatar;
-        } catch (err) {
-            console.warn(`Failed to fetch avatar for ${id}: ${err}`);
-        }
-        return await getDefaultAvatar(id);
+/** @param {string} id The user's UID */
+export async function getDefaultAvatar(id) {
+    const path = getDefaultAvatarPath(id);
+    const response = await fetch(path);
+    if(!response.ok) {
+        console.error("Failed to fetch default profile picture: ", response);
+        return null;
     }
-}
\ No newline at end of file
+    return await response.blob();
+}
+
+/** @param {string} id The user's UID */
+export async function getAvatar(id) {
+    try {
+        const avatar = await DB.getAvatarById(id);
+        if(avatar) return avatar;
+    } catch (err) {
+        console.warn(`Failed to fetch avatar for ${id}: ${err}`);
+    }
+    return await getDefaultAvatar(id);
+}
+
+export default getAvatar;
\ No newline at end of file
diff --git a/testing.html b/testing.html
index c2646f5..c3dfb0c 100644
--- a/testing.html
+++ b/testing.html
@@ -12,19 +12,17 @@
     <a href="/index.html">Click here to return to the main page.</a>
     <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br> <br>
 
-    <button id="login">Test button</button>
+    <div id="avatars" style="display: flex; flex-direction: column; width: 128px;">
+
+    </div>
 
     <script type="module">
-        import { SUPABASE } from '/js/db.js';
+        import { DEFAULT_AVATAR_SVGS } from '/js/avatar.js';
 
-        document.getElementById("login").addEventListener("click", async () => 
-            await SUPABASE.auth.signInWithOAuth({
-                provider: "discord",
-                options: {
-                    redirectTo: "https://techmino-hub.github.io/auth/discord-callback.html"
-                }
-            })
-        );
+        document.getElementById("avatars").innerHTML = DEFAULT_AVATAR_SVGS.join("");
     </script>
+    <style>
+        @font-face { font-family: "techmino-proportional"; src: url('/fonts/proportional.otf') }
+    </style>
 </body>
 </html>
\ No newline at end of file