<?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: Moeki Kawakami</title>
    <description>The latest articles on DEV Community by Moeki Kawakami (@moekidev).</description>
    <link>https://dev.to/moekidev</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%2F962103%2F0afbca2d-79d5-4b2b-9e1d-b52c4fa535b4.jpg</url>
      <title>DEV Community: Moeki Kawakami</title>
      <link>https://dev.to/moekidev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moekidev"/>
    <language>en</language>
    <item>
      <title>Integrating LLM into your Rails applications</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Wed, 28 Jun 2023 09:02:18 +0000</pubDate>
      <link>https://dev.to/moekidev/integrating-llm-into-your-rails-applications-52h6</link>
      <guid>https://dev.to/moekidev/integrating-llm-into-your-rails-applications-52h6</guid>
      <description>&lt;p&gt;LLM libraries are more prevalent in Python and TypeScript, and it seems that Ruby, which I will talk about this time, is still not as popular. However, &lt;strong&gt;I believe that a considerable number of people are developing applications with Rails&lt;/strong&gt; and there is a strong demand to integrate LLM functionality into those applications. In the end, many people may feel that implementing LLMs with Python or TypeScript, which they are not familiar with, is not well-connected to their usual web development applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current State of LLM Libraries (as of June 28, 2023)
&lt;/h2&gt;

&lt;p&gt;First, let's summarize the current state of LLM libraries for Python and TypeScript, which are likely to have many users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Python
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/openai/openai-python"&gt;openai/openai-python: The OpenAI Python library provides convenient access to the OpenAI API from applications written in the Python language.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pinecone-io/pinecone-python-client"&gt;pinecone-io/pinecone-python-client: The Pinecone Python client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hwchase17/langchain"&gt;hwchase17/langchain: ⚡ Building applications with LLMs through composability ⚡&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jerryjliu/llama_index"&gt;jerryjliu/llama_index: LlamaIndex (GPT Index) is a data framework for your LLM applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/guidance"&gt;microsoft/guidance: A guidance language for controlling large language models.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/openai/openai-node"&gt;openai/openai-node: Node.js library for the OpenAI API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rileytomasek/pinecone-client"&gt;rileytomasek/pinecone-client: Pinecone.io client with excellent TypeScript support.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hwchase17/langchainjs"&gt;hwchase17/langchainjs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Surprisingly, there are options for Ruby as well
&lt;/h2&gt;

&lt;p&gt;Now let's introduce recommended libraries for Ruby.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boxcars
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/BoxcarsAI/boxcars"&gt;BoxcarsAI/boxcars: Building applications with composability using Boxcars with LLM's. Inspired by LangChain.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike Langchain, Boxcars offers a wide range of features for &lt;strong&gt;generating queries for LLMs, such as Google search, SQL, and ActiveRecord&lt;/strong&gt;, rather than integration with a vector database. The experience of operating ActiveRecord with natural language is quite interesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Langchain.rb
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/andreibondarev/langchainrb"&gt;andreibondarev/langchainrb: Build LLM-backed Ruby applications&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an unofficial Ruby version of Langchain. It will eventually change its name, but for now, it is using this name. I am also involved in its development. In recent updates, &lt;strong&gt;integration with ActiveRecord has been added&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Hooks have been provided to update the data in the connected vector database in sync with updates on the ActiveRecord (RDB) side. For example, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;vectorsearch&lt;/span&gt; &lt;span class="ss"&gt;provider: &lt;/span&gt;&lt;span class="no"&gt;Langchain&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Vectorsearch&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                 &lt;span class="ss"&gt;api_key: &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
         &lt;span class="ss"&gt;environment: &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
                 &lt;span class="ss"&gt;index_name: &lt;/span&gt;&lt;span class="s2"&gt;"Products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="ss"&gt;llm: &lt;/span&gt;&lt;span class="no"&gt;Langchain&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;LLM&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;api_key: &lt;/span&gt;&lt;span class="c1"&gt;# ...&lt;/span&gt;
               &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;after_save&lt;/span&gt; &lt;span class="ss"&gt;:upsert_to_vectorsearch&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's easy to imagine the integration with actual applications!&lt;/p&gt;

&lt;h3&gt;
  
  
  Baran
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/moekidev/baran"&gt;moekidev/baran: Text Splitter for Large Language Model (LLM) datasets.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Baran is a library I recently released for &lt;strong&gt;text splitting&lt;/strong&gt;. Text splitting is quite common in the context of LLMs. It is an effective method to bypass the token limit of prompts and improve the accuracy of vector searches. For example, in Langchain, there is a module called Text Splitter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter"&gt;Split by character | 🦜️🔗 Langchain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Baran is also used in Langchain.rb. It can split Markdown as well, and here's an example of how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Baran&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MarkdownSplitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; [{ cursor: 0, text: "..." }, ...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although it may be an overstatement to use Langchain.rb just for text splitting, I created this library because there were situations where I wanted to perform text splitting.&lt;/p&gt;

&lt;h3&gt;
  
  
  ActivePinecone
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/moekidev/active_pinecone"&gt;moekidev/active_pinecone: ActiveRecord-esque base class that lets you use Pinecone. Enjoy development with LLM and Rails!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is another library I recently released as part of the Active〇〇 series. It allows you to manipulate vector data models using an ActiveRecord-like interface.&lt;/p&gt;

&lt;p&gt;For example, you can define a Recipe model like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Recipe&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActivePinecone&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;vectorizes&lt;/span&gt; &lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:body&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can create and search for recipes with semantic search capabilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;recipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Recipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s2"&gt;"Hamburger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;body: &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;author: &lt;/span&gt;&lt;span class="s2"&gt;"Kevin"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;recipes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Recipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"How to make a hamburger"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;recipes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; "Hamburger"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It even comes with an assistant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;assistant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Recipe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assistant&lt;/span&gt;

&lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"How to make a hamburger)

reply.content
# =&amp;gt; "&lt;/span&gt;&lt;span class="no"&gt;OK&lt;/span&gt;&lt;span class="err"&gt;！&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="s2"&gt;"

reply.references
# [#&amp;lt;Recipe:0x000...&amp;gt;, ...]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be a fun experience!&lt;/p&gt;

&lt;h2&gt;
  
  
  Ruby's LLM contributions are still in progress
&lt;/h2&gt;

&lt;p&gt;All these libraries have a relatively small number of contributors. As I mentioned earlier, personally, I believe that by promoting integration with Rails, we can increasingly enhance the compatibility with the applications developers work on regularly (although it may be more suitable for beginners). So I encourage everyone to participate and contribute!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>langchain</category>
      <category>llm</category>
    </item>
    <item>
      <title>Comparing Vercel Storage and Heroku</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Mon, 15 May 2023 04:23:45 +0000</pubDate>
      <link>https://dev.to/moekidev/comparing-vercel-storage-and-heroku-35b3</link>
      <guid>https://dev.to/moekidev/comparing-vercel-storage-and-heroku-35b3</guid>
      <description>&lt;p&gt;I tried Vercel Storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vercel.com/blog/vercel-storage"&gt;https://vercel.com/blog/vercel-storage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I compared it with an app that was running on Heroku.&lt;/p&gt;

&lt;p&gt;It's Blitz.js, but please don't worry about that too much.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diff
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gh"&gt;diff --git a/Procfile b/Procfile
&lt;/span&gt;&lt;span class="p"&gt;deleted file mode 100644
&lt;/span&gt;&lt;span class="gh"&gt;index bc6eb1f..0000000
&lt;/span&gt;&lt;span class="gd"&gt;--- a/Procfile
&lt;/span&gt;&lt;span class="gi"&gt;+++ /dev/null
&lt;/span&gt;&lt;span class="p"&gt;@@ -1,2 +0,0 @@&lt;/span&gt;
&lt;span class="gd"&gt;-release: npx blitz prisma migrate deploy
-web: npm run start:production
&lt;/span&gt;&lt;span class="gh"&gt;diff --git a/db/schema.prisma b/db/schema.prisma
index 0f8f549..3a35c9b 100644
&lt;/span&gt;&lt;span class="gd"&gt;--- a/db/schema.prisma
&lt;/span&gt;&lt;span class="gi"&gt;+++ b/db/schema.prisma
&lt;/span&gt;&lt;span class="p"&gt;@@ -2,8 +2,9 @@&lt;/span&gt;
 // learn more about it in the docs: https://pris.ly/d/prisma-schema

 datasource db {
&lt;span class="gd"&gt;-  provider = "postgresql"
-  url      = env("DATABASE_URL")
&lt;/span&gt;&lt;span class="gi"&gt;+  provider          = "postgresql"
+  url               = env("POSTGRES_PRISMA_URL") // uses connection pooling
+  shadowDatabaseUrl = env("POSTGRES_URL_NON_POOLING") // used for migrations
&lt;/span&gt; }

 generator client {
&lt;span class="gh"&gt;diff --git a/package.json b/package.json
index f6484ea..a1e0358 100644
&lt;/span&gt;&lt;span class="gd"&gt;--- a/package.json
&lt;/span&gt;&lt;span class="gi"&gt;+++ b/package.json
&lt;/span&gt;&lt;span class="p"&gt;@@ -3,14 +3,13 @@&lt;/span&gt;
   "version": "1.0.0",
   "scripts": {
     "dev": "blitz dev",
&lt;span class="gd"&gt;-    "build": "blitz build",
&lt;/span&gt;&lt;span class="gi"&gt;+    "build": "blitz prisma migrate deploy &amp;amp;&amp;amp; blitz build",
&lt;/span&gt;     "start": "blitz start",
     "studio": "blitz prisma studio",
     "lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
     "test": "vitest run --passWithNoTests",
     "test:watch": "vitest",
&lt;span class="gd"&gt;-    "prepare": "husky install",
-    "start:production": "blitz start --port $PORT"
&lt;/span&gt;&lt;span class="gi"&gt;+    "prepare": "husky install"
&lt;/span&gt;   },
   "prisma": {
     "schema": "db/schema.prisma"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run migration with &lt;code&gt;npm run build&lt;/code&gt; instead of &lt;code&gt;Procfile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Replace with the recommended official env for Postgres URLs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison between Heroku and Vercel
&lt;/h2&gt;

&lt;p&gt;Comparison in this case.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Vercel&lt;/th&gt;
&lt;th&gt;Heroku&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Migration&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Procfile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deploy time&lt;/td&gt;
&lt;td&gt;1m30s&lt;/td&gt;
&lt;td&gt;4m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;Free (up to 1 Database)&lt;/td&gt;
&lt;td&gt;$7.00 + $9.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I didn't expect this comparison table to be realized.&lt;/p&gt;

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

&lt;p&gt;It's nice. Keep up the good work, Vercel.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Should we use ORM?</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Mon, 15 May 2023 04:20:17 +0000</pubDate>
      <link>https://dev.to/moekidev/should-we-use-orm-57fg</link>
      <guid>https://dev.to/moekidev/should-we-use-orm-57fg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vercel.com/docs/storage/vercel-postgres"&gt;https://vercel.com/docs/storage/vercel-postgres&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon the announcement of Vercel Postgres, I personally thought:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There will likely be &lt;strong&gt;more scenarios to use Postgres with Typescript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Started to become interested in the &lt;strong&gt;query builder called Kysely&lt;/strong&gt; that Vercel provides as a wrapper&lt;/li&gt;
&lt;li&gt;I've used &lt;strong&gt;Prisma&lt;/strong&gt; before, but it can be difficult when dealing with complex queries&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vercel/@postgres&lt;/code&gt; is a wrapper for &lt;code&gt;pg&lt;/code&gt;. I want to question the premise of using a query builder or ORM in the first place&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these thoughts in mind, I decided to re-examine the ways to use SQL with Typescript in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Database Driver
&lt;/h3&gt;

&lt;p&gt;Manually generates TCP packets and sends them to the database. It handles connecting to the database and managing the connection pool. At this level, you write raw SQL strings and pass them to the database, and receive responses from the database.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pg"&gt;pg - npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/mysql"&gt;mysql - npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/sqlite3"&gt;sqlite3 - npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Query Builder
&lt;/h3&gt;

&lt;p&gt;Allows you to write SQL queries in Typescript.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/knex"&gt;knex - npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/kysely"&gt;kysely - npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ORM
&lt;/h3&gt;

&lt;p&gt;As the name suggests, it maps RDB records to application objects.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/sequelize-typescript"&gt;sequelize-typescript - npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/prisma"&gt;prisma - npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/bookshelf"&gt;bookshelf - npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overall Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;First, we will look at the opinions of those who use ORM vs query builders, and query builders vs drivers.&lt;/li&gt;
&lt;li&gt;Thoughts&lt;/li&gt;
&lt;li&gt;Practice&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🙋‍♂️ Opinions of those who use ORM
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Everyone is using it
&lt;/h3&gt;

&lt;p&gt;There seems to be a lot of information out there. Is it due to ActiveRecord's contribution?&lt;/p&gt;

&lt;h3&gt;
  
  
  Easily switch databases
&lt;/h3&gt;

&lt;p&gt;For example, if you are using an ORM that supports both Postgres and MySQL, you can "relatively" easily switch between the two (regardless of frequency).&lt;/p&gt;

&lt;h3&gt;
  
  
  ORM can convert object-oriented query methods to SQL
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Applications are written in an object-oriented manner, so SQL can be written in that context&lt;/li&gt;
&lt;li&gt;Focusing on describing the interface allows you to concentrate on business logic&lt;/li&gt;
&lt;li&gt;It's impossible to manage database schema and objects (types) in a DRY manner&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mastering SQL strictly is difficult
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Has robust transaction support&lt;/li&gt;
&lt;li&gt;Guards against SQL injection vulnerabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Supports raw queries
&lt;/h3&gt;

&lt;p&gt;This allows developers to also use raw queries as a means of writing queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Want to leverage the power of TypeScript
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Autocomplete&lt;/li&gt;
&lt;li&gt;Type checking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🙋‍♂️ Opinions of those who use query builders
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Writing raw SQL is painful for dynamic queries
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;pg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO users(name, email) VALUES($1, $2) RETURNING *&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="cm"&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;Kysely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;kysely&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&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="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&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="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  There are occasional queries that cannot be realized with ORM
&lt;/h3&gt;

&lt;p&gt;There are queries that even the giant ActiveRecord cannot handle, and in the end, you have to write raw SQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing complex ORM descriptions can be inefficient (performance)
&lt;/h3&gt;

&lt;p&gt;Kysely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;user_email&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="n"&gt;post&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt;
  &lt;span class="k"&gt;user&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sequelize:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="nv"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user.id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user.name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"email"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user.email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;"user-&amp;gt;post"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"category_id"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user.post.category_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;"user-&amp;gt;post"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"user_id"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user.post.user_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;"user-&amp;gt;post"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"unit"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user.post.unit"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="nv"&gt;"user"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;OUTER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nv"&gt;"post"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user-&amp;gt;post"&lt;/span&gt;
  &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"user-&amp;gt;post"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"user_id"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"user-&amp;gt;post"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"category_id"&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;
&lt;span class="nv"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Supports raw queries
&lt;/h3&gt;

&lt;p&gt;This allows developers to also use raw queries when needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Want to utilize TypeScript's capabilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Autocompletion&lt;/li&gt;
&lt;li&gt;Type checking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🙋‍♂️ Opinions of those who use database drivers directly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Even if you learn a specific ORM or query builder, you cannot apply that knowledge across languages or libraries
&lt;/h3&gt;

&lt;p&gt;For example, the descriptions are subtly different between Sequelize and Prisma, both Node.js libraries.&lt;/p&gt;

&lt;p&gt;Sequelize:&lt;br&gt;
&lt;/p&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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;findAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Kevin&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&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;dataValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prisma:&lt;br&gt;
&lt;/p&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;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&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;findAll&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Kevin&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&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;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, there are only a few dialects of SQL. By learning how to generate queries using raw SQL, you can easily switch between different languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What I felt
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I don't want to learn ORM one by one&lt;/li&gt;
&lt;li&gt;I want to be proficient in SQL&lt;/li&gt;
&lt;li&gt;I want TypeScript to autocomplete&lt;/li&gt;
&lt;li&gt;ORM doesn't reach the itchy spots&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I felt uneasy about
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Transaction and SQL injection prevention when writing raw SQL&lt;/li&gt;
&lt;li&gt;Wondering about the duplication of descriptions in the schema and type (object)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I thought might not be a problem
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Query builder specifications seem simple, so it's easy to learn&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Preliminary conclusion
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I want to try using a query builder&lt;/li&gt;
&lt;li&gt;I still want to define the schema with Prisma&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💪 Practical use of TypeScript (Kysely x Prisma)
&lt;/h2&gt;

&lt;p&gt;For now, I'll define the schema with Prisma and write queries with Kysely!&lt;/p&gt;

&lt;p&gt;There seems to be something like this, but I'll write it myself this time.&lt;br&gt;
&lt;a href="https://github.com/valtyr/prisma-kysely"&gt;valtyr/prisma-kysely: 🪄 Generate Kysely types directly from your Prisma schema!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;schema.prisma&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id        Int       @id @default(dbgenerated("uuid()"))
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  email     String    @unique
  name      String?
  posts     Post[]
}

model Post {
  id          Int      @id @default(dbgenerated("gen_random_uuid()"))
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  title       String
  body        String?
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId      Int
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to note here is the &lt;code&gt;@default&lt;/code&gt;.&lt;br&gt;
In Prisma, it's typically defined like this, but &lt;strong&gt;since this is a JS-based implementation, it will not be reflected in the actual database when inserting with Kysely.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@default(gen_random_uuid())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we'll use the SQL-based UUID like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- @default(uuid())
&lt;/span&gt;&lt;span class="gi"&gt;+ @default(dbgenerated("uuid()"))
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialization of Kysely.&lt;br&gt;
Here, we pass &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Post&lt;/code&gt; from &lt;code&gt;@prisma/client&lt;/code&gt; to Kysely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Kysely&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PostgresDialect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kysely&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&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;Post&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;User&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;
  &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Post&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Kysely&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PostgresDialect&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&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="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;kysely&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trying it out:&lt;br&gt;
&lt;/p&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kysely&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Post&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="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&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="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;For now, I've tried leaving the schema and objects to Prisma and composing queries with Kysely. I'd like to try this for a while. If you have any additional information or advice, please let me know!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I have launched an AI Conversational UX Guide.</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Fri, 28 Apr 2023 00:39:07 +0000</pubDate>
      <link>https://dev.to/moekidev/i-have-launched-an-ai-conversational-ux-guide-of0</link>
      <guid>https://dev.to/moekidev/i-have-launched-an-ai-conversational-ux-guide-of0</guid>
      <description>&lt;p&gt;The proliferation of applications that use language models has caused application developers to consider the unknown conversational UX. This guide summarizes the characteristics of how language models behave in applications and provides guidelines for designing conversational UX.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/uxaidev/AI-Conversational-UX-Guide"&gt;uxaidev/AI-Conversational-UX-Guide: 💡 Guides, blogs and applications list for conversational UX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://guide.uxai.dev/"&gt;AI Conversational UX Guide - AI Conversational UX Guide&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Idea: Converting from Relational Database to Vector Database</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Sun, 16 Apr 2023 09:11:21 +0000</pubDate>
      <link>https://dev.to/moekidev/idea-converting-from-relational-database-to-vector-database-4k4p</link>
      <guid>https://dev.to/moekidev/idea-converting-from-relational-database-to-vector-database-4k4p</guid>
      <description>&lt;h2&gt;
  
  
  What is Vector Database?
&lt;/h2&gt;

&lt;p&gt;Complex data is growing at break-neck speed. These are unstructured forms of data that include documents, images, videos, and plain text on the web. Many organizations would benefit from storing and analyzing complex data, but complex data can be difficult for traditional databases built with structured data in mind. Classifying complex data with keywords and metadata alone may be insufficient to fully represent all of its various characteristics.&lt;/p&gt;

&lt;p&gt;Fortunately, Machine Learning (ML) techniques can offer a far more helpful representation of complex data by transforming it into vector embeddings. Vector embeddings describe complex data objects as numeric values in hundreds or thousands of different dimensions.&lt;/p&gt;

&lt;p&gt;Vector databases are purpose-built to handle the unique structure of vector embeddings. They index vectors for easy search and retrieval by comparing values and finding those that are most similar to one another.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vector Search is more powerful than structured data search with the rise of machine learning
&lt;/h2&gt;

&lt;p&gt;With the release of the OpenAI API, tools such as Langchain, and vector database services such as Pinecone, the use of vector search has become much more accessible than ever before.&lt;/p&gt;

&lt;p&gt;I see a lot of people starting to work with unstructured data in the past few months and experimenting a lot. So what about structured data?&lt;/p&gt;

&lt;p&gt;The method introduced by LLM toolchains such as Langchain appears to be very simple, and that is to have the language model generate SQL queries. This looks amazing at first glance, but when you actually try it, it is simply like changing the SQL controller from wired to wireless, and the actual game image on the screen does not change at all. In other words, in contrast to vector search, which seems to return search results in a fairly natural way, relational database search seems to have been left behind by the times.&lt;/p&gt;

&lt;p&gt;However, one can expect some people to say that they are structured for rigorous searches, and that it is not wrong to say that they do not respond adequately to natural language.&lt;/p&gt;

&lt;p&gt;Is this really the case?&lt;/p&gt;

&lt;h2&gt;
  
  
  Main unstructured Document and the Time/Person associated with it
&lt;/h2&gt;

&lt;p&gt;I think the documents and messages are the ones that suffer the most from this problem. This is because documents and messages themselves have a strong unstructured aspect, but they always contain information about when they were updated and who wrote them, so both unstructured and structured perspectives are necessary. I think this is related to the fact that ChatGPT confuses old and new information in some cases.&lt;/p&gt;

&lt;p&gt;Of course, this is not so much of a problem when the document itself is likely to contain date and author information, as in the Web, but the problem is with internal documents and internal chats that are managed entirely in RDBs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proposed Solution
&lt;/h2&gt;

&lt;p&gt;I have decided to take the following tentative steps to address this document chat issue. Embed relevant information in the text to be vectorized.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Title: {{title}}
Author: {{author}}
UpdatedAt: {{updatedAt}}
Body: {{boday}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my experiments, I was able to give reasonable answers to questions such as who is knowledgeable about which information and which information is correct.&lt;/p&gt;

&lt;p&gt;This is a suggestion. I would like to hear your opinions.&lt;/p&gt;

</description>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Achieve streaming output like the ChatGPT mainframe</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Sun, 09 Apr 2023 08:15:05 +0000</pubDate>
      <link>https://dev.to/moekidev/achieve-streaming-output-like-the-chatgpt-mainframe-1lbl</link>
      <guid>https://dev.to/moekidev/achieve-streaming-output-like-the-chatgpt-mainframe-1lbl</guid>
      <description>&lt;p&gt;In this example, we use Langchain, but perhaps the original API alone can be used.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://js.langchain.com/docs/"&gt;Welcome to LangChain | 🦜️🔗 Langchain&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, the server side.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChatOpenAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/chat_models&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HumanChatMessage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/schema&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CallbackManager&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/callbacks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;openAIApiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;streaming&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;callbackManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CallbackManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromHandlers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;handleLLMNewToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;token&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HumanChatMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&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;The point is to enable streaming with &lt;code&gt;streaming: true&lt;/code&gt; and &lt;a href="https://nodejs.org/api/stream.html#writable-streams"&gt;&lt;code&gt;write()&lt;/code&gt;&lt;/a&gt;. This is called Writable streams in Node.js and is enabled for files and responses.&lt;/p&gt;

&lt;p&gt;When all the Langchain processing is done, we terminate it with &lt;code&gt;end()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next is the client side.&lt;br&gt;
&lt;/p&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;reply&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;input&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TextDecoder&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&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="s2"&gt;application/json&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="na"&gt;body&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="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;input&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;getReader&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;

  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&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;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&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;done&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;read&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;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
      &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;decoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decode&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="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;The point is &lt;a href="https://developer.mozilla.org/ja/docs/Web/API/ReadableStream/getReader"&gt;&lt;code&gt;getReader()&lt;/code&gt;&lt;/a&gt;. Also, we need to decode it, so we put that process in.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>chatgpt</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Hybrid of chat and document for your programming notes</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Sat, 08 Apr 2023 06:43:08 +0000</pubDate>
      <link>https://dev.to/moekidev/hybrid-of-chat-and-document-for-your-programming-notes-34dg</link>
      <guid>https://dev.to/moekidev/hybrid-of-chat-and-document-for-your-programming-notes-34dg</guid>
      <description>&lt;p&gt;Beta version of new documentation tool released.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ink-o.com/"&gt;https://www.ink-o.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BbAfFYjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61gpj6wq946jy8i3m9ql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BbAfFYjq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61gpj6wq946jy8i3m9ql.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have never been able to successfully use Notion or Evernote. Most of this is due to the difficulty in managing folders and files. For example, I sometimes end up at lunch time wondering if my daily notes should be separated by date or by topic. I would like to know how you all avoid these problems. It was difficult for me.&lt;/p&gt;

&lt;p&gt;On the other hand, I find that I am very good at the flow of getting my thoughts out to chat tools like Slack. It often makes my work go much more smoothly. In Japanese, there is a reporting flow to manage, called "Minutes Reporting". What I do is practically the same as this, but in my case, I do it only to completely organize my mind.&lt;/p&gt;

&lt;p&gt;However, most of the time, chat does not have the same high-level expression methods as markdown. For example, it lacks the functionality to leave code snippets or quotes.&lt;/p&gt;

&lt;p&gt;So I came up with this hybrid of chat and documentation.&lt;br&gt;
The idea came from my experience with ChatGPT, where you can use quite functional expressions while interacting with ChatGPT in a chat format. This was a great experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LdHDkqMz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vowimth6opspi6gp18qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LdHDkqMz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vowimth6opspi6gp18qk.png" alt="Image description" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also thought that with AI-based summary and search capabilities, perhaps the definition of information structures such as folders and files might be unnecessary.&lt;/p&gt;

&lt;p&gt;We have not yet implemented AI support in this release, but perhaps that could make this tool more powerful. So I would like to solicit your ideas for this tool. We welcome your ideas in the following Github Discussions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/moekidev/ink-o/discussions"&gt;https://github.com/moekidev/ink-o/discussions&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Trying Finch and introduce containerd</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Thu, 01 Dec 2022 13:35:06 +0000</pubDate>
      <link>https://dev.to/moekidev/trying-finch-and-introduce-containerd-jej</link>
      <guid>https://dev.to/moekidev/trying-finch-and-introduce-containerd-jej</guid>
      <description>&lt;p&gt;AWS announces Finch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/jp/blogs/opensource/introducing-finch-an-open-source-client-for-container-development/"&gt;Introducing Finch: An Open Source Client for Container Development | AWS Open Source Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The author uses a Mac and uses Docker Desktop or &lt;a href="https://github.com/abiosoft/colima"&gt;colima&lt;/a&gt; x Docker CLI to realize a Docker development environment. Dcoker Desktop uses an internal &lt;a href="https://github.com/moby/hyperkit"&gt; HyperKit&lt;/a&gt; (macOS hypervisor) to launch a Linux VM and run dockerd in it. Docker Desktop is based on Lima, and it generates Lima configuration files, and it is used to run Linux.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prepare Linux environment by generating Lima configuration file&lt;/li&gt;
&lt;li&gt;Install Docker on Linux on Lima environment&lt;/li&gt;
&lt;li&gt;Prepare an environment that allows transparent connection between Docker CLI on the host side (i.e., macOS side) and Docker on Linux on Lima&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker development support is provided by doing the following. At this point, I was aware of Lima's existence, but the AWS article suggests that Lima itself is quite exciting.&lt;/p&gt;

&lt;p&gt;What is the background behind Finch's announcement, i.e., the entry of Alternative Docker? To be honest, I have never actually used Kubernetes and am not familiar with it, so I recognized the story of Kunernetes quitting Docker when I started finding the following articles in the wake of this Finch.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://medium.com/nttlabs/docker-to-containerd-4f3a56e6f2b6"&gt;Migration from Docker to containerd (NTT Tech Conference 2022 Presentation Report) | by Akihiro Suda | nttlabs | Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the details, it seems that Kubernetes used to touch Docker for managing containers on distributed environments, but in recent years, they started to use &lt;a href="https://containerd.io/"&gt;containerd&lt;/a&gt; directly.&lt;/p&gt;

&lt;p&gt;! &lt;a href="https://miro.medium.com/max/1400/1*HL7tRfSRwv8fLleLRDvDXQ.webp"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://speakerdeck.com/ktock/dockerkaracontainerdhefalseyi-xing?slide=7"&gt;https://speakerdeck.com/ktock/dockerkaracontainerdhefalseyi-xing?slide=7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Direct use of containerd? containerd? turns out I didn't know anything about container technology.&lt;br&gt;
containerd was originally developed by Docker in 2015 as a daemon that provided basic container management capabilities under Docker. containerd's scope has gradually expanded and now seems to cover almost everything in the Docker Engine. For example, &lt;a href="https://github.com/containerd/nerdctl"&gt;nerdctl&lt;/a&gt; is a CLI for containerd; the UX is almost identical to the Docker CLI, and Docker Compose is also supported (&lt;code&gt;nerdctl compose&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Back to Kubernetes, according to CHANGELOG, there was a maintenance problem with Docker's Container Runtime Interface (CRI) called dockershim.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The kubelet uses a module called "dockershim" which implements CRI support for Docker and We encourage you to evaluate moving to a container runtime that is a We encourage you to evaluate moving to a container runtime that is a full-fledged implementation of CRI (v1alpha1 or v1 compliant) as they become available.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#deprecation"&gt;kubernetes/CHANGELOG-1.20.md at master - kubernetes/kubernetes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarize, containerd was born and derived from Docker and has expanded its own domain, containerd was chosen over Docker due to maintenance issues with Kubernetes, and there is now both a method and a reason to manage containerd directly. And against this backdrop, Finland's FinnServer has been gaining momentum. Before Finch, most containerd users would have used Lima directly.&lt;/p&gt;

&lt;p&gt;In addition, the Finch article also mentions &lt;a href="https://github.com/moby/buildkit"&gt;BuildKit&lt;/a&gt;, which should also be kept in mind. As before, I will focus on understanding the relationship with Docker. I remember myself, and I have seen things like &lt;code&gt;DOCKER_BUILDKIT=1 docker build . I had a chance to see something like&lt;/code&gt;DOCKER_BUILDKIT=1 docker build . This is a way to use BuildKit with Docker, which seems to have the following advantages over the Docker default build&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple stages of a build can be executed in parallel.&lt;/li&gt;
&lt;li&gt;A mechanism (RUN --mount command in the Dockerfile) can be used to prevent sensitive information from being left in the build artifact (including cache)&lt;/li&gt;
&lt;li&gt;Local files can be used for builds only&lt;/li&gt;
&lt;li&gt;Remote files can be retrieved via SSH connection at build time&lt;/li&gt;
&lt;li&gt;Build cache import/export&lt;/li&gt;
&lt;li&gt;Distributed builds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I see. The build cache and parallel execution seem powerful, and I think we can assume that these features are available by default in Finch.&lt;/p&gt;

&lt;p&gt;Now that you understand the significance of Finch, let's actually use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install finch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, I tried to set up the configuration of finch, following the README as follows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.finch/finch.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cpus: 8
memory: 8GiB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And initialize vm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;finch vm init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now vm is up and running.&lt;br&gt;
Next, we'll use Docker Compose, as well as the Docker CLI and nerdctl.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;finch compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I encountered some differences in behavior between Docker and containerd.&lt;/p&gt;

&lt;p&gt;First, the abbreviated description of port was invalid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  db:
    ports:
-     - 5432
+     - 5432:5432
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other error occurred when I tried to read a file outside of the context. This time, I had to change the location of the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  app:
     volumes:
-      - ~/.gitconfig:/root/.gitconfig
+      - ./.gitconfig:/root/.gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other than that, it was the same as with Docker.&lt;/p&gt;

&lt;p&gt;The above mentioned Finch helped me to deepen my understanding of containerd and technologies around containers. I feel that I will be able to catch the tide by gradually migrating to Finch in the future.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Technological selection is rhythm game!</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Thu, 24 Nov 2022 11:50:42 +0000</pubDate>
      <link>https://dev.to/moekidev/technological-selection-is-rhythm-game-4g49</link>
      <guid>https://dev.to/moekidev/technological-selection-is-rhythm-game-4g49</guid>
      <description>&lt;p&gt;I've been reading and learning a lot lately about technology selection from different teams.&lt;/p&gt;

&lt;p&gt;There are many differences in technology selection between teams, one of which is how advanced they are.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Progressive vs Conservative
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever we talk about technology selection, it's always a hot topic.&lt;br&gt;
Often the argument is, "It's too early to use this," or "Isn't this already out of date?" or "Isn't it too old?&lt;/p&gt;

&lt;p&gt;In reading various articles about technology selection, I have found myself thinking.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What are the criteria that make you feel you are too advanced or too conservative in selecting a certain technology?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd like to dig deeper into this question.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of technology selection do I consider too progressive?
&lt;/h2&gt;

&lt;p&gt;For example, when I feel that a certain technology adoption is too advanced, it is when&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rudimentary PR or issues are accumulating.&lt;/li&gt;
&lt;li&gt;I don't see any blogs out there that have tried it.&lt;/li&gt;
&lt;li&gt;I read the documentation and there are too many new concepts to understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these senses are relative and have to be compared with other libraries and frameworks, but I understood that rather that is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of technology selection do you feel is too conservative?
&lt;/h2&gt;

&lt;p&gt;On the other hand, I feel too conservative in the following cases&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PRs and issues are left unaddressed&lt;/li&gt;
&lt;li&gt;A completely upwardly compatible library is being promoted.&lt;/li&gt;
&lt;li&gt;The date of publication of the blog where you tried it is already long ago.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing which UI to adopt may be a similar story
&lt;/h2&gt;

&lt;p&gt;What is an easy-to-understand UI? I often ask myself, "What's the most common UI? This is because users do not use only our products. They use various applications in their daily lives and learn how to use computers on a daily basis.&lt;/p&gt;

&lt;p&gt;In that context, &lt;strong&gt;old UI&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Black phone crux.&lt;/li&gt;
&lt;li&gt;Floppy disk save symbols (do they still exist?)&lt;/li&gt;
&lt;li&gt;scuumorphism (is this still around?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and &lt;strong&gt;unseen UI&lt;/strong&gt; will confuse users.&lt;br&gt;
As well as avoiding these, we felt that we needed to &lt;strong&gt;follow other product and industry trends&lt;/strong&gt; in technology selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rhythm of Technology
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Get into the rhythm of technology. Don't be too late or too early.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's because technology is social.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How do you get into the rhythm of technology?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dive into the actual library and language community

&lt;ul&gt;
&lt;li&gt;Look in the repositories.&lt;/li&gt;
&lt;li&gt;Ask lots of questions.&lt;/li&gt;
&lt;li&gt;Contribute to things you like&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Communicate with other teams

&lt;ul&gt;
&lt;li&gt;Conferences&lt;/li&gt;
&lt;li&gt;Technical blog&lt;/li&gt;
&lt;li&gt;Hear about failures&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I guess this is about right. Well, it's obvious, but you may need to pay attention to the following points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that have nothing to do with the rhythm of technology.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  My own impression
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The feeling of touching the technology by yourself may possibly not be reliable.&lt;/strong&gt;&lt;br&gt;
Even if a framework is pleasant to touch for you, it may not be so for the world, and it may pass away as it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Innovativeness of the technology
&lt;/h3&gt;

&lt;p&gt;If we can use that technology to solve all sorts of problems! but if the community is not fully developed, security risks and bugs may be addressed too late.&lt;/p&gt;

&lt;h2&gt;
  
  
  However, there are cases where too advanced or too conservative a choice is a good one.
&lt;/h2&gt;

&lt;p&gt;I remember back in the day when Apple adopted flat design with iOS7 and got a lot of flak for it.&lt;br&gt;
However, as is the case with many of the policies that Apple has advocated, flat design has become an airy UI that has somehow made its way into the world.&lt;br&gt;
I think this is because Apple is a platformer. Platforms should &lt;strong&gt;work on challenging technologies that can break through the status quo and are easy to work on&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Conversely, there are times when too conservative a choice is a good one. On the other hand, there are times when being too conservative is a good choice, such as when a very high level of safety is required. For example, the cockpit of an airplane should be improved slowly and for a long time, because a new UI might cause confusion.&lt;/p&gt;

&lt;p&gt;I think this is also true for technology selection. There are cases where exceptional choices should be made if safety is required or if it is a platformer of some kind.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Technology selection should be done according to the rhythm of the world.&lt;/li&gt;
&lt;li&gt;Actually, the same can be said for UI.&lt;/li&gt;
&lt;li&gt;There are cases where exceptional choices should be made.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Small effects of A/B testing on small websites</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Tue, 15 Nov 2022 22:43:42 +0000</pubDate>
      <link>https://dev.to/moekidev/small-effects-of-ab-testing-on-small-websites-28l5</link>
      <guid>https://dev.to/moekidev/small-effects-of-ab-testing-on-small-websites-28l5</guid>
      <description>&lt;p&gt;I have done A/B testing in my work. My impression after doing it is that A/B testing is very delicate and intricate, so it is very difficult to handle. I think there is a high possibility of failure. In this article, I would like to discuss why A/B testing is so difficult.&lt;/p&gt;

&lt;p&gt;A/B testing is a method of testing two sites by delivering a pattern of appearance and functionality to a specified percentage of users, to see which pattern is more likely to achieve a given goal. The goals are, for example, page transitions, button clicks, conversions, etc. This is expected to be set appropriately depending on where the A/B test is conducted.&lt;/p&gt;

&lt;p&gt;It is important to note that A/B testing can only tell us what is likely, it does not mean that the results will always be better when we actually release the product.&lt;/p&gt;

&lt;p&gt;Now that I have given you an overview, I will talk about why this A/B testing is so difficult. First of all, let's talk about goal setting. For example, let's say you want to test a link that takes you to a form, and you set the number of times the link is pressed as the target value. At this point, it is important to note that even if the link is pressed more often in Pattern B, it does not necessarily mean that the number of completed conversions will be higher. In A/B testing, the business-critical metrics that you do not want to lower by making changes, such as the number of completed conversions, are called &lt;strong&gt;guardrail metrics&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A possible reason for the actual release of a pattern that performed well in A/B testing but did not affect conversions or had a negative impact is that this guardrail metric is being ignored.&lt;/p&gt;

&lt;p&gt;Of course, it is best to set the final goal, the conversion completion rate, as the target for A/B testing, but there may be cases where the population of conversions is too small to test because the differences in goals are not significantly comparable. This is where guardrail metrics come into play, which is ultimately the same as setting the conversion completion rate as the A/B test goal. In other words, A/B testing will not work if the number of inflows and conversions are considerably low.&lt;/p&gt;

&lt;p&gt;I believe this phenomenon often occurs with site changes themselves to begin with. For a website with a clear goal, such as an landing page, you should design the story of how the user achieves the goal. This is very important from a macro perspective.&lt;/p&gt;

&lt;p&gt;If the number of inflows and conversions are low, we believe it is more effective to make changes to the story, such as fewer pages or a richer main visual, rather than small changes such as button decorations or wording.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Attaching database to static site on Next.js and Vercel</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Tue, 08 Nov 2022 03:05:12 +0000</pubDate>
      <link>https://dev.to/moekidev/sprinkling-db-to-nextjs-on-vercel-40oi</link>
      <guid>https://dev.to/moekidev/sprinkling-db-to-nextjs-on-vercel-40oi</guid>
      <description>&lt;p&gt;I recently added a like button to my website.&lt;/p&gt;

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

&lt;p&gt;In the past, if I wanted to add a little database processing to a static website, I either had to change the app implementation from a static site generator to a server-side framework like Ruby on Rails, or I had to have another DB server and hit API. Site functionality affected the entire architecture.&lt;/p&gt;

&lt;p&gt;However, this experiment made us realize that Next.js and Vercel have a very &lt;strong&gt;application-first&lt;/strong&gt; philosophy that can extend the functionality of a website without major architectural changes.&lt;br&gt;
This is largely due to the fact that Vercel is able to receive the Rest API with Serverless Function.&lt;/p&gt;

&lt;p&gt;Let's see.&lt;/p&gt;

&lt;p&gt;First, we will implement the UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MdThumbUp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-icons/md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLikeCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;liked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLiked&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;createLike&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="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;liked&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO: create like&lt;/span&gt;
      &lt;span class="nf"&gt;setLikeCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nf"&gt;setLiked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;liked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-blue-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;
          &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createLike&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"ml-4 mb-4 align-bottom cursor-pointer inline-block bg-white border-2 border-gray-800 rounded-full px-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MdThumbUp&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"inline mr-2"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"inline-block ml-4 mb-4 align-bottom"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;liked&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Thank you!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;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;Where the DB is concerned, &lt;code&gt;TODO: create like&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createLike&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="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;liked&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// TODO: create like&lt;/span&gt;
      &lt;span class="nf"&gt;setLikeCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nf"&gt;setLiked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;and &lt;code&gt;likeCount&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLikeCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will prepare PostgreSQL and Prisma, an ORM made with Node.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add prisma
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;code&gt;prisma/schema.prisma&lt;/code&gt;, schema file.&lt;br&gt;
Like model is very simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// prisma/schema.prisma

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Like {
  id    Int     @id @default(autoincrement())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we will generate and aplly migrations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn run prisma migrate dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we will generate prisma client to access database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn run prisma generate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we will implement the part that actually accesses the database.&lt;/p&gt;

&lt;p&gt;If you export a function called &lt;code&gt;getServerSideProps&lt;/code&gt; (Server-Side Rendering) from a page, Next.js will pre-render this page on each request using the data returned by &lt;code&gt;getServerSideProps&lt;/code&gt;. So, we get like count on here and set props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/index.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getServerSideProps&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;likeCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;like&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;likeCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;likeCount&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;Then the update part of like. We will create post endpoint to create a like record&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&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;like&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;like&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;like&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;and add the fetching process to callback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createLike&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="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;liked&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/like/create&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nf"&gt;setLikeCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;likeCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nf"&gt;setLiked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;This concludes the implementation part.&lt;/p&gt;

&lt;p&gt;Next, let's set up Vercel to use Prisma and prepare a PostgreSQL server.&lt;/p&gt;

&lt;p&gt;I have a PostgreSQL server at render.com.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://render.com/" rel="noopener noreferrer"&gt;Cloud Application Hosting for Developers | Render&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prisma has put together a method for deploying to &lt;br&gt;
Vercel, so I will try to follow this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-vercel" rel="noopener noreferrer"&gt;How to deploy a Prisma app to Vercel&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// package.json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vercel-build&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="s2"&gt;prisma generate &amp;amp;&amp;amp; prisma migrate deploy &amp;amp;&amp;amp; next build&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we will environment variable for Prisma to Vercel.&lt;/p&gt;

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

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

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;We were able to add DB-based functionality to our site without major architectural changes. It was a very freeing development experience, and I think I understand a little bit of what Next.js and Vercel are trying to do.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Portfolio with more than just technical content, vision and values</title>
      <dc:creator>Moeki Kawakami</dc:creator>
      <pubDate>Sun, 06 Nov 2022 13:59:01 +0000</pubDate>
      <link>https://dev.to/moekidev/portfolio-with-more-than-just-technical-content-vision-and-values-1o42</link>
      <guid>https://dev.to/moekidev/portfolio-with-more-than-just-technical-content-vision-and-values-1o42</guid>
      <description>&lt;p&gt;In this post, I will discuss my policy for updating my website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://moeki.dev/"&gt;https://moeki.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was to let visitors to my website know what I have in mind when I'm developing.&lt;/p&gt;

&lt;p&gt;What I want people to see on my website are the people they may work with in the future or the people they work with in the community on a daily basis. What they really want to know is if I am someone they can be with and be inspired by.&lt;/p&gt;

&lt;p&gt;My technical interests and skills do not tell you what I am thinking. So I put my vision and values on the website.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Technology for Living Your Own Way
&lt;/h2&gt;

&lt;p&gt;I have been saved by technology. However, it has not saved my life or solved my problems. It has nurtured my creativity. Photography, music and software. Without computer technology, I would never have been able to actually put the ideas in my head into reality. It was a world where we could show our photos to many people without exhibition, and where we could make music without playing an instrument. I want to give back to computer technology.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In describe of my vision, I have included the story of how I came to it. Maybe someone who reads it will have a similar story and relate to it. Others may disagree with my view of technology. But that's okay. I wanted the website to have a role in communicating my character to visitors. I would be very happy if visitors took some kind of action (whether like or dislike). Also, knowing someone's vision allows us to discuss the vision behind a particular action instead of just criticizing it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  My Five Values
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Starting with myself to improve my team&lt;/li&gt;
&lt;li&gt;Starting with my neighbors to create a culture&lt;/li&gt;
&lt;li&gt;Making minimal product first to get feedback&lt;/li&gt;
&lt;li&gt;Looking at our daily development&lt;/li&gt;
&lt;li&gt;Solving our own problems in our own way&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;"My Five Values" proclaims to visitors the way I work. It is important to know what kind of work style the people you work with prefer, because there are a way of working that suits some people and not others. It allows you to acknowledge and accept that your team's values and your personal values may not be perfectly aligned. &lt;br&gt;
For example, when matching a team with an individual, the most important thing is to strongly identify with each other's values and to acknowledge that our values will never be in complete agreement with each other.&lt;/p&gt;

&lt;p&gt;Technical interests and skills may perhaps be important in a temporary business exchange. I am not saying they are not important at all, and I love technology. I also have a strong desire to share it. But don't limit the content of your portfolio website to just that. Find people who not only trust your skills, but who share your way of working.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
