{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"0f971df2-8144-5c92-8d92-a2c10c0918e8","html":"<p>DGNmstr is a full-stack web application built for tabletop RPG game masters and their players. It serves as a living campaign bible — a single place to create, organize, and reference every asset in a game world, from NPCs and factions to quests, scenes, and locations.</p>\n<p>The app supports two distinct roles: <strong>Game Master</strong> and <strong>Player</strong>, each with a tailored view of the campaign. GMs have full creation and editing access, while players see only what's relevant to their character.</p>\n<h3>Key Features</h3>\n<p><strong>Campaign Archive</strong> — A tabbed interface for browsing and managing all world-building assets (Locations, NPCs, Factions, Items, Quests, Scenes). Assets support rich Markdown descriptions with a live editor, image uploads to DigitalOcean Spaces, and a side-by-side comparison tool for evaluating two assets simultaneously.</p>\n<p><strong>AI Asset Generation</strong> — GMs can generate asset descriptions on demand using the OpenAI API. A tagging system lets the user specify tone, type, and difficulty level before generation, with the result dropped directly into the creation form.</p>\n<p><strong>Session Timeline</strong> — A chronological log of play sessions attached to each campaign, giving the group a persistent record of what happened and when.</p>\n<p><strong>Character System</strong> — Players manage their own character sheets, ability scores, and journals. Character data is scoped to the active game and party via JWT claims, ensuring players only access their own records.</p>\n<p><strong>Party &#x26; Game Management</strong> — GMs create games and parties, invite players, and manage settings. Role-based access is enforced at both the frontend routing level and on every API endpoint via JWT claim inspection in the FastAPI backend.</p>\n<h3>Architecture</h3>\n<p>The backend is split into two FastAPI services — one for authentication (SuperTokens + PostgreSQL) and one for all game data — orchestrated with Docker Compose. RTK Query handles all data fetching and caching on the frontend, keeping server state normalized across the Redux store. JWTs signed with RS256 carry embedded game-context claims (<code>In_Game.Role</code>, <code>In_Game.Game</code>, <code>In_Game.Party</code>) so the backend can authorize requests without additional DB lookups.</p>","frontmatter":{"sortOrder":1,"name":"DGNmstr","languagesArray":["React","Redux Toolkit","FastAPI","PostgreSQL","Docker","OpenAI"],"shortDescription":"A full-stack campaign management platform for tabletop RPG game masters and players.","screenshotArray":[{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,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"},"images":{"fallback":{"src":"/static/0db89a5ad99d63fc5cffe12eedb092aa/bc240/dgnkeeper-1.png","srcSet":"/static/0db89a5ad99d63fc5cffe12eedb092aa/bd936/dgnkeeper-1.png 477w,\n/static/0db89a5ad99d63fc5cffe12eedb092aa/3496d/dgnkeeper-1.png 954w,\n/static/0db89a5ad99d63fc5cffe12eedb092aa/bc240/dgnkeeper-1.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/0db89a5ad99d63fc5cffe12eedb092aa/0cf28/dgnkeeper-1.webp 477w,\n/static/0db89a5ad99d63fc5cffe12eedb092aa/c1c0f/dgnkeeper-1.webp 954w,\n/static/0db89a5ad99d63fc5cffe12eedb092aa/74e37/dgnkeeper-1.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":2241}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD/UlEQVRIx51WW28bRRidNE16sZuobVr1IvW5f4BrSKXQi504hTYNKJVaideqQiAektIHyk3wCgiEqADBK2+FhwqQEFKk0qpILUUmCbaz3ji+2+v1lfXeDprPO8vENihipaOZ9ZzvzPm+b1Zj9tLx45g/dgznx8bw3N69mNmzB8/v24dIMIipXbtwenAQJzm2b0doxw6Ed+7E1O7dtM65Z0dHCRcOHcLswYNg1bKGUjaLbDKJjXgcqVgMSjSKxKNHiD38DWo0ig+//Bpvf3oTmbU1pONxqCsrUJeXsb66ioyioJzNQS8WoZdKYNjCE0ul8Xtc2QoVTMvnkVUUcphT1c5cUZBLJpFXVXL72cICPrp6FSv376OQSpFTwROxWSWJ/Po62Buzszi3fz9ePHqUajl3+DCN337+Be5+/wOWbt3C3JEjmA4EMTMygjNDQzgzPEz1lHF6aAjnDxwAe/XECUwyRoUWi9PBIF4eH8frkQhuLi7i7OgIIoEANUk0hQsI8A1ODQ7i3NgYGG9IOpHoFDyRwEa8M39w5y5+vv0jfvruNu4t3cG9pV/w4NeH+ObjT/DVmzeQVVXiE7xYnjprNZr4yzDQtqxNxXUAWC7QMi1sFDXkcwXUq3U06nXqZr/HchywciqFXCYDTavAMk2YHO02LMuCY9toNJso6xVoFR3VWh0uQBAc27ZhWTaNhmGAcRe241AwEQRsG67jQKvqSOdzyBRKKJQrxLM9NFst1BsNNBt1NGt12oTpLQf5QhmlQgFtw4Btmv+IWhZc2wYch8A3EL+blol0roA/42tYT6xCiS6jWiqDcbu6rqOiaajXapQ2OZDd9oNtIZ0rdgTXYlD+WIHOBfmirmnQSmU0ajWYhkHWfRgGjFaLIK+12wZyhSIURUVaVZCKxVHTKmCu6/pd4nOHp+a6nbllweLF5zBNGqkMHsfxai/HMSFE3ZPEKC2evldTR343TeKCc/kof8tCgM6e2Jl33HMmi9ieS9+p58w3tcmh10US5k3pI7TpN09QxAlTvqDjnTsS7Eqvr1vvy/JjhaDcFJGyqF+38KYzyusopSzEfYeQmsJJPUJdEK5cqYY9TZEJsmh3ylysm9/TlG6CfC79Eki16ieI/xLsCex6/ze+n7JY9GuzBTjSkfFT7hHoIsgb+fCEumP5e881Kqf2fx72wZUreO/SJVyPRPDa5CRemZigcTEcxrVwGIuhEK7PzOCd+Xm8f/kyjRw85q0X5nDjwiwWQiFcm5rCuxcvgk0whmcHBvAUY3iSMRrFXOAJxvC4h8cYwzhjeIYxPM0Y3ZiCx9fZdCAADn7n8iv05MAATm3bRtciQZ5776HhYbqf+Tv/jyNz/ga527D6XeGORQAAAABJRU5ErkJggg=="},"images":{"fallback":{"src":"/static/a65207a3b71d26ed539f3ef3f4e7927c/4baef/dgnkeeper-2.png","srcSet":"/static/a65207a3b71d26ed539f3ef3f4e7927c/d9867/dgnkeeper-2.png 477w,\n/static/a65207a3b71d26ed539f3ef3f4e7927c/212ea/dgnkeeper-2.png 954w,\n/static/a65207a3b71d26ed539f3ef3f4e7927c/4baef/dgnkeeper-2.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/a65207a3b71d26ed539f3ef3f4e7927c/19127/dgnkeeper-2.webp 477w,\n/static/a65207a3b71d26ed539f3ef3f4e7927c/f7d56/dgnkeeper-2.webp 954w,\n/static/a65207a3b71d26ed539f3ef3f4e7927c/8a263/dgnkeeper-2.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":2750}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAbCAYAAAB836/YAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFcElEQVRIx42VWWxUVRjHj7gQJcYnHk2M4FIEjXFBIRoFjKLxxQdj3Kjbg0Z9MCbGmGhcoNXEmLiFVoRStC1gJKUbnc7SoUAxdF+mpZ1pp7MvneXOzJ07W/sz58y01uXBm/zy/853vu+7Oeee71zx/p49vLtzJ6/feSevVFWx77bbqL79dl7ctInnb7qJ5268kac2bmTvxo3K99Lmzbx0yy28fOutVFdV8erWrbxx1128tX07b957LwKgVCqRz+UwdJ1sJkMqkUCLxUkuLpLVUvxqsvLD6c5yTEYnrWmkE0kymoaRzVJaWmKZ8iP4H8/M9AzjoxP/JxQxNz7OkMXCsM3G6NmzSoetVqTfMz3NxPnz1O7bxyfPPEPvyZNqbsBkYqCnRzEoMZuVPWq3I97bvZudQrBLcsUVPFLRo/sP0NNynL7WVp66/noeFYIdQnCPENxX0bXcLYTKFbXV1WqzX9u2jVfvuEMhP9B7u3bxwd69fPvOO2rjq6u2KH1x82Ze2HSzin9t69aybttG9ZYtvL1jB2J5eRlJsVgkn8+Ty+UoFAr4fUEmJ2cYG5lgxulm1unG7Q9jOvEbbXV1FEslDMPAyBoqr1gssbS0hIiF/aTiASbHLnGipRG7pZ2BfjPnerswd5/GbGrD3N1Gd+cpzN2tnO/t4mJfNzbTaXo6fqf9VAtjQ/1QShPxzyOCC7N4XGNEAk588w5SMQ8FPUw+UyaXDq3akmI2QjEbVVrIhCnoEQWFOF7nBCLkdbEYdJLXI2S1IHoygJEKrdpazEs64V8dl4xFlnIxhbRXoJjEPz+FCPvmCHqmSS56iIXmiIXm0bX/Tlw7/nfBBP65KYRct8c1TjTgIh6eV0Wl5lIhtbRcKkhOC5Q1FVTLLOoRhVqyIsJyLobP5UDEQh7CoTlSWggjGyWrR4EMkIXlNKCvIVvBAApAfg3LhH1OhHNskLb67zjTUE/HoR/pOnwQU+NP9DTW091Qh63pCBdbj9Pf2oK9pQFb02FFb3MD9pajynf2eCO9zUcY6u1GuCZHMJ88xqiti7HeLsbsZxixdjJsaWfY3M6ItYPxPhMTfSZGbJ0M9rQxZG5n2NKhxjJW6rj9DI5L5xCemUkGbZ1M/WHn8qWzTP/Ry1S/DccFyyozA33MDp7DccHK5Iq/36piJdKeuWTn8vBFxOg5G/tfeJYvX36elppPsTc30NNQh/mopF7ZfScaFSu+MnVYjx3C0vgTZrlFRw4yYOkqH2zH0Hl8znEMLag+xFIhSSkfX9V8NqqQdjEniZXni0koaZUPViDkmUUEvS68bgc5PUI67kOLLpCMLhCXZzLoIh3zkJGHO+YlE/eVx3EvWS1QbgItSFGPspyP459zIKIBNwuzYwQWpokGnKoF42G3KpqKeSkZ0cq5K7fdkrGokiVrD/ffD7bbQTTsJm8skkn6yST85NJhjHQIIxWs9G70b52hkL6KX7WeLBiYv8ygtYNhezdD1k5CbgepuJdEdEEVk4VXWu6frBSVL5OXg1rynGMEy8lj6rwN9ZwmujCl2k5P+NDlpZAMKJVjuYcSPV6ek/sp21FuCflY+bbREmEioTm0ZJBEwk8kNE/I7yQcdLEYcZNK+NHiPqWpZIC0FiStBUgly/6MFsSQ15weIRKYR1iamzjxzdf8WnuAI598zKGPPlTaVFtD05c1HNv/Bc1f1dJ68Ec6D/9MW30dp374nt+//1bl/VKzn8bPP+OXmgN0/HwI8dhVV/HkdRvUj+p+IXigwvaK7qjwYAUZ85AQ6qf1sBDI/AfXzIvH16/niWuv5ckNG3j8mmvYvW4de668chU5Vr6KX9oyXuY9dvXVPH3DDX/lrFvHn87evV0ALfGeAAAAAElFTkSuQmCC"},"images":{"fallback":{"src":"/static/d5480cbf79ffbaa48284045c3397ee27/cbc9d/dgnkeeper-3.png","srcSet":"/static/d5480cbf79ffbaa48284045c3397ee27/dad98/dgnkeeper-3.png 477w,\n/static/d5480cbf79ffbaa48284045c3397ee27/8ad71/dgnkeeper-3.png 954w,\n/static/d5480cbf79ffbaa48284045c3397ee27/cbc9d/dgnkeeper-3.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/d5480cbf79ffbaa48284045c3397ee27/5e259/dgnkeeper-3.webp 477w,\n/static/d5480cbf79ffbaa48284045c3397ee27/bfd83/dgnkeeper-3.webp 954w,\n/static/d5480cbf79ffbaa48284045c3397ee27/965a5/dgnkeeper-3.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":2621}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,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"},"images":{"fallback":{"src":"/static/1051c9c3e70f945498fad35865c180cf/d77bf/dgnkeeper-4.png","srcSet":"/static/1051c9c3e70f945498fad35865c180cf/e686d/dgnkeeper-4.png 477w,\n/static/1051c9c3e70f945498fad35865c180cf/fad15/dgnkeeper-4.png 954w,\n/static/1051c9c3e70f945498fad35865c180cf/d77bf/dgnkeeper-4.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/1051c9c3e70f945498fad35865c180cf/41163/dgnkeeper-4.webp 477w,\n/static/1051c9c3e70f945498fad35865c180cf/6adcc/dgnkeeper-4.webp 954w,\n/static/1051c9c3e70f945498fad35865c180cf/c4427/dgnkeeper-4.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":3503}}]}}]}}},{"node":{"id":"0d09e00d-8f6c-5e1a-b5cb-b2388cbb87ba","html":"<p>A real-time IDE used for teaching students basic Python. This tool allows a user with a Teacher account to host an IDE session for multiple Students.</p>\n<p>Web sockets are used to ensure each account sees the same code in their IDE, and the Teacher assigns edit permissions via a \"talking stick\" mechinic, ensuring that only one account can edit the code at a time. The Python code is handled in-browser by an interesting library called Brython.</p>","frontmatter":{"sortOrder":2,"name":"Interactive Python IDE","languagesArray":["React/Typescript","Web Sockets","Brython"],"shortDescription":"A real-time IDE used for teaching students basic Python.","screenshotArray":[{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA+ElEQVQoz6WSv0vEMBiGU3NJHTo0hetZJf0BtW4e/guiggpS2u4uBc1R3JycnRz8k1/56mU4cl4LDg8feUOevIGw5xeDzTDgbRiwMQbGvO5AWd/36LoOTdOgbVsH2qvrGnf3D2DxcolUaySrGJEKEYXhOFX4S6QUgiAAY2weVXWBy/Ua5XmJPM9RFAVyy3attYbv+5BSQggBzrnDQggIKcGyLIMlTVMHypMk2dvG87yRnZxuPwRJSegctGzz6vYRNx+fYPtaWUhoG/4ltPn1U433r+//Cx2mhOOTT6eFtH/E+byGJ/Fq/rc5KKR5ppFdlRDqeFLG+QI/Y/kA1GNjyJkAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/6811d5fef181e8c3f8dd6bdb266ae07d/f42e4/ide-featureintro.png","srcSet":"/static/6811d5fef181e8c3f8dd6bdb266ae07d/d928a/ide-featureintro.png 477w,\n/static/6811d5fef181e8c3f8dd6bdb266ae07d/39e28/ide-featureintro.png 954w,\n/static/6811d5fef181e8c3f8dd6bdb266ae07d/f42e4/ide-featureintro.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/6811d5fef181e8c3f8dd6bdb266ae07d/42dc1/ide-featureintro.webp 477w,\n/static/6811d5fef181e8c3f8dd6bdb266ae07d/30f42/ide-featureintro.webp 954w,\n/static/6811d5fef181e8c3f8dd6bdb266ae07d/2547d/ide-featureintro.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":987}}]}}]}}},{"node":{"id":"b1684d21-be9d-5ea8-b48d-f931b223d774","html":"<p><em>Note: This is still in-progress. Styling and overall functionality will change as I get user feedback.</em></p>\n<p>This is a fullstack project built for my friends' Twitch stream. It utilizes <a href=\"https://netlify.com\" target=\"_blank\">Netlify</a> for hosting, user management/authentication, and for serverless functions. While multiple user accounts aren't a strict necessity for this application, and a more simple approach to password protecting the website could have been used, this seemed like a good project to test Netlify's user management service.</p>\n<p>This dashboard contains basic CRUD operations for managing the song database, as well as a \"setlist\" feature. Songs marked with an active checkbox are added to the setlist, which appears on the dashboard as well as in the response returned by quering an endpoint. This data is then utilized by their Twitch chatbot, which returns the current song via the <code>!song</code> command, and advances to the next song (i.e. dequeues from the song queue) with the admin command <code>!next</code>.</p>\n<p>FaunaDB queries are currently written in FQL, though they may be refactored into GraphQL queries in the future.</p>","frontmatter":{"sortOrder":3,"name":"Song Setlist Dashboard for Twitch","languagesArray":["React/Typescript","Netlify","Serverless","FaunaDB"],"shortDescription":"A queue of setlist songs is exposed via API, which can be queried and used by a Twitch chatbot.","screenshotArray":[{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABZElEQVQoz3VRy07DMBDM//8BCIQAUQQHTr3wDRxoC7RwQT3RV1Iljd9xMmiWOlAElkbe2fXOPpwdX45xOphieD/D3XCKo4sXnA5mOLn6Au2/uGDvO7t+xcXtG85v3pC9PD9iPHrAfP6OGD2AFoen2+M37/6MZ6PRGJPJEz4WC0Tj4X0D7wNibOGVhVIGda3ERyilsauV+J3z0Po73rYdss1mgzzPsd1u0TiP3W6Huq4RQoA3FFSoqkp40zQS6+PeH3DpcLVaYblciigTtNYiwsc+BOFMsNZKEjlBO8YoObTb9mtV2Xq9BkWLooBWqq/UdZ2g39wP/l+M6AXZoQ9eKqbK7NI5J91Jx3vOogRtIr3n/S1Y5IjWwxoDbQyCsXC1RlmV4qMYR+U+aafxy7KUmz6O/UOwQDBOErhDVk4CHIUJ9FOAN7tOH8aPJD8YmTu0zvaC/Ag+TL+ewHgSYcE0KrszxuATHMX4GJ7TN1QAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/721e230c4f071f67ac194f8ff37a968b/f42e4/s4x-overview.png","srcSet":"/static/721e230c4f071f67ac194f8ff37a968b/d928a/s4x-overview.png 477w,\n/static/721e230c4f071f67ac194f8ff37a968b/39e28/s4x-overview.png 954w,\n/static/721e230c4f071f67ac194f8ff37a968b/f42e4/s4x-overview.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/721e230c4f071f67ac194f8ff37a968b/42dc1/s4x-overview.webp 477w,\n/static/721e230c4f071f67ac194f8ff37a968b/30f42/s4x-overview.webp 954w,\n/static/721e230c4f071f67ac194f8ff37a968b/2547d/s4x-overview.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":987}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABk0lEQVQoz41RO04jURD0eWCl5aflk5EQwB2AhQN4PGPPvO/MyBKJ1z4CCIwzAif2GQg4hYmdWLYlSw4KVdtvxGqTHanUb7rrVVf3qx2c3mL/5Dcuru5wcXmHnYNr/Dj6f+weXuPnrxvsHd/i7PwetXoUo16PUY8SJM0MaaahjYPSVqIxHsb6KjKnWdN2w9lGpTb8WrPZBNFqteC9g/deUBQFrDVSS5IYaZoiTVtQKoMxBtZa4fNsjEbuPcqyQC1JEhC86FwgbC50On/w+PiE5+cX9Pt9DAYDyVGcTa2jWw2lNZzzyPNi4zAIkhTE4jjGaDTCcrnEarXCer0Gv/F4jCiKZALyaYLI81xyfwlSiGCBK6DgYrHAdDrFfD7fCo6ET04QYQyoBCmgxbpDWZbSYDgcYjabieBkMsH7xydeB2+yS45HLg1QKOz+n5FJCGO32210u130ej3Bw0MH3udSD/vOsqz6rwQD3HbJBItKKcmHh8qyVBAaEuSEyUSQ7hqNRrXDQJDX256DYMjRFeN3ZwR3+AUSLO5EcXsDxAAAAABJRU5ErkJggg=="},"images":{"fallback":{"src":"/static/83ff96c4c8c9da9b0a04a6ae20d5b678/b3c65/s4x-song-add.png","srcSet":"/static/83ff96c4c8c9da9b0a04a6ae20d5b678/6ce38/s4x-song-add.png 477w,\n/static/83ff96c4c8c9da9b0a04a6ae20d5b678/f8838/s4x-song-add.png 954w,\n/static/83ff96c4c8c9da9b0a04a6ae20d5b678/b3c65/s4x-song-add.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/83ff96c4c8c9da9b0a04a6ae20d5b678/76386/s4x-song-add.webp 477w,\n/static/83ff96c4c8c9da9b0a04a6ae20d5b678/9f964/s4x-song-add.webp 954w,\n/static/83ff96c4c8c9da9b0a04a6ae20d5b678/b2cfc/s4x-song-add.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":981}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwUlEQVQoz42SvW4TQRSF/TyABCSIv44mBXmHEMIDOPb+zuzM7kS2MIqEUxHJTdDihkeIlGcIEgUFsiAihYWiKAVrN5blD+5udkHQMNLRHc2ce+bce6e19mibuw+fs7G5w8bTHW6sbXHr3v/j5voWt+8/486DbR4/eUGrvdul3e7S3vXw/IgwUihliFWC1gad2Ar6d1QqKe8FzT5OUNrQ8n0fQRAEWGuw1pJaS5alKBXj+x5et0sYhoRhQBD4KKVIkqTka63RWpU5zmW0PM9DIKLGVARJSNOUN4eHHB29Jc9z8vwd4/GY0WiE0rrkCoQbK4UxljTNKoe1oLgTwTiOcc4xmUyYzWasViuWyyWyptNpyROxOgrEQJb9JShl1IQ9t8eXs6/8KAqKomA+n7NYLDg//1YmCkeiQMRqNILSQ1VaN1hjcC/7fHp/zNXpZ67mBZcX3/nw8Yzjk1N6PUeSVA+LCRESt4J/ShaClG2s5ZXrsd8f8Ho45OBgyGCwj3P9pgrhRVFU8a9b0Ey5Hoq4FIK4jFRMEAbNoKKomnQtII9Lv5vKRFDcdTqdpoc1oZze9b76Gro5E1cS/3RWfrdfPfwJo+Hx92NUPPMAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/2c0a3a497df9dea0ac5c98785a8ec598/b3c65/s4x-song-edit.png","srcSet":"/static/2c0a3a497df9dea0ac5c98785a8ec598/6ce38/s4x-song-edit.png 477w,\n/static/2c0a3a497df9dea0ac5c98785a8ec598/f8838/s4x-song-edit.png 954w,\n/static/2c0a3a497df9dea0ac5c98785a8ec598/b3c65/s4x-song-edit.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/2c0a3a497df9dea0ac5c98785a8ec598/76386/s4x-song-edit.webp 477w,\n/static/2c0a3a497df9dea0ac5c98785a8ec598/9f964/s4x-song-edit.webp 954w,\n/static/2c0a3a497df9dea0ac5c98785a8ec598/b2cfc/s4x-song-edit.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":981}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABWElEQVQoz21SS07DMBTMvVpYwKYFCTZQmn6StEkcu/moqhBIcBYWIFQQIA7BAg6ABEJUgMr3FoP8HCcOZTGy/T7jeWNb9WYftUYfq5sOVjZc1BoO6k23wNJaFWbOrFleV7DawxAKDN1QwOExXJGU4Ek1Jvc8LmN6zxN4IoW17QaQaHkhuuGoQI/F6AQjtIcRwQ4EOoGA7Qu0fU6rzMvV9nnRY0kik5CafU4rG+/i/uERT88zvM3fcXN7R3WaQMImcnXuR8kioUxKJS2PIds/xPzjE7OXV3x9/xA5EQSiUGROVCHcGbDiJidKaJ/uHWB6dY2j0ymOzy5wcn4Jh6fU3IsUJAmdcywoNG+WSgfxGEE6QZBN4ImMYrquk/uq6/8lJOPzJhp9wEpfc29N/3SuQqhhPop6UWW4HOsvgc7rX6CV0rfZcnzyUAZ1g6nIZrFC3lx+pVKZHvsXfQC3oWNtcAkAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/d7db079484df3153460791f5d69a7222/f42e4/s4x-logout.png","srcSet":"/static/d7db079484df3153460791f5d69a7222/d928a/s4x-logout.png 477w,\n/static/d7db079484df3153460791f5d69a7222/39e28/s4x-logout.png 954w,\n/static/d7db079484df3153460791f5d69a7222/f42e4/s4x-logout.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/d7db079484df3153460791f5d69a7222/42dc1/s4x-logout.webp 477w,\n/static/d7db079484df3153460791f5d69a7222/30f42/s4x-logout.webp 954w,\n/static/d7db079484df3153460791f5d69a7222/2547d/s4x-logout.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":987}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAtElEQVQoz2OITc/5jw3HpGX/J0eOgZCmuIxcFEyWgTANIDosIfV/aDwEhyWkociR7ML4zLz/R46f/H/52nUwPnj0OFiMLC9Hp2b9T8wu+P/8xcv/MPDy9ev/iVn5YDmSDYxKyfyfll/yf9f+g/9Xbdj0f/XGzf93HzgEFgPJkRUp8Rm5/1et3/h/6649/7fu3ANmg8QoipTQ+JT/IVAMYlMUKdRPNiA+iJ2ZB8Fp2RAxPC4EAJZCxziohe1QAAAAAElFTkSuQmCC"},"images":{"fallback":{"src":"/static/6a5616a9b6045ac5edf446e8bb5c01fa/b3c65/s4x-login.png","srcSet":"/static/6a5616a9b6045ac5edf446e8bb5c01fa/6ce38/s4x-login.png 477w,\n/static/6a5616a9b6045ac5edf446e8bb5c01fa/f8838/s4x-login.png 954w,\n/static/6a5616a9b6045ac5edf446e8bb5c01fa/b3c65/s4x-login.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/6a5616a9b6045ac5edf446e8bb5c01fa/76386/s4x-login.webp 477w,\n/static/6a5616a9b6045ac5edf446e8bb5c01fa/9f964/s4x-login.webp 954w,\n/static/6a5616a9b6045ac5edf446e8bb5c01fa/b2cfc/s4x-login.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":981}}]}}]}}},{"node":{"id":"b930fa4b-a13e-56b7-b9fc-dee503733ca1","html":"<p>SVG Avatar Generator for Student Accounts. Students may choose to use an animated avatar rather than upload a photo of themselves. This feature is limited to Student accounts, Teacher accounts are required to have photograph profile picture. Avatar building blocks are pulled from the <a href=\"https://getavataaars.com\" target=\"_blank\">Avataaars library</a>.</p>\n<p>The SVG data is saved to an image blob, which is then converted to a PNG. The PNG's URI is then generated via <code>canvas.toDataURL()</code> and stored in the database.</p>","frontmatter":{"sortOrder":4,"name":"Animated Avatars","languagesArray":["React/Typescript","Django","SVG","Avataaars"],"shortDescription":"SVG Avatar Generator for Student Accounts.","screenshotArray":[{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3klEQVQoz22R0W4SQRiFeSRfwxfwCUxMTFpc2GWW3Z2Z3U1Eq0GWEq+qeONNb/TGBApIkG0pa9NiExOjiW2aNlraKkKILQY5Zga2XRon+bOzZ87/zfkzsQWNIGWYUFUNKyvP4Ps+6vU6Nttt7HQ68r/RaMjy19fRarWwsdFCs9lEEAQoFosgug5KKRLxRcQEKG0YWIzfQ3ltDeE6OznB21IJ0dX72cPhty6G/QHGk4nUarUaFEWB7TgSHDNNE5xzaJqGSqVy2bz69DGUmzewG2xCtP7oHmN36z0+bG/jYO8LBv2+9ImeZDIJ13WnQAFzHEeK1Wr1Eui/a+DN6nN8+vwVf2eJvx8eYDQcYnIxwiSScA7IGJNAVVVRno04Oj/H/mCMzukYp7/HuBj9wa+zLj4Gdbwqv8Dr9ksc9Y6lt1QuyV4B1EOgSMkoBXNcJNz7YA+WkH+SRSGXRd7LIZ/34HkecjkP7KEDkjGxlH2EwnIBmUxGPoht21dAUbbNoRIdt+7cxe2FOAzDkI8lvqlUSo4j9syisCmHTnQQQiQsDEXmEnI+vcmy4HAutbAs05JnUx+TXovSK+06MBREAiWRAJ1p0TP2Hy2qi306nZ4HmpY1HetaczRJVJv3cRimgX+UMzesgEawlQAAAABJRU5ErkJggg=="},"images":{"fallback":{"src":"/static/005284077f238bbb7ebfaa1f36478218/b3c65/happy-done-avatar.png","srcSet":"/static/005284077f238bbb7ebfaa1f36478218/6ce38/happy-done-avatar.png 477w,\n/static/005284077f238bbb7ebfaa1f36478218/f8838/happy-done-avatar.png 954w,\n/static/005284077f238bbb7ebfaa1f36478218/b3c65/happy-done-avatar.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/005284077f238bbb7ebfaa1f36478218/76386/happy-done-avatar.webp 477w,\n/static/005284077f238bbb7ebfaa1f36478218/9f964/happy-done-avatar.webp 954w,\n/static/005284077f238bbb7ebfaa1f36478218/b2cfc/happy-done-avatar.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":981}}]}}]}}},{"node":{"id":"a9b5fe02-a482-52c2-9abe-38f0ffe566b3","html":"<p>A database of common vocabulary words can be created and managed via this tool. In this case, the intent is to allow students to become familiar with common words found on tests such as the ACT and SAT.</p>\n<p>This vocabulary dashboard serves as a way for Admin acounts to organize data so that Teachers may use it in their tutoring sessions. Each vocabulary entry is given a definition in English and a Chinese translation, and is then given a main category corresponding to the relevant test. From there, a smaller subcategory can be created in order to break the list up in to more managable chunks.</p>\n<p>This was my first project in which I was responsible for database design, and as such it was the first time I needed to use relational database concepts such as many-to-one and one-to-many relationships. Because of this I chose to include the graphic I used to plan out the underlying schema.</p>","frontmatter":{"sortOrder":5,"name":"Vocabulary Database Dashboard","languagesArray":["React/Typescript","Django","SQL"],"shortDescription":"Tool used to manage a database of common ACT and SAT vocabulary words.","screenshotArray":[{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABFklEQVQoz62Sa27DIBCEOV7txK5j3KiX75+qUtXUT8DmzVSsmxwgCdKIZQXfsgOsPr/jxDl425Ka0wm8ewPnHHX9irqq0DQNqaoqHA9HHMoDyqLAS1GiLEu0bYeWdzhXNdjnOENqC+s8Nm0gpIRUCj4EhBhJMSXEmPY4Jngf4LyHDRHGOmhjodYN0yLAlFSwOWkdrHNQShE00uFdm9YwxtzWKSVYaymXZyEkLpPAx+jAhmnGummqtG0aUkra4Jz7l8cwjFQox7lovv2yCPT9AO/9bW8MHmycZqh1B+bqjw42L5K8yz6EsANzS/eKLULt7WpDZj8M/Pr+waWf8DvM5M8VeHfL12enlmN8BtDe/tJTgBn0TOAf7nY7TGSwhxEAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/5a64d4416b444713a733bf29fa35d7be/fe1e7/vocab-list-unsorted.png","srcSet":"/static/5a64d4416b444713a733bf29fa35d7be/73868/vocab-list-unsorted.png 477w,\n/static/5a64d4416b444713a733bf29fa35d7be/8e0ac/vocab-list-unsorted.png 954w,\n/static/5a64d4416b444713a733bf29fa35d7be/fe1e7/vocab-list-unsorted.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/5a64d4416b444713a733bf29fa35d7be/93be8/vocab-list-unsorted.webp 477w,\n/static/5a64d4416b444713a733bf29fa35d7be/3f803/vocab-list-unsorted.webp 954w,\n/static/5a64d4416b444713a733bf29fa35d7be/f608b/vocab-list-unsorted.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":1075}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB10lEQVQoz52STWsTQQCG95+0mg8rIbGJIKL/xWN3u0lzadLu7MxsdknAGqoIjSIWa3oIHis9eClSlJKe8icEpceKlhxsfGQ2uyF+oODCy8yw7zzzvrtj3b5zl+VSietLS5SKRQqFAsuVCpVKhXwux5XFRa7l8+SyWRYXFmKZeTaTIZvJkslcpVQoUi7f5NaNMtY928ap1qjX67jVKo7jsOq62I7D/a0tXvb7vNjbo7+/z2AwoNvtYts2rvGsurHXra1Rra3hrqxgSaUJwpCg1SI0YxAQBC2UUgxPT/n1GY1GSCnpdDq0222iKEJrjZCadRlibXoevpRIpWKj5wmEEDSbGxy/PeLL53O+XlwwHo9j4PvhkGajgfB9Go0mUk73mbXnK6yNBKi0jk9qxUkjtC949eYdZ4bzfcK3yQQ+fOLk9SGelLM2rXDazCgKk4SGbhKaqvHLKEL5HgdHJ5xfApPLKfDjGccHhwgl46opyIRIZRmYSRcnDIKZycwfP9pm99lTdnZ69Ho9nuw+58HDbVqJbx40A643mmx6IpaBpkYzmh8jhI/vJxICrdRPsDRAKsuAPOHH0jr4zWyqzWv+wD/J0kldo/Tq/G3Dv2TF1yVRMPdt/hf4A3/9KO3bWBAIAAAAAElFTkSuQmCC"},"images":{"fallback":{"src":"/static/d6886848c11fa91b3470fba81f22de41/3a968/vocab-update.png","srcSet":"/static/d6886848c11fa91b3470fba81f22de41/1ca00/vocab-update.png 477w,\n/static/d6886848c11fa91b3470fba81f22de41/8e0ac/vocab-update.png 954w,\n/static/d6886848c11fa91b3470fba81f22de41/3a968/vocab-update.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/d6886848c11fa91b3470fba81f22de41/81b11/vocab-update.webp 477w,\n/static/d6886848c11fa91b3470fba81f22de41/3f803/vocab-update.webp 954w,\n/static/d6886848c11fa91b3470fba81f22de41/5c38e/vocab-update.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":1073}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSUlEQVQoz6WSjUoCQRSF5z3aQCXd1YSgeu5eIDJd9yefIiJIF3N3df93Z/1iTUVNKvHAgZnL8M25d0bc3t3TVlUa9TqaqtJsNul0u1x3OjQaDeq1Gq1WE01TV2tFUbjcsaJcoF61aHeuudHaiIden55pMRqNMEyT/mDAQNcxLQvLtrGsfdv2C4ZhMhwOedZN9KGBYdmYlo3x9IjIZcmhZPmz9puKQuJ4AR8xCNfzCaOYOEkJowjf95nNXJIk2Xo6/cR1ve0+TVM8z2M8mRAnCYtFwOvbO5PZHDFbA9MsJ88LpJQsl8s9H6uVZUlRFOuEBY7jEIUBwvXnBGFEkmZIeVqr2xFJSRTHxHGCqGBZXnwnXN94mOYv70qMnSmuv1g5y/It8D/anNuFiwrkL0LmQbia4SnAYxIVpGq5Srf5LmcBq8fYuBruucAvbw8kDTjCCSUAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/48862b8f6356858462325b4a005e4005/3a968/subcategory-dropdown.png","srcSet":"/static/48862b8f6356858462325b4a005e4005/1ca00/subcategory-dropdown.png 477w,\n/static/48862b8f6356858462325b4a005e4005/8e0ac/subcategory-dropdown.png 954w,\n/static/48862b8f6356858462325b4a005e4005/3a968/subcategory-dropdown.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/48862b8f6356858462325b4a005e4005/81b11/subcategory-dropdown.webp 477w,\n/static/48862b8f6356858462325b4a005e4005/3f803/subcategory-dropdown.webp 954w,\n/static/48862b8f6356858462325b4a005e4005/5c38e/subcategory-dropdown.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":1073}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABw0lEQVQoz52ST2sTQRyG95OYajY2EhKbFUT0u3hMtps0lybu7M7+JQWLePCcgynoUujBi9BTBReRBDz4MQQPFg8VtLqPzOSPSbAILrzMwLz7/N53do179x+w02hwq1qlUa9Tq9XYsSwsy+JmpcL1rS2q29tUTJNSqUTpWknvzXIZs2xSLt+gUavTbN7h7u0mxsN2G7vTpdfr4XQ62LbNruPQtm0eHx4yPjpiNBrxfDzm5Djj2dMntNptHOXZdbTX6e7R6e7htFoYMgiJkoQojknUGkVEUUwQBEwmE9Tz81eh1+/A6/cfiQPJ8OCA4XBImqaEYYgnQ/ZlguEKgS8lMgiQUiKEh/A8BoMBZ2dvuLj4xpfzcy4vf/D501eOX7zC8wWe59HvD5By9p7n+wg/wHg0BwZhqCfFcaynuq7LdDrVyYpilpCi4MPpKa6UyzZxMmumlCbzhIquEqqqi0M1NcsyXfttnpPnOe8mE8YvMwIFTNOlV4VYyFAwlU4njKKlYQEVQvyR685gG5A14H5/gCs8LQVdNesaabqm1YF/k+Hqj+BrheF6wqtSbA5dA4bzukrRivmqBP+SoX+XuaKNO/wf4G/PciRwbkoS2gAAAABJRU5ErkJggg=="},"images":{"fallback":{"src":"/static/121a899de58ff488deebab56460ca498/3a968/vocab-category-create.png","srcSet":"/static/121a899de58ff488deebab56460ca498/1ca00/vocab-category-create.png 477w,\n/static/121a899de58ff488deebab56460ca498/8e0ac/vocab-category-create.png 954w,\n/static/121a899de58ff488deebab56460ca498/3a968/vocab-category-create.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/121a899de58ff488deebab56460ca498/81b11/vocab-category-create.webp 477w,\n/static/121a899de58ff488deebab56460ca498/3f803/vocab-category-create.webp 954w,\n/static/121a899de58ff488deebab56460ca498/5c38e/vocab-category-create.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":1073}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB2UlEQVQoz52ST2sTQRjG95OYahIbCYlNBBH9Lh6TdJPm0myzs7Ozf0jBog14yx8s9iSi6MGjiBF6aMQP4jnGQhNLfjKTbAgqCg48vAPzzO99n92x7t1/wE6xyK1cjmKhQD6fZ6dcplwuczOb5frWFrntbbNPpVKkrqXIZjJk0mky6Qzp9A2K+QKl0h3u3i5hPaxWqdUbNJtN7HqdWq3Grm1TrdV4dHTE89NTBsMhz05OePXyBU+7T6hUq9jas2sbr93Yo97Yw65UsKSvCKKIIAyJdA0CgiDE933Oz8foNZv/MPUSePfpC5GSdA4P6XQ6xHGMUgohFfsywmq7Lp6USN9HSonrCoQQOI7DaDRiPp8znX7nYvqNrxcLXr8/Qxw4COHRajlIubwnPA/X87EOVkBfKdMpDELTVUM1cDabMZlMuLy6gsmEz2/e0vZ9onCZJoyWybTiaDWhpusJdVRzEMe47Tbj8TLyYrEgWWcfPuJ6wngSUBiGa1kapqczEwbB2qS7d7tdhsMh/X6ffq9HbzDg8fGxOfsVtAbutxzarjDS0MSoq/4xrk4gxFpKx92AJQMksjTIFZ6RUsFvZh1tU5sN/yRLreJqJU/nbxf+Jcs8l5U2v83/An8CmZopKWBfrskAAAAASUVORK5CYII="},"images":{"fallback":{"src":"/static/a90b63503709f04e049645b38ce85047/3a968/vocab-subcategory-create.png","srcSet":"/static/a90b63503709f04e049645b38ce85047/1ca00/vocab-subcategory-create.png 477w,\n/static/a90b63503709f04e049645b38ce85047/8e0ac/vocab-subcategory-create.png 954w,\n/static/a90b63503709f04e049645b38ce85047/3a968/vocab-subcategory-create.png 1908w","sizes":"(min-width: 1908px) 1908px, 100vw"},"sources":[{"srcSet":"/static/a90b63503709f04e049645b38ce85047/81b11/vocab-subcategory-create.webp 477w,\n/static/a90b63503709f04e049645b38ce85047/3f803/vocab-subcategory-create.webp 954w,\n/static/a90b63503709f04e049645b38ce85047/5c38e/vocab-subcategory-create.webp 1908w","type":"image/webp","sizes":"(min-width: 1908px) 1908px, 100vw"}]},"width":1908,"height":1073}}]}},{"image":{"childrenImageSharp":[{"gatsbyImageData":{"layout":"constrained","placeholder":{"fallback":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe7Ngo//xAAWEAADAAAAAAAAAAAAAAAAAAARICH/2gAIAQEAAQUCNX//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAZEAEAAgMAAAAAAAAAAAAAAAABABEgMfD/2gAIAQEAAT8hVpLeMf/aAAwDAQACAAMAAAAQcw//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAgIDAAAAAAAAAAAAAAABETEQIQBB8P/aAAgBAQABPxAgAx3rmm248nIBWP/Z"},"images":{"fallback":{"src":"/static/9dbde18b0db661da1e59df6eaa1e4dd4/8456e/vocab-DB.jpg","srcSet":"/static/9dbde18b0db661da1e59df6eaa1e4dd4/1936f/vocab-DB.jpg 440w,\n/static/9dbde18b0db661da1e59df6eaa1e4dd4/8c13f/vocab-DB.jpg 879w,\n/static/9dbde18b0db661da1e59df6eaa1e4dd4/8456e/vocab-DB.jpg 1758w","sizes":"(min-width: 1758px) 1758px, 100vw"},"sources":[{"srcSet":"/static/9dbde18b0db661da1e59df6eaa1e4dd4/877c8/vocab-DB.webp 440w,\n/static/9dbde18b0db661da1e59df6eaa1e4dd4/d7364/vocab-DB.webp 879w,\n/static/9dbde18b0db661da1e59df6eaa1e4dd4/de02b/vocab-DB.webp 1758w","type":"image/webp","sizes":"(min-width: 1758px) 1758px, 100vw"}]},"width":1908,"height":1041.9112627986349}}]}}]}}}]}}}