<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rad Ghost</title>
    <description>The latest articles on DEV Community by Rad Ghost (@radghost).</description>
    <link>https://dev.to/radghost</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1531664%2F7186b4a3-2f6a-4a40-9615-a3fc786a3cc2.jpg</url>
      <title>DEV Community: Rad Ghost</title>
      <link>https://dev.to/radghost</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/radghost"/>
    <language>en</language>
    <item>
      <title>I turned an abandoned Go project into a full terminal Arcade Game</title>
      <dc:creator>Rad Ghost</dc:creator>
      <pubDate>Thu, 28 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/radghost/i-turned-an-abandoned-go-project-into-a-full-terminal-arcade-game-4ck2</link>
      <guid>https://dev.to/radghost/i-turned-an-abandoned-go-project-into-a-full-terminal-arcade-game-4ck2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;NovaDash&lt;/strong&gt;, a retro-inspired terminal arcade dungeon crawler written in Go using the Charm ecosystem.&lt;/p&gt;

&lt;p&gt;Originally, NovaDash wasn’t supposed to become a full game at all. I originally created the project as a way to learn Go while exploring the terminal UI ecosystem from &lt;a href="https://charm.sh/" rel="noopener noreferrer"&gt;Charm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was fascinated by how modern terminal applications could feel animated, interactive, and visually polished instead of looking like traditional command-line tools.&lt;/p&gt;

&lt;p&gt;The project started as an excuse to experiment with several parts of the Charm ecosystem, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/charmbracelet/bubbletea" rel="noopener noreferrer"&gt;Bubble Tea&lt;/a&gt; for the core application architecture and game loop&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/charmbracelet/lipgloss" rel="noopener noreferrer"&gt;Lip Gloss&lt;/a&gt; for styling and retro terminal visuals&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/charmbracelet/bubbles" rel="noopener noreferrer"&gt;Bubbles&lt;/a&gt; for reusable TUI components&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/charmbracelet/harmonica" rel="noopener noreferrer"&gt;Harmonica&lt;/a&gt; for smooth animations and motion&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/charmbracelet/log" rel="noopener noreferrer"&gt;Charm Log&lt;/a&gt; for structured logging and debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the time, I just wanted to see how far I could push a terminal application aesthetically and mechanically. So I built a tiny retro-style prototype to experiment with movement, rendering, and gameplay ideas inside the terminal.&lt;/p&gt;

&lt;p&gt;Then I abandoned it.&lt;/p&gt;

&lt;p&gt;For a long time, it sat untouched in my computer archives as a half-finished experiment that never really became a “real” game.&lt;/p&gt;

&lt;p&gt;When the Finish-Up-A-Thon challenge appeared, I decided to revisit the project and see how far I could push the idea.&lt;/p&gt;

&lt;p&gt;That abandoned prototype eventually evolved into a full arcade experience featuring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;50 handcrafted levels&lt;/li&gt;
&lt;li&gt;Animated ASCII visuals&lt;/li&gt;
&lt;li&gt;Multiple enemy types&lt;/li&gt;
&lt;li&gt;Power-ups and inventory systems&lt;/li&gt;
&lt;li&gt;Time manipulation mechanics&lt;/li&gt;
&lt;li&gt;Save/resume support&lt;/li&gt;
&lt;li&gt;Scoring and leaderboard systems&lt;/li&gt;
&lt;li&gt;Embedded retro soundtrack/audio&lt;/li&gt;
&lt;li&gt;AI autopilot&lt;/li&gt;
&lt;li&gt;Automated testing&lt;/li&gt;
&lt;li&gt;Cross-platform builds for Linux, macOS, and Windows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entire game runs directly inside the terminal.&lt;/p&gt;

&lt;p&gt;One of my favorite parts of the project was pushing the terminal beyond what people normally expect from it. I wanted NovaDash to feel fast, chaotic, colorful, and arcade-like instead of feeling like a traditional CLI application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GitHub Repository
&lt;/h3&gt;

&lt;p&gt;Check out the repo to download the game, no development required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/RiskyFrisky/NovaDash" rel="noopener noreferrer"&gt;https://github.com/RiskyFrisky/NovaDash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Before — The Original Prototype
&lt;/h3&gt;

&lt;p&gt;This was the original version before the challenge:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/bZpy6W02zXc"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can also see how small the original project was by looking at the very first commit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/RiskyFrisky/NovaDash/commit/8a669fdb43f5e2cea7f898be728db1a4a456d49f" rel="noopener noreferrer"&gt;https://github.com/RiskyFrisky/NovaDash/commit/8a669fdb43f5e2cea7f898be728db1a4a456d49f&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the time, it was mostly just movement, simple enemies, and rendering experiments.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Result — NovaDash Today
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Up-lndVjK60"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;By the end of the challenge, the project had transformed into a full retro arcade-style dungeon crawler running entirely inside the terminal.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;The biggest change wasn’t just adding features — it was turning the project from a prototype into something that actually felt complete.&lt;/p&gt;

&lt;p&gt;At first, NovaDash was only a small experiment to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;terminal rendering&lt;/li&gt;
&lt;li&gt;The Elm Architecture (TEA)&lt;/li&gt;
&lt;li&gt;and the Charm ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was especially interested in how Bubble Tea structures applications into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt; → state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update&lt;/strong&gt; → logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt; → rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That architecture ended up making the game surprisingly scalable as more mechanics were added.&lt;/p&gt;

&lt;p&gt;The original version was extremely simple. It had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;basic movement,&lt;/li&gt;
&lt;li&gt;primitive enemies,&lt;/li&gt;
&lt;li&gt;and minimal gameplay.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coming back to the project for the challenge, I wanted to push the idea much further.&lt;/p&gt;

&lt;p&gt;Over time I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;handcrafted level progression,&lt;/li&gt;
&lt;li&gt;more advanced enemy behavior,&lt;/li&gt;
&lt;li&gt;inventory systems,&lt;/li&gt;
&lt;li&gt;tactical power-ups,&lt;/li&gt;
&lt;li&gt;time-based mechanics,&lt;/li&gt;
&lt;li&gt;save/resume functionality,&lt;/li&gt;
&lt;li&gt;audio,&lt;/li&gt;
&lt;li&gt;visual polish,&lt;/li&gt;
&lt;li&gt;and gameplay balancing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the new mechanics included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Space Bombs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Speed Boosts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time Rush&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time Slow&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Invincibility&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One feature that became unexpectedly useful was the &lt;strong&gt;AI autopilot system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Originally it started as a fun experiment, but it quickly became an important debugging and balancing tool because it could automatically play levels and help verify that every stage was actually beatable.&lt;/p&gt;

&lt;p&gt;I also wanted the project to feel like a real downloadable game rather than just a source repository.&lt;/p&gt;

&lt;p&gt;To make that happen, I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automated tests,&lt;/li&gt;
&lt;li&gt;GitHub Actions CI pipelines,&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;and cross-platform builds that generate native executables for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux&lt;/li&gt;
&lt;li&gt;macOS&lt;/li&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;That way players can simply download the game and run it directly without needing to build from source themselves.&lt;/p&gt;

&lt;p&gt;The soundtrack and audio (generated with &lt;a href="https://suno.com/" rel="noopener noreferrer"&gt;Suno&lt;/a&gt;) were also embedded directly into the binary, helping reinforce the retro synthwave arcade atmosphere.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot became a huge part of the development process for NovaDash.&lt;/p&gt;

&lt;p&gt;I used several models throughout development depending on what I was working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPT-5.4&lt;/li&gt;
&lt;li&gt;GPT-5-mini&lt;/li&gt;
&lt;li&gt;gemma4:31b-cloud through Ollama&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What surprised me most was how iterative and collaborative the workflow became.&lt;/p&gt;

&lt;p&gt;I didn’t design the entire game upfront.&lt;/p&gt;

&lt;p&gt;Instead, the project evolved feature by feature.&lt;/p&gt;

&lt;p&gt;Often I would finish implementing one mechanic, and Copilot would help suggest the next logical improvement or expansion idea.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;after adding bombs, new tactical gameplay ideas appeared,&lt;/li&gt;
&lt;li&gt;after implementing progression, level balancing evolved,&lt;/li&gt;
&lt;li&gt;after improving enemies, the autopilot system emerged,&lt;/li&gt;
&lt;li&gt;and after polishing gameplay, more quality-of-life systems followed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That iterative loop is honestly how the game became much larger and more polished than I originally expected.&lt;/p&gt;

&lt;p&gt;I also experimented with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;custom Copilot skills,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;structured prompting workflows,&lt;/li&gt;
&lt;li&gt;and architecture guidance systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some resources that helped:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/github/awesome-copilot" rel="noopener noreferrer"&gt;https://github.com/github/awesome-copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/obra/superpowers" rel="noopener noreferrer"&gt;https://github.com/obra/superpowers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/multica-ai/andrej-karpathy-skills" rel="noopener noreferrer"&gt;https://github.com/multica-ai/andrej-karpathy-skills&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing I really liked about the process was that Copilot didn’t just help speed up coding — it helped sustain momentum. Reviving an abandoned project can be difficult, but having an AI workflow that constantly helped iterate on ideas made it much easier to keep improving the game piece by piece.&lt;/p&gt;

&lt;p&gt;Finishing NovaDash ended up becoming one of the most satisfying projects I’ve worked on, especially because it started as something I thought I would probably never touch again.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>ai</category>
      <category>go</category>
    </item>
    <item>
      <title>TrackNChat - Look up your tracking numbers in one place</title>
      <dc:creator>Rad Ghost</dc:creator>
      <pubDate>Mon, 27 May 2024 06:03:58 +0000</pubDate>
      <link>https://dev.to/radghost/tracknchat-look-up-your-tracking-numbers-in-one-place-53eb</link>
      <guid>https://dev.to/radghost/tracknchat-look-up-your-tracking-numbers-in-one-place-53eb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/aws"&gt;The AWS Amplify Fullstack TypeScript Challenge &lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;Many businesses often require a solution to notify customers about the tracking status of their packages (i.e. whether the package has arrived, where the package is in transit, and how long until the package arrives). We offer an easy-to-use web app that allows users to query information about tracking numbers and get the data they need in a single place. This is useful for some businesses that may not have an automated system in place to send tracking status to their customers, but want a quick and easy way to check the tracking status of their customers' packages in one place. This can also be used by customers to check their package tracking status as well. To use the app, you ask the chatbot information about your tracking number, and it'll respond back with relevant information about the tracking status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Try the &lt;a href="https://main.d1p7vujy19xg7x.amplifyapp.com"&gt;live app here&lt;/a&gt;! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Chat interface&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjinnlwzkhnxkb37g35ue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjinnlwzkhnxkb37g35ue.png" alt="Image description" width="623" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;View previous sessions&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1iekm4bzlc85e75lkdxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1iekm4bzlc85e75lkdxv.png" alt="Image description" width="623" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/ImgyeongLee/TrackNChat"&gt;code here&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;Our team consisted of 2 members, and we spent a single day working on the project (actually on the same day the project was to be turned in for the hackathon) from the idea to submission. It was a fun sprint to see how much we could get done in a short time and to learn/try new technologies we hadn't used before. We used AWS Amplify to power our full-stack application and AWS Lex to power the chatbot. While working on our project, we discovered how easy it was to follow the Amplify docs to get started and incorporate all their components including frontend, backend, hosting, data storage, and automated CI/CD. In regards to the chatbot, at first we considered developing a custom AI agent/tool, but realized that it would take too much time, and so in our search for something simpler, we came across AWS Lex which already had documenation on how to connect it with AWS Amplify. We found that using AWS Lex worked surprisingly well, and we could ask the chatbot in human language, and it'd be able to understand our intent and parse out the tracking number from the query. We weren't able to accomplish all the things that we'd like to implement, but we were proud that we got a chance to learn new technologies and build a fun and useful tool.&lt;/p&gt;

&lt;p&gt;These are some of the things we'd like to incorporate into our app in the future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interact with the UPS, USPS, FedEx, DHL, etc. APIs to could get direct access to the tracking information rather than using an NPM package that provides basic details on a tracking number. We would've implemented this, but we found out that when we signed up for the USPS API, they require an approval process that we simply didn't have time to wait for.&lt;/li&gt;
&lt;li&gt;Allow uploading of CSVs/Excel files in bulk to process many tracking numbers and the chatbot would provide the status of all tracking numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Connected Components and/or Feature Full&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an architecture of how our system works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosnuxovpi73k66msgoss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosnuxovpi73k66msgoss.png" alt="Image description" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When an user interacts with our NextJS web app, they can ask information about their tracking number, and it'll send a request to AWS Lex which forwards the request to AWS Lambda which can make a request to the shipping provider APIs to provide information on the tracking number. It turns out AWS Lex works very similar to Amazon Alexa and you can optionally add in generative AI support with AWS Bedrock for even better customer interaction.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AWS Lex chatbot configuration&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwy14n8rw4koirhlx2mj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwy14n8rw4koirhlx2mj.png" alt="Image description" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AWS Lambda handler to process chatbot events that match the QueryTracking intent&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sessionState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fulfilled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;sessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dialogAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trackingNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpretations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slots&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TrackingNumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpretedValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getTracking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trackingNumber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- returns tracking details in this object&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sessionState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PlainText&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NextJS interaction with chatbot (triggered every time user enters a chat message)&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submitMsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Interactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;botName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NextJS callback for chatbot responses&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Interactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;botName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bot conversation failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// &amp;lt;process chatbot response here (e.g. display to user)&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All users are assigned a guest user id, provided by the AWS Cognito service. We use this id to store chat sessions and all the chat content so that users can refer back to their previous chat histories. Users can also optionally sign in to save their chat sessions to their accounts instead. This is similar to ChatGPT's website where you can view all your chat history. The data is read from/written to DynamoDB via AppSync GraphQL. And all of this is abstracted with the AWS Amplify typescript SDK!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Authentication component&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Authenticator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{({&lt;/span&gt; &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sign&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Authenticator&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Data schema&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;ChatSession&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;chatContents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ChatContent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatSessionId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publicApiKey&lt;/span&gt;&lt;span class="p"&gt;()]),&lt;/span&gt;
    &lt;span class="na"&gt;ChatContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BOT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="na"&gt;chatSessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;chatSession&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ChatSession&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatSessionId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publicApiKey&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the issues we currently still encounter is when we create a new ChatSession record in the database and try to get the data back with a query like this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GraphQL query&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyQuery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;getChatContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8f525820-8132-42ca-82e6-fa49116d3e2b"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;chatSessionId&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;listChatContents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chatSessionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"b56b034e-3cb5-479b-92fa-cebe1bd74e9c"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The data returned ends up being like this. For some reason &lt;code&gt;listChatContents&lt;/code&gt; is empty even though it should contain the same data as &lt;code&gt;getChatContent&lt;/code&gt;. If anyone has an answer to this problem, please let us know in the comments.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JSON output&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"getChatContent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8f525820-8132-42ca-82e6-fa49116d3e2b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Some content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"chatSessionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"b56b034e-3cb5-479b-92fa-cebe1bd74e9c"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"listChatContents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Continuing on, the NextJS app is styled with tailwindss and shadcn, and it is hosted on AWS Amplify. Every time we push new code changes to our GitHub repo, AWS Amplify will automatically build and deploy the new version of our app to the live site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And, that wraps up our project. We had a lot of fun working on this project and participating in this hackathon. It gave us a chance to apply our skills as well as explore the new AWS Amplify gen 2 platform and other AWS services as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a class="mentioned-user" href="https://dev.to/radghost"&gt;@radghost&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a class="mentioned-user" href="https://dev.to/imgyeonglee"&gt;@imgyeonglee&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>awschallenge</category>
      <category>amplify</category>
      <category>fullstack</category>
    </item>
  </channel>
</rss>
