<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Young developers based in Tokyo, Yoyogi.]]></title><description><![CDATA[Young developers based in Tokyo, Yoyogi.]]></description><link>https://amplify-space.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1690644750775/xzDPSS5xy.png</url><title>Young developers based in Tokyo, Yoyogi.</title><link>https://amplify-space.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 19 Sep 2026 19:58:36 GMT</lastBuildDate><atom:link href="https://amplify-space.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Sound Byte - Article Summarizer App with Text-to-Speech!]]></title><description><![CDATA[Introduction
Sound Byte is an app that provides summaries and audio output of articles from their URLs. With this app, you can receive news not only visually but also through auditory input, allowing you to listen to the news instead of reading it.
L...]]></description><link>https://amplify-space.hashnode.dev/sound-byte</link><guid isPermaLink="true">https://amplify-space.hashnode.dev/sound-byte</guid><category><![CDATA[AWS Amplify]]></category><category><![CDATA[AWS Amplify Hackathon]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[#AWSAmplify and #AWSAmplifyHackathon]]></category><dc:creator><![CDATA[taksnr]]></dc:creator><pubDate>Mon, 31 Jul 2023 17:54:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1690824971132/8b778535-af89-4be0-9e37-e129d72cd458.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Sound Byte is an app that provides summaries and audio output of articles from their URLs. With this app, you can receive news not only visually but also through auditory input, allowing you to listen to the news instead of reading it.</p>
<h3 id="heading-links">Links</h3>
<p><a target="_blank" href="https://github.com/Kaiki-kk/sound-byte">GitHub Repository</a></p>
<p><a target="_blank" href="https://sound-byte.vercel.app/">Application</a></p>
<h1 id="heading-how-to-play">How to Play</h1>
<ol>
<li><p>Sign in to the app.</p>
<ul>
<li><p>Username: <a target="_blank" href="mailto:soundbyteamplify@gmail.com">soundbyteamplify@gmail.com</a></p>
</li>
<li><p>Password: amplify@12345</p>
</li>
</ul>
</li>
<li><p>Send a URL.</p>
</li>
<li><p>Press the play button.</p>
</li>
</ol>
<h3 id="heading-demo-video">Demo Video</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/GFXXYi8BxDc">https://youtu.be/GFXXYi8BxDc</a></div>
<p> </p>
<hr />
<h1 id="heading-why-we-do">Why we do</h1>
<h3 id="heading-problem">Problem</h3>
<p>Busy modern people do not have much time. However, we are forced to have a large amount of input to survive. We don't have time to read the news as it is of interest to us.</p>
<h3 id="heading-solution">Solution</h3>
<p>Reading a text article in its entirety is time-consuming and is only possible in an environment where you can see the device. However, this makes it impossible to input news on the move or when the device is not at hand. So we summarized the text articles and output them in audio.</p>
<hr />
<h1 id="heading-how-we-built">How we built🚀</h1>
<h2 id="heading-andltawsandgt">&lt;AWS&gt;</h2>
<h3 id="heading-cognito-authentication">Cognito: Authentication</h3>
<p>Amplify can easily implement authentication using Cognito. This time, we used the Amplify CLI to build authentication.<br />You can build authentication with a single command from the Amplify CLI.</p>
<pre><code class="lang-bash">amplify add auth
</code></pre>
<h3 id="heading-appsync-graphql-api">AppSync: GraphQL API</h3>
<p>AppSync is used with the GraphQL API.<br />Using the GraphQL category of the Amplify CLI, we have created a database-based GraphQL API that can also be built with a single command from the Amplify CLI.</p>
<pre><code class="lang-bash">amplify add api
</code></pre>
<h3 id="heading-data-modeling">Data Modeling</h3>
<p>We created a data model with schema.graphQL created by <code>amplify add api.</code><br />By using <code>@model</code>, Amazon DynamoDB database tables are automatically created.<br />We also use <code>@auth</code> and <code>@hasMany</code> to build the data model.</p>
<pre><code class="lang-yaml"><span class="hljs-string">//</span> <span class="hljs-string">amplify/backend/api/soundbyte/schema.graphql</span>

<span class="hljs-string">type</span> <span class="hljs-string">User</span>
  <span class="hljs-string">@model</span>
  <span class="hljs-string">@auth(rules:</span> [{ <span class="hljs-attr">allow:</span> <span class="hljs-string">private</span>, <span class="hljs-attr">provider:</span> <span class="hljs-string">userPools</span> }, { <span class="hljs-attr">allow:</span> <span class="hljs-string">private</span>, <span class="hljs-attr">provider:</span> <span class="hljs-string">iam</span> }]<span class="hljs-string">)</span> {
  <span class="hljs-attr">id:</span> <span class="hljs-string">ID!</span>
  <span class="hljs-attr">email:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">articles:</span> [<span class="hljs-string">Article</span>] <span class="hljs-string">@hasMany</span>
}

<span class="hljs-string">type</span> <span class="hljs-string">Article</span> <span class="hljs-string">@model</span> <span class="hljs-string">@auth(rules:</span> [{ <span class="hljs-attr">allow:</span> <span class="hljs-string">private</span>, <span class="hljs-attr">provider:</span> <span class="hljs-string">userPools</span> }]<span class="hljs-string">)</span> {
  <span class="hljs-attr">id:</span> <span class="hljs-string">ID!</span>
  <span class="hljs-attr">title:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">content:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">sourceUrl:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">speechUrl:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">userId:</span> <span class="hljs-string">ID!</span> <span class="hljs-string">@index(name:</span> <span class="hljs-string">"byUserId"</span>, <span class="hljs-attr">queryField:</span> <span class="hljs-string">"articlesByUserId"</span><span class="hljs-string">)</span>
  <span class="hljs-attr">user:</span> <span class="hljs-string">User!</span> <span class="hljs-string">@hasOne(fields:</span> [<span class="hljs-string">"userId"</span>]<span class="hljs-string">)</span>
}

<span class="hljs-string">type</span> <span class="hljs-string">GenerateSummaryTextResponse</span> {
  <span class="hljs-attr">title:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">summaryText:</span> <span class="hljs-string">String!</span>
}

<span class="hljs-string">type</span> <span class="hljs-string">Query</span> {
  <span class="hljs-string">generateSummaryTextQuery(url:</span> <span class="hljs-string">String!):</span> <span class="hljs-string">GenerateSummaryTextResponse!</span>
    <span class="hljs-string">@auth(rules:</span> [{ <span class="hljs-attr">allow:</span> <span class="hljs-string">private</span>, <span class="hljs-attr">provider:</span> <span class="hljs-string">userPools</span> }]<span class="hljs-string">)</span>
    <span class="hljs-string">@function(name:</span> <span class="hljs-string">"generateSummaryText"</span><span class="hljs-string">)</span>
  <span class="hljs-attr">textToGenerateSpeech:</span> <span class="hljs-string">String</span>
    <span class="hljs-string">@auth(rules:</span> [{ <span class="hljs-attr">allow:</span> <span class="hljs-string">private</span>, <span class="hljs-attr">provider:</span> <span class="hljs-string">userPools</span> }]<span class="hljs-string">)</span>
    <span class="hljs-string">@predictions(actions:</span> [<span class="hljs-string">convertTextToSpeech</span>]<span class="hljs-string">)</span>
}
</code></pre>
<h3 id="heading-dynamodb-database">DynamoDB: Database</h3>
<p>Automatically creates Amazon DynamoDB database tables based on <code>schema.graphql</code></p>
<h3 id="heading-lambda-function">Lambda: Function</h3>
<p>Lambda is run via AppSync to retrieve and summarize articles and output audio.<br />This Lambda was built using a container image because the use of newspaper, a library for Python scraping, could only be achieved by building with a container image.</p>
<pre><code class="lang-python"><span class="hljs-comment">## This function is generated by Dockerfile in the same directory, so you need to build the image and push it to ECR.</span>

<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">from</span> newspaper <span class="hljs-keyword">import</span> Article

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handler</span>(<span class="hljs-params">event, context</span>):</span>
  arguments = event.get(<span class="hljs-string">"arguments"</span>)
  url = arguments.get(<span class="hljs-string">"url"</span>)

  openai.api_key = os.environ[<span class="hljs-string">"GPT_API_KEY"</span>]

  <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> url:
    <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"The attribute url is required."</span>)

  <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> openai.api_key:
    <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"There is a missing environment variable."</span>)

  <span class="hljs-keyword">try</span>:
    article = Article(url)
    article.download()
    article.parse()

    title = article.title

    text = article.text

    chat_completion = openai.ChatCompletion.create(model=<span class="hljs-string">"gpt-3.5-turbo"</span>, messages=[{<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"The following is the text of a news article. Please summarize this sentence in plain English.<span class="hljs-subst">{text}</span>"</span>}])

    <span class="hljs-keyword">return</span> {
      <span class="hljs-string">"summaryText"</span>: chat_completion[<span class="hljs-string">"choices"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"message"</span>][<span class="hljs-string">"content"</span>],
      <span class="hljs-string">"title"</span>: title
    }
  <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> err:
    print(err)
    <span class="hljs-keyword">raise</span> Exception(<span class="hljs-string">"internal server error"</span>)
</code></pre>
<pre><code class="lang-json"><span class="hljs-comment">// amplify/backend/api/soundbyte/schema.graphql</span>
type Query {
  generateSummaryTextQuery(url: String!): GenerateSummaryTextResponse!
    @auth(rules: [{ allow: private, provider: userPools }])
    @function(name: <span class="hljs-string">"generateSummaryText"</span>)
<span class="hljs-comment">/// ...</span>
}
</code></pre>
<h3 id="heading-storage-to-use-amazon-polly">Storage: To use amazon polly</h3>
<p>I am adding storage to use amazon polly. You can build authentication with a single command from the Amplify CLI.</p>
<pre><code class="lang-bash">amplify add storage
</code></pre>
<h3 id="heading-amazon-polly-text-to-speech">Amazon Polly: Text to Speech</h3>
<p>Amazon Polly is used to convert summarized content into speech.<br />We chose Amazon Polly because of its natural voice, support for dozens of languages, and ease of use in Amplify projects.</p>
<hr />
<h2 id="heading-andltdesignandgt">&lt;Design&gt;</h2>
<p>We organized the model, designed the database, and designed the page in Figma.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690805862041/a693f5ba-2b13-4e08-9c5d-53585654886d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690643303065/b65d7cdb-2340-4fc2-98d5-426f5cacd9fd.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-andltfrontendandgt">&lt;Frontend&gt;</h2>
<h3 id="heading-mui">MUI</h3>
<p>Various UI components could be used for free and easily.</p>
<h3 id="heading-next-js">Next js</h3>
<p>Next js could be incorporated into Amplify.</p>
<hr />
<h2 id="heading-andltbackend-or-summaryandgt">&lt;Backend | Summary&gt;</h2>
<h3 id="heading-newspaper-scraping">newspaper: scraping</h3>
<p>Using Python’s newspaper library, we were able to get the full text of the article.</p>
<h3 id="heading-chatgpt-summary">ChatGPT: summary</h3>
<p>Using ChatGPT’s API, the obtained text can be summarized with high accuracy.</p>
<hr />
<h2 id="heading-andlthostingandgt">&lt;Hosting&gt;</h2>
<h3 id="heading-vercel">Vercel</h3>
<p>Since the latest Next js version cannot be hosted by Amplify Hosting, we adopted Vercel for hosting this time.<br />Vercel was also able to host projects using Amplify and Next js with high speed.</p>
<hr />
<h1 id="heading-tech-stack">Tech Stack</h1>
<h3 id="heading-aws">AWS</h3>
<ul>
<li><p>Cognito: Authentication</p>
</li>
<li><p>AppSync: Graphql API</p>
</li>
<li><p>Lambda: Function</p>
</li>
<li><p>Polly: Text to Speech</p>
</li>
<li><p>DynamoDB: Database</p>
</li>
<li><p>Storage: S3</p>
</li>
</ul>
<h3 id="heading-design">Design</h3>
<ul>
<li><p>Figma: design</p>
</li>
<li><p>Figjam: modering</p>
</li>
</ul>
<h3 id="heading-frontend">Frontend</h3>
<ul>
<li><p>MUI</p>
</li>
<li><p>NextJS</p>
</li>
</ul>
<h3 id="heading-backend-or-summary">Backend | Summary</h3>
<ul>
<li><p>ChatGPT: summary</p>
</li>
<li><p>newspaper: scraping</p>
</li>
</ul>
<h3 id="heading-hosting">Hosting</h3>
<ul>
<li>Vercel</li>
</ul>
<hr />
<h1 id="heading-conclusion">Conclusion</h1>
<p>This time we were able to achieve our goal of creating a minimalist app at high speed using Amplify. Amazon Polly and Chat GPT are easy to connect to AppSync, and Amplify provides a very comfortable development experience by making it easy to incorporate AWS services. It is a great service to try out products. Thanks to <a target="_blank" href="https://hashnode.com/?source=aws-amplify-2023">Hashnode</a> and <a target="_blank" href="https://aws.amazon.com/jp/pm/amplify/?sc_channel=el&amp;trk=bc603709-686b-4e27-b79f-07e5de3686ec">AWS Amplify</a> for this opportunity. Thank you.</p>
]]></content:encoded></item></channel></rss>