<?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>Forem: 4484-ho</title>
    <description>The latest articles on Forem by 4484-ho (@4484ho).</description>
    <link>https://forem.com/4484ho</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%2F3680666%2F345961b3-4b30-4b20-bc87-31abdc825532.png</url>
      <title>Forem: 4484-ho</title>
      <link>https://forem.com/4484ho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/4484ho"/>
    <language>en</language>
    <item>
      <title>Bypassing the Human Brain: How I Built a Full-Stack Prototype in 60 Minutes</title>
      <dc:creator>4484-ho</dc:creator>
      <pubDate>Tue, 06 Jan 2026 11:31:38 +0000</pubDate>
      <link>https://forem.com/4484ho/bypassing-the-human-brain-how-i-built-a-full-stack-prototype-in-60-minutes-1jk4</link>
      <guid>https://forem.com/4484ho/bypassing-the-human-brain-how-i-built-a-full-stack-prototype-in-60-minutes-1jk4</guid>
      <description>&lt;p&gt;We always try our best to explain things, but we never really know if we're getting through. And customers are always worried: "Do they really understand what I need?"&lt;/p&gt;

&lt;p&gt;This is a story about fighting back against that hopeless situation.&lt;/p&gt;




&lt;p&gt;"Can you reorganize this complex business logic from scratch?"&lt;/p&gt;

&lt;p&gt;That's the request I got recently. At first, I thought about using NotebookLM to organize existing documents and create materials. But that would take time, and I wasn't sure if it would really meet the requirements.&lt;/p&gt;

&lt;p&gt;So I tried combining these three tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://claude.ai/code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://notebooklm.google/" rel="noopener noreferrer"&gt;NotebookLM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gotalab/cc-sdd" rel="noopener noreferrer"&gt;cc-sdd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My plan was to quickly build a prototype and get everyone on the same page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools I Used
&lt;/h2&gt;

&lt;h3&gt;
  
  
  NotebookLM Skill for Claude Code
&lt;/h3&gt;

&lt;p&gt;I used &lt;a href="https://github.com/PleasePrompto/notebooklm-skill" rel="noopener noreferrer"&gt;notebooklm-skill&lt;/a&gt; to enable Claude Code to directly access NotebookLM notebooks. I created a &lt;code&gt;.claude/skill&lt;/code&gt; directory in the project root and cloned the repository there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; .claude/skill
&lt;span class="nb"&gt;cd&lt;/span&gt; .claude/skill
git clone https://github.com/PleasePrompto/notebooklm-skill notebooklm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I could get answers from Claude Code based on documents I'd uploaded to NotebookLM. Honestly, I was surprised.&lt;/p&gt;

&lt;p&gt;Before this, I couldn't download materials from NotebookLM, and I thought of it as a separate tool from Agentic Coding. The workflow was: organize requirements and designs in ClaudeCode, then feed them to NotebookLM. That was my mental model.&lt;/p&gt;

&lt;p&gt;Since it operates through browser automation internally, it seemed like a simpler structure compared to MCP and similar tools.&lt;/p&gt;

&lt;p&gt;Anyway, now I could easily get the information I needed—including all the sources and notes I'd built up with customers over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  cc-sdd
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/gotalab/cc-sdd" rel="noopener noreferrer"&gt;cc-sdd&lt;/a&gt; is a tool that supports Specification-Driven Development. I used it with the standard workflow this time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Actual Process
&lt;/h2&gt;

&lt;p&gt;As a prerequisite, I'd already registered our product's requirements documents and business logic materials as sources in NotebookLM.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Organizing Specifications with NotebookLM
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;I asked NotebookLM via Claude Code to create data models needed for the business logic in markdown format&lt;/li&gt;
&lt;li&gt;I had it organize the necessary business logic, formulas, data models, and table/column elements for success patterns, then output them in markdown format&lt;/li&gt;
&lt;li&gt;Since I'd also placed existing product specifications in NotebookLM, I sent a request asking for a minimal prototype that took all of those into account, and got the results&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By this point, I had pretty well-organized specifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Deciding on the Tech Stack
&lt;/h3&gt;

&lt;p&gt;Once the specifications were organized, I decided on the tech stack first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container&lt;/strong&gt;: Build PostgreSQL with Docker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend/Backend&lt;/strong&gt;: Next.js (configured as BFF architecture)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since it's a minimal prototype, I kept it simple. With Next.js, I can handle both server-side and frontend with API Routes and Server Components, and database connections are straightforward.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Starting Specification-Driven Development with cc-sdd
&lt;/h3&gt;

&lt;p&gt;Once the tech stack was decided, I ran &lt;code&gt;cc-sdd init&lt;/code&gt; to initialize the project. Then I followed the standard workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create requirements (from here on, I had cc-sdd commands directly ask NotebookLM questions while creating requirements)&lt;/li&gt;
&lt;li&gt;Create Steering (with the decided tech stack specified)&lt;/li&gt;
&lt;li&gt;Specify design&lt;/li&gt;
&lt;li&gt;Present tasks&lt;/li&gt;
&lt;li&gt;Implement the application&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;cc-sdd proceeds with implementation based on the specifications.&lt;/p&gt;

&lt;p&gt;I think the key point is telling it to query NotebookLM, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/kiro/spec-requirements &amp;lt;spec-name&amp;gt;
I want to create requirements for a minimal setup that can test business logic for customer demos
Please use the Skill to ask NotebookLM questions
Also incorporate the data model and business logic materials I have locally

ultrathink
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I told ClaudeCode to build PostgreSQL with Docker containers and implement it as a BFF architecture with Next.js in the Steering. I also had it create table definitions based on the data models I'd obtained earlier.&lt;/p&gt;

&lt;p&gt;It's smarter and faster than I am.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All of this took one hour.&lt;/strong&gt; Honestly, I was surprised myself. Normally, just organizing requirements would take several hours, and building a prototype would take a full day.&lt;/p&gt;

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

&lt;p&gt;This combination is really useful. Especially the flow of organizing specifications with NotebookLM and then implementing with cc-sdd—it was super helpful for clarifying requirements and maintaining consistency in implementation. I also didn't have to deal with ClaudeCode asking me a bunch of questions. There's something to be said for being clear and fast without going through a human brain.&lt;/p&gt;

&lt;p&gt;By the way, the app details are secret, so I won't go into them here (lol). But this tool combination itself is pretty versatile, so I hope you'll give it a try.&lt;/p&gt;

&lt;p&gt;And here I am, writing this post after finishing the work so quickly. Don't tell anyone, but it took me the same amount of time to write this post as it did to build the prototype.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>Deploy Next.js to GCP for FREE: Serverless Setup with SQLite</title>
      <dc:creator>4484-ho</dc:creator>
      <pubDate>Mon, 05 Jan 2026 03:55:01 +0000</pubDate>
      <link>https://forem.com/4484ho/deploy-nextjs-to-gcp-for-free-serverless-setup-with-sqlite-2lf8</link>
      <guid>https://forem.com/4484ho/deploy-nextjs-to-gcp-for-free-serverless-setup-with-sqlite-2lf8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When deploying personal projects or small-scale applications to GCP (Google Cloud Platform), you want to keep costs low while avoiding complex configurations. This article introduces a simple and practical GCP deployment setup that runs for &lt;strong&gt;$0-5/month (effectively $0 when using the free tier)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article explains how to achieve a cost-effective, maintenance-free setup using the &lt;strong&gt;Next.js BFF pattern&lt;/strong&gt; combined with &lt;strong&gt;SQLite + Cloud Storage&lt;/strong&gt;. Throughout this guide, we'll use a &lt;strong&gt;vocabulary learning web application&lt;/strong&gt; as a practical example to demonstrate the concepts and implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of This Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Single Container Architecture&lt;/strong&gt;: Frontend and backend run in one container&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;SQLite Database&lt;/strong&gt;: No additional DB server required, reducing costs&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No Maintenance Required&lt;/strong&gt;: Serverless operation with Cloud Run&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Auto-scaling&lt;/strong&gt;: Automatically scales based on traffic (can scale down to 0)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;TypeScript Throughout&lt;/strong&gt;: Type safety between frontend and backend&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Generous Free Tier&lt;/strong&gt;: Free up to 2 million requests per month&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────┐
│   Cloud Run Service                 │
│                                     │
│   ┌─────────────────────────────┐  │
│   │  Next.js Container (BFF)    │  │
│   │  - Frontend (React)         │  │
│   │  - API Routes (Backend)     │  │
│   └─────────────────────────────┘  │
│            │                        │
│            ▼                        │
│   ┌─────────────────────────────┐  │
│   │  Cloud Storage              │  │
│   │  └─ vocabulary.db (SQLite)   │  │
│   │     (Download on startup /   │  │
│   │      Upload on shutdown)     │  │
│   └─────────────────────────────┘  │
└─────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What is the BFF (Backend for Frontend) Pattern?
&lt;/h3&gt;

&lt;p&gt;This pattern leverages Next.js's &lt;strong&gt;App Router&lt;/strong&gt; to integrate the frontend and API routes within the same application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple deployment with everything in one container&lt;/li&gt;
&lt;li&gt;Type safety between frontend and backend (unified TypeScript)&lt;/li&gt;
&lt;li&gt;No need for additional API gateways or load balancers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Structure Example&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;/app
  ├── page.tsx          # Home page
  ├── register/page.tsx # Registration page
  ├── exercise/page.tsx # Exercise page
  └── api/
      ├── cards/route.ts    # Card CRUD API
      └── reviews/route.ts  # Learning history API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Technology Stack Selection Rationale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Next.js (App Router)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why Next.js&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can integrate frontend and API (BFF pattern)&lt;/li&gt;
&lt;li&gt;Supports Server-Side Rendering (SSR) and Static Site Generation (SSG)&lt;/li&gt;
&lt;li&gt;Can leverage TypeScript's type safety&lt;/li&gt;
&lt;li&gt;Rich ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SQLite
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why SQLite&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Additional DB Server&lt;/strong&gt;: No need for managed DB services like Cloud SQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-based&lt;/strong&gt;: Easy to set up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Reduction&lt;/strong&gt;: No DB server fees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified with Local Development&lt;/strong&gt;: Can use the same DB in both development and production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constraints on concurrent writes from multiple instances&lt;/li&gt;
&lt;li&gt;Not suitable for large-scale data or multi-user scenarios&lt;/li&gt;
&lt;li&gt;Consider migrating to PostgreSQL (Cloud SQL) in such cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloud Run
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why Cloud Run&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serverless&lt;/strong&gt;: No server management required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-scaling&lt;/strong&gt;: Automatically scales based on traffic (can scale down to 0)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request-based Billing&lt;/strong&gt;: No charges when there are no requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generous Free Tier&lt;/strong&gt;: Free up to 2 million requests per month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Integration&lt;/strong&gt;: Can automate deployment with Cloud Build or GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GCP Deployment Configuration Comparison
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Recommended: Cloud Run + Cloud Storage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Run service (container-based, serverless)&lt;/li&gt;
&lt;li&gt;Store SQLite database file in Cloud Storage&lt;/li&gt;
&lt;li&gt;Download from Cloud Storage on startup, upload on shutdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost Estimate&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud Run: $0 within free tier, approximately $0.40 per million requests when exceeded&lt;/li&gt;
&lt;li&gt;Cloud Storage: Approximately $0.020/GB/month (storage)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: Effectively $0/month within free tier, approximately $0-5/month when exceeded&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No maintenance required&lt;/li&gt;
&lt;li&gt;Request-based billing (no charges when there are no requests)&lt;/li&gt;
&lt;li&gt;Auto-scaling support (can scale down to 0)&lt;/li&gt;
&lt;li&gt;Generous free tier&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alternative 1: Compute Engine e2-micro (Free Tier)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compute Engine e2-micro (using free tier)&lt;/li&gt;
&lt;li&gt;Run container with Docker&lt;/li&gt;
&lt;li&gt;Persist SQLite data with persistent disk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost Estimate&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Using Free Tier: Effectively $0/month&lt;/strong&gt; (up to 750 hours per month)&lt;/li&gt;
&lt;li&gt;After free tier expires: Approximately $6-7/month&lt;/li&gt;
&lt;li&gt;Persistent Disk: Approximately $0.04/GB/month&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lowest cost (when using free tier)&lt;/li&gt;
&lt;li&gt;Full control possible&lt;/li&gt;
&lt;li&gt;Can run continuously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintenance required (OS patches, etc.)&lt;/li&gt;
&lt;li&gt;Scaling is manual configuration&lt;/li&gt;
&lt;li&gt;Free tier is up to 750 hours per month (about one month of continuous operation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alternative 2: Cloud Run + Cloud SQL
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cost Estimate&lt;/strong&gt;: Approximately $10-15/month (minimum configuration)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-user support&lt;/li&gt;
&lt;li&gt;Data sharing possible between multiple instances&lt;/li&gt;
&lt;li&gt;Automatic backups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher cost&lt;/li&gt;
&lt;li&gt;Overkill for small projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alternative 3: Cloud Run + Cloud Filestore
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cost Estimate&lt;/strong&gt;: Approximately $20-30/month (minimum configuration)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NFS-compatible file system&lt;/li&gt;
&lt;li&gt;Data sharing possible between multiple instances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher cost&lt;/li&gt;
&lt;li&gt;Cannot mount directly from Cloud Run (requires Compute Engine)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Points for SQLite + Cloud Storage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data Persistence Mechanism
&lt;/h3&gt;

&lt;p&gt;Since Cloud Run is stateless, it cannot directly save SQLite files. Therefore, we adopt a method of storing SQLite files in &lt;strong&gt;Cloud Storage&lt;/strong&gt;, downloading them on startup and uploading them on shutdown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cloud Run Container (on startup)
  └─ Download SQLite file from Cloud Storage
  └─ Save to /tmp/vocabulary.db
  └─ Run application

Cloud Run Container (on shutdown)
  └─ Upload /tmp/vocabulary.db to Cloud Storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementation Points
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Cloud Storage Configuration
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Bucket Creation&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a Cloud Storage bucket in the GCP console&lt;/li&gt;
&lt;li&gt;Select a region (recommended: same region as Cloud Run)&lt;/li&gt;
&lt;li&gt;Configure access control (grant read/write permissions to Cloud Run service account)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  2. Database Connection Implementation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/db/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Database&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;better-sqlite3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;Storage&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;@google-cloud/storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&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;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&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;Storage&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;bucketName&lt;/span&gt; &lt;span class="o"&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;GCS_BUCKET_NAME&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vocabulary-app-db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbFileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vocabulary.db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localDbPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/tmp/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dbFileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;gcsDbPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`data/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dbFileName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Download SQLite file from Cloud Storage&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;downloadDatabase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketName&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;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gcsDbPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Check if file exists&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;exists&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&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;exists&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;localDbPath&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Database downloaded from Cloud Storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Create empty database on first startup&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Creating new database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error downloading database:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Create empty database on error&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Upload SQLite file to Cloud Storage&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;uploadDatabase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketName&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;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gcsDbPath&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localDbPath&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localDbPath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/x-sqlite3&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Database uploaded to Cloud Storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error uploading database:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Download database on application startup&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;downloadDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Database connection&lt;/span&gt;
&lt;span class="k"&gt;export&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="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localDbPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Upload database on process termination&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;uploadDatabase&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="nf"&gt;exit&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="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="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGINT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;uploadDatabase&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="nf"&gt;exit&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Periodic backup (optional)&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;uploadDatabase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Every 5 minutes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Local Development Environment
&lt;/h4&gt;

&lt;p&gt;For local development, use the local file system instead of Cloud Storage:&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="c1"&gt;// lib/db/index.ts (for local development)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isProduction&lt;/span&gt; &lt;span class="o"&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;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isProduction&lt;/span&gt; 
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`/tmp/vocabulary.db`&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/vocabulary.db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&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="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Environment Variable Configuration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env.local (local development)&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./data/vocabulary.db

&lt;span class="c"&gt;# Cloud Run environment variables&lt;/span&gt;
&lt;span class="nv"&gt;GCS_BUCKET_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vocabulary-app-db
&lt;span class="nv"&gt;GOOGLE_APPLICATION_CREDENTIALS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/service-account.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Important Considerations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Concurrent Writes with Multiple Instances&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQLite has constraints on concurrent writes from multiple processes&lt;/li&gt;
&lt;li&gt;Cloud Run may start multiple instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solutions&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;Set Cloud Run's maximum instances to 1&lt;/li&gt;
&lt;li&gt;Or migrate to Cloud SQL (PostgreSQL)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Increased Startup Time&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloading from Cloud Storage takes time (several seconds)&lt;/li&gt;
&lt;li&gt;May increase response time for the first request&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Loss Risk&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the process terminates abnormally, the latest data may not be uploaded&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Implement periodic backups (e.g., every 5 minutes)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQLite is optimal for small-scale data&lt;/li&gt;
&lt;li&gt;Consider migrating to PostgreSQL for large-scale data or high traffic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Cost Calculation (Specific Examples)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario 1: Within Free Tier (Personal Development / Small Projects)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;: Cloud Run + Cloud Storage&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Run (up to 2 million requests)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Storage (1GB)&lt;/td&gt;
&lt;td&gt;$0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Approximately $0.02/month (effectively $0)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Scenario 2: Exceeding Free Tier (Medium Traffic)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;: Cloud Run + Cloud Storage&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Run (5 million requests)&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud Storage (5GB)&lt;/td&gt;
&lt;td&gt;$0.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Approximately $1.30/month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Scenario 3: Using Compute Engine Free Tier
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;: Compute Engine e2-micro (Free Tier) + Persistent Disk&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compute Engine e2-micro (Free Tier)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistent Disk (20GB)&lt;/td&gt;
&lt;td&gt;$0.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Approximately $0.80/month (approximately $6.80/month after free tier expires)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Implementation Flow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Project Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create Next.js project&lt;/span&gt;
npx create-next-app@latest vocabulary-app &lt;span class="nt"&gt;--typescript&lt;/span&gt;

&lt;span class="c"&gt;# Install required packages&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;better-sqlite3 drizzle-orm @google-cloud/storage
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; drizzle-kit @types/better-sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Database Schema Definition
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/db/schema.ts&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;sqliteTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;integer&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;drizzle-orm/sqlite-core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sqliteTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cards&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;created_at&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;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;notNull&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reviewHistory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sqliteTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;review_history&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;cardId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cards&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;span class="na"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;answer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// 'ok' or 'ng'&lt;/span&gt;
  &lt;span class="na"&gt;answeredAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;answered_at&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;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;nextReviewAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next_review_at&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;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;notNull&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;h3&gt;
  
  
  3. API Routes Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/cards/route.ts&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;NextRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;db&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;@/lib/db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;cards&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;@/lib/db/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;z&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;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCardSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&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="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="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;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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;body&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;request&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createCardSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;card&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="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cards&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;returning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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;card&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to create card&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;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&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;h3&gt;
  
  
  4. Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:20-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;deps&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.json* ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci

&lt;span class="c"&gt;# Build&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=deps /app/node_modules ./node_modules&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="c"&gt;# Production&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;runner&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_ENV=production&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/public ./public&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/.next/standalone ./&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/.next/static ./.next/static&lt;/span&gt;

&lt;span class="c"&gt;# Create temporary directory (for SQLite file)&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /tmp

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT=8080&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Cloud Run Deployment
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;cloudbuild.yaml&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/cloud-builders/docker'&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;build'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-t'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/$PROJECT_ID/vocabulary-app'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/cloud-builders/docker'&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;push'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/$PROJECT_ID/vocabulary-app'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/cloud-builders/gcloud'&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;run'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploy'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vocabulary-app'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--image'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/$PROJECT_ID/vocabulary-app'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--region'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asia-northeast1'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--platform'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;managed'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--allow-unauthenticated'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--set-env-vars'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GCS_BUCKET_NAME=vocabulary-app-db'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--max-instances'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deployment Command&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Deploy with Cloud Build&lt;/span&gt;
gcloud builds submit &lt;span class="nt"&gt;--config&lt;/span&gt; cloudbuild.yaml

&lt;span class="c"&gt;# Or deploy directly&lt;/span&gt;
gcloud run deploy vocabulary-app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--source&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; asia-northeast1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--platform&lt;/span&gt; managed &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--allow-unauthenticated&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set-env-vars&lt;/span&gt; &lt;span class="nv"&gt;GCS_BUCKET_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vocabulary-app-db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--max-instances&lt;/span&gt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Q: Is SQLite okay?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;: It's sufficient for small projects or personal development. Consider migrating to PostgreSQL (Cloud SQL) in the following cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-user support is required&lt;/li&gt;
&lt;li&gt;Large-scale data (several GB or more)&lt;/li&gt;
&lt;li&gt;High traffic (100+ requests per second)&lt;/li&gt;
&lt;li&gt;Complex queries or transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Q: What about data consistency with multiple instances?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;: Cloud Run may start multiple instances. Since SQLite has constraints on concurrent writes from multiple processes, we recommend the following measures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set maximum instances to 1&lt;/strong&gt;: &lt;code&gt;--max-instances 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migrate to Cloud SQL&lt;/strong&gt;: When multi-user support is needed&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Q: Will startup time be slower?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;: Downloading from Cloud Storage takes several seconds. The response time for the first request may increase, but it's usually within acceptable limits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Q: What about backups?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;: The following methods are available:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Periodic uploads&lt;/strong&gt;: Upload to Cloud Storage every 5 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Storage versioning&lt;/strong&gt;: Enable file version management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migrate to Cloud SQL&lt;/strong&gt;: Use automatic backup features&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Q: What about security?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;: We recommend the following measures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Properly configure Cloud Storage bucket access control&lt;/li&gt;
&lt;li&gt;Grant minimum permissions to Cloud Run service account&lt;/li&gt;
&lt;li&gt;HTTPS required (Cloud Run handles this automatically)&lt;/li&gt;
&lt;li&gt;Manage secrets with environment variables (Secret Manager)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The benefits of this configuration:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Cost Efficiency&lt;/strong&gt;: Effectively $0 within free tier, approximately $0-5/month when exceeded&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Simple&lt;/strong&gt;: Single container architecture, no maintenance required&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Scalable&lt;/strong&gt;: Auto-scaling based on traffic (can scale down to 0)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Type Safe&lt;/strong&gt;: Improved development efficiency with unified TypeScript&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Practical&lt;/strong&gt;: Suitable for personal development to small projects&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Projects Suitable for This Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal development / Portfolio&lt;/li&gt;
&lt;li&gt;Small-scale web applications&lt;/li&gt;
&lt;li&gt;Prototype / MVP development&lt;/li&gt;
&lt;li&gt;Learning projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Future Extensions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-user support → Migrate to PostgreSQL (Cloud SQL)&lt;/li&gt;
&lt;li&gt;High traffic → Adjust Cloud Run scaling settings&lt;/li&gt;
&lt;li&gt;Global expansion → Cloud CDN + Multiple regions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even beginners can achieve ultra-low-cost GCP deployment with this configuration. Especially when leveraging Cloud Run's generous free tier, you can operate for effectively $0. Give it a try!&lt;/p&gt;




&lt;h2&gt;
  
  
  Reference Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/run/docs" rel="noopener noreferrer"&gt;Cloud Run Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/storage/docs" rel="noopener noreferrer"&gt;Cloud Storage Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app" rel="noopener noreferrer"&gt;Next.js App Router Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://orm.drizzle.team/" rel="noopener noreferrer"&gt;Drizzle ORM Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/free" rel="noopener noreferrer"&gt;GCP Free Tier&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloud</category>
      <category>nextjs</category>
      <category>serverless</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Demystifying ReAct: Why Reasoning and Acting is the Standard for LLM Agents</title>
      <dc:creator>4484-ho</dc:creator>
      <pubDate>Sat, 03 Jan 2026 12:19:24 +0000</pubDate>
      <link>https://forem.com/4484ho/demystifying-react-why-reasoning-and-acting-is-the-standard-for-llm-agents-1ii6</link>
      <guid>https://forem.com/4484ho/demystifying-react-why-reasoning-and-acting-is-the-standard-for-llm-agents-1ii6</guid>
      <description>&lt;p&gt;The ReAct (Reasoning and Acting) framework has become the de facto standard for building LLM agents in recent years.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ReAct: Synergizing Reasoning and Acting in Language Models&lt;/p&gt;

&lt;p&gt;Shunyu Yao, Jeffrey Zhao, Dian Yu, Nan Du, Izhak Shafran, Karthik Narasimhan, Yuan Cao&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since the paper was published in 2022, it has been abstracted by libraries like LangChain and is increasingly used as a black box.&lt;/p&gt;

&lt;p&gt;This is a summary I put together as part of my LangChain studies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rough Summary of the Paper
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Abstract
&lt;/h3&gt;

&lt;p&gt;Proposes the synergy between reasoning and acting. Summarizes how the ReAct framework, which defines LLMs generating thought traces and task-specific actions alternately, achieved suppression of reasoning errors and reduction of hallucinations through interaction with external environments (such as Wikipedia).&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Introduction
&lt;/h3&gt;

&lt;p&gt;Identifies the separation of "Reasoning" (CoT, etc.) and "Acting" (WebShop, etc.) in existing language models as problematic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deficiencies in Reasoning

&lt;ul&gt;
&lt;li&gt;Factual errors due to lack of external knowledge, and static reasoning processes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Deficiencies in Acting

&lt;ul&gt;
&lt;li&gt;Wandering due to lack of abstract goals&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By integrating these, the paper describes the motivation for introducing a loop that resembles human cognitive processes:&lt;br&gt;
"Formulating action plans through reasoning"&lt;br&gt;
and&lt;br&gt;
"Correcting reasoning based on action results"&lt;/p&gt;
&lt;h3&gt;
  
  
  2. ReAct: Synergizing Reasoning and Acting in Language Models
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Environment definition

&lt;ul&gt;
&lt;li&gt;A Markov Decision Process (MDP)-like environment consisting of state &lt;code&gt;s in S&lt;/code&gt;, action &lt;code&gt;a in A&lt;/code&gt;, and observation &lt;code&gt;o in O&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Input sequence (Trajectory) construction&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defines context &lt;code&gt;c(t)&lt;/code&gt; at time &lt;code&gt;t&lt;/code&gt; as:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c(t) = (x, r(1), a(1), o(1), ..., r(t-1), a(t-1), o(t-1))
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Output structure&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models a probability distribution &lt;code&gt;p(r(t), a(t) | c(t))&lt;/code&gt; that takes &lt;code&gt;c(t)&lt;/code&gt; as input and generates thought &lt;code&gt;r(t)&lt;/code&gt; or action &lt;code&gt;a(t)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3. Knowledge-Intensive Reasoning Tasks (HotpotQA, FEVER)
&lt;/h3&gt;

&lt;p&gt;Evaluation experiments on knowledge-intensive tasks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method

&lt;ul&gt;
&lt;li&gt;Uses Wikipedia API as the external environment and defines three actions: Search, Lookup, Finish&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Results

&lt;ul&gt;
&lt;li&gt;Compared to CoT alone (reasoning only), accuracy of factual information improved. Compared to Action alone, confirmed more efficient information exploration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Analysis

&lt;ul&gt;
&lt;li&gt;Qualitatively evaluated that ReAct has the ability to self-correct hallucinations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. Decision Making Tasks (ALFWorld, WebShop)
&lt;/h3&gt;

&lt;p&gt;Evaluation experiments on decision-making and manipulation tasks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment

&lt;ul&gt;
&lt;li&gt;Physical room manipulation (ALFWorld) and online shopping (WebShop)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Findings

&lt;ul&gt;
&lt;li&gt;Demonstrated that by interposing language-based "Thought," tasks can be completed without losing sight of long-term goals even under sparse reward settings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  5. Related Work
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Chain-of-Thought (CoT)

&lt;ul&gt;
&lt;li&gt;Differences from prior research focused solely on reasoning&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Modular Deep RL

&lt;ul&gt;
&lt;li&gt;Advantages of flexibility through few-shot learning of LLMs over reinforcement learning approaches&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  6. Conclusion
&lt;/h3&gt;

&lt;p&gt;Concludes that ReAct is effective for both knowledge-intensive tasks and decision-making tasks. As future challenges, presents addressing context length limitations and few-shot dependency through model fine-tuning.&lt;/p&gt;
&lt;h2&gt;
  
  
  Content I Organized Out of Interest
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Problems Under Sparse Reward Settings
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Problems and Challenges
&lt;/h4&gt;

&lt;p&gt;Sparse reward setting refers to a state in reinforcement learning or decision-making tasks where an agent only receives positive rewards (feedback) at the final stage when the goal is completely achieved, and during the intermediate process, rewards remain at "0 (zero)" or a constant value.&lt;/p&gt;

&lt;p&gt;Under these conditions, the following phenomena occur, making it difficult for simple action models (acting only) to complete tasks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delayed evaluation

&lt;ul&gt;
&lt;li&gt;It's not immediately clear whether the results of actions are heading in the "right direction"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Exploration difficulty

&lt;ul&gt;
&lt;li&gt;Since no useful signals are obtained until accidentally reaching the goal, the efficiency of trial and error (exploration) becomes extremely low&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  ReAct's Solution
&lt;/h4&gt;

&lt;p&gt;Shows that it can be overcome by the LLM's "Thought" playing the following roles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Self-generation of intermediate goals&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In processes where final rewards are not obtained, the LLM generates logical intermediate steps within the context, such as "I should check XX next"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Substitution for internal reward function&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even when physical rewards are not obtained, by linguistically evaluating whether Observations align with its own Thought (plan), it forms a de facto self-feedback loop&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  What Observation Specifically Is
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;It's the "physical data processing that synchronizes and maps external outputs to working memory called context."&lt;/p&gt;

&lt;p&gt;Refers to a series of data processing steps that integrate outputs returned from the external environment into the input sequence (&lt;code&gt;c(t+1)&lt;/code&gt;) for the agent's (LLM's) next reasoning cycle.&lt;/p&gt;
&lt;h4&gt;
  
  
  In More Detail
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Data reception and serialization (Input)

&lt;ul&gt;
&lt;li&gt;After external tool execution completes, synchronously receives its return value

&lt;ul&gt;
&lt;li&gt;Data flow

&lt;ul&gt;
&lt;li&gt;Structured data (JSON, Binary, etc.) is transferred from external processes (API, DB, Interpreter, etc.) to the system side (agent control program)&lt;/li&gt;
&lt;li&gt;Memory structure

&lt;ul&gt;
&lt;li&gt;Received data is held in a temporary buffer and serialized into UTF-8 format text data that the LLM can interpret&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Context token appending (State Transition)

&lt;ul&gt;
&lt;li&gt;Physically concatenates serialized text to the end of the existing token sequence (Trajectory) held within the LLM's context window

&lt;ul&gt;
&lt;li&gt;State transition

&lt;ul&gt;
&lt;li&gt;Transition from state &lt;code&gt;S(t) = (x, r(1), a(1), o(1), ..., r(t), a(t))&lt;/code&gt; to state &lt;code&gt;S(t') = (x, r(1), a(1), o(1), ..., r(t), a(t), o(t))&lt;/code&gt;. (x: instruction, r: Thought, a: Action, o: Observation)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Formatting

&lt;ul&gt;
&lt;li&gt;A token identifier defined by the system (e.g., \nObservation: ) is added as a prefix so the LLM can recognize it as a boundary for "external input"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Context window integrity control

&lt;ul&gt;
&lt;li&gt;Logic intervenes to calculate token length after concatenation and control so it doesn't exceed the LLM's maximum context window

&lt;ul&gt;
&lt;li&gt;Internal mechanism

&lt;ul&gt;
&lt;li&gt;Token counting

&lt;ul&gt;
&lt;li&gt;Calculates the token count of the entire sequence including serialized &lt;code&gt;o(t)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Truncation/summarization (when necessary)

&lt;ul&gt;
&lt;li&gt;When exceeding the limit is anticipated, deletes or compresses part of preceding &lt;code&gt;o(1...t-1)&lt;/code&gt; or &lt;code&gt;r(1...t-1)&lt;/code&gt; to secure memory space needed for reasoning at current time &lt;code&gt;t&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Trigger to reasoning phase (Output)

&lt;ul&gt;
&lt;li&gt;Sends (requests) updated context &lt;code&gt;S(t')&lt;/code&gt; as payload to the LLM's reasoning endpoint

&lt;ul&gt;
&lt;li&gt;Data flow

&lt;ul&gt;
&lt;li&gt;The entire updated sequence is transferred from the control program to the LLM engine&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Purpose

&lt;ul&gt;
&lt;li&gt;Presents the result &lt;code&gt;o(t)&lt;/code&gt; for the immediately preceding &lt;code&gt;a(t)&lt;/code&gt; to the LLM as established fact (grounding) and induces generation of the next step &lt;code&gt;r(t+1)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  CoT vs ReAct
&lt;/h3&gt;

&lt;p&gt;Chain-of-Thought (CoT) and ReAct are different frameworks in LLM reasoning processes, and their main difference lies in "interaction with external environments (closed system or open system)."&lt;/p&gt;

&lt;p&gt;From an engineering perspective,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReAct extends CoT and
defines a control loop
to incorporate external I/O (Observation)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be interpreted this way.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chain-of-Thought (CoT)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Definition

&lt;ul&gt;
&lt;li&gt;A method where LLMs generate logical intermediate steps to reach an answer using only their own internal parameters (learned knowledge)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Data flow

&lt;ul&gt;
&lt;li&gt;A linear process that generates a thought process for input and outputs a final answer&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;System boundary

&lt;ul&gt;
&lt;li&gt;Closed system. Does not receive inputs (Observations) from external environments, and reasoning is internally self-contained within the LLM&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  ReAct
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Definition

&lt;ul&gt;
&lt;li&gt;A framework that integrates "reasoning (Thought)" like CoT with "action (Action)" that operates external tools and its result "observation (Observation)"&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Data flow

&lt;ul&gt;
&lt;li&gt;A dynamic process that repeats the Thought → Action → Observation cycle&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;System boundary

&lt;ul&gt;
&lt;li&gt;Open system. Incorporates dynamic feedback from external environments into context and modifies next-step reasoning based on it&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  ReAct Flow Summary Based on the Above
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Initial State (t=0)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Input

&lt;ul&gt;
&lt;li&gt;User command (Query: &lt;code&gt;x&lt;/code&gt;) and few-shot prompt (&lt;code&gt;p&lt;/code&gt;) that defines ReAct's operating rules.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;State (c(0))&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c(0) = (p, x)
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Memory structure&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A static instruction set is placed at the beginning of the LLM's context window&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Reasoning Cycle (t=n)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step A: Thought Generation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Process

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;p(r(t) | c(t-1))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Processing

&lt;ul&gt;
&lt;li&gt;The LLM references current context &lt;code&gt;c(t-1)&lt;/code&gt; and verbalizes (&lt;code&gt;r(t)&lt;/code&gt;) the validity of the next action&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Internal mechanism

&lt;ul&gt;
&lt;li&gt;Does not interfere with external environments and formulates intermediate goals in the LLM's internal logical space&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step B: Action Generation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Process

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;p(a(t) | c(t-1), r(t))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Processing

&lt;ul&gt;
&lt;li&gt;The LLM outputs an identifier and arguments (&lt;code&gt;a(t)&lt;/code&gt;) to invoke external tools according to a specific format (e.g., &lt;code&gt;search[query]&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;System output

&lt;ul&gt;
&lt;li&gt;Generated &lt;code&gt;a(t)&lt;/code&gt; is sent from the LLM engine to the agent control program&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step C: Execution
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Processing

&lt;ul&gt;
&lt;li&gt;The control program parses &lt;code&gt;a(t)&lt;/code&gt; and drives the corresponding external tool (API, DB, etc.).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Note

&lt;ul&gt;
&lt;li&gt;This phase occurs outside the LLM, and LLM reasoning is in a suspended state&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step D: Observation Integration
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Input

&lt;ul&gt;
&lt;li&gt;Return value (Raw Data) from external tools.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Processing

&lt;ul&gt;
&lt;li&gt;The system converts data to text, adds an identifier, and makes it &lt;code&gt;o(t)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;State transition&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;c(t) = (c(t-1), r(t), a(t), o(t))
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Memory update&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concatenates &lt;code&gt;o(t)&lt;/code&gt; to the end of the context and determines the next request payload to the LLM&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Termination Judgment and Final Output
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Condition

&lt;ul&gt;
&lt;li&gt;When the LLM recognizes "task completion" during reasoning, it outputs a specific action (e.g., &lt;code&gt;Finish[answer]&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Output

&lt;ul&gt;
&lt;li&gt;Returns the final answer (&lt;code&gt;y&lt;/code&gt;) to the user and terminates the process&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Properties in the Sequence
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Synchrony

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;r(t+1)&lt;/code&gt; is not generated until &lt;code&gt;o(t)&lt;/code&gt; is concatenated to the context.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Accumulation

&lt;ul&gt;
&lt;li&gt;Since all &lt;code&gt;r&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;o&lt;/code&gt; from each cycle accumulate in the context, computational cost (token count) increases proportionally with the number of steps.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Recursive correction

&lt;ul&gt;
&lt;li&gt;When the content of &lt;code&gt;o(t)&lt;/code&gt; diverges from predictions in &lt;code&gt;r(t)&lt;/code&gt;, plan reconstruction (Dynamic Replanning) occurs in &lt;code&gt;r(t+1)&lt;/code&gt; of the next cycle&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
    <item>
      <title>Deploy calculation game app</title>
      <dc:creator>4484-ho</dc:creator>
      <pubDate>Sat, 27 Dec 2025 01:48:15 +0000</pubDate>
      <link>https://forem.com/4484ho/deploy-calculation-game-app-1had</link>
      <guid>https://forem.com/4484ho/deploy-calculation-game-app-1had</guid>
      <description>&lt;p&gt;I deployed my calculation game app to Vercel—specifically designed for Japanese kids who aren't fond of math! (Haha!) &lt;a href="https://flush-calc.vercel.app/" rel="noopener noreferrer"&gt;https://flush-calc.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's incredible that it took only 1 minute to deploy after setting up my Vercel account. This is a great example of how modern DX (Developer Experience) accelerates shipping products.&lt;/p&gt;

&lt;p&gt;This is currently an MVP (Minimum Viable Product) version. I'm gathering feedback from my daughter and her friends before expanding the features and refining the UX.&lt;/p&gt;

&lt;p&gt;🛠️ Development &amp;amp; Methodology&lt;br&gt;
I treated this project not just as a hobby, but as a mini-product to test my current workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Methodology: Used BMAD-Method for requirement definition, PRD creation, and implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Editor: Cursor (The AI-powered coding experience is a game-changer).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E2E Testing: Antigravity to ensure reliable user flows.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m excited to continue exploring the modern tech stack and sharing my journey!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
