From 9e497c5fcac42654a8e522ab6825926fec6120de Mon Sep 17 00:00:00 2001
From: Rikuoh <mail@riq0h.jp>
Date: Thu, 20 Feb 2025 22:46:52 +0900
Subject: [PATCH] 0.0.1

---
 .dockerignore                                 |  37 ++
 .erb_lint.yml                                 |   0
 .gitattributes                                |   9 +
 .gitignore                                    |  38 ++
 .ruby-version                                 |   1 +
 Dockerfile                                    |  62 ++++
 Gemfile                                       |  76 ++++
 Gemfile.lock                                  | 328 ++++++++++++++++++
 Procfile.dev                                  |   2 +
 README.md                                     |   1 +
 Rakefile                                      |   6 +
 app/assets/builds/.keep                       |   0
 app/assets/config/manifest.js                 |   5 +
 app/assets/images/.keep                       |   0
 app/assets/stylesheets/application.css        |  15 +
 .../stylesheets/application.tailwind.css      |  16 +
 app/assets/tailwind/application.css           |   1 +
 app/channels/application_cable/channel.rb     |   4 +
 app/channels/application_cable/connection.rb  |   4 +
 app/controllers/application_controller.rb     |   4 +
 app/controllers/concerns/.keep                |   0
 app/controllers/memos_controller.rb           |  61 ++++
 app/helpers/application_helper.rb             |   3 +
 app/helpers/memos_helper.rb                   |   2 +
 app/javascript/application.js                 |   7 +
 app/javascript/controllers/application.js     |   9 +
 .../controllers/hello_controller.js           |   7 +
 app/javascript/controllers/index.js           |   3 +
 .../controllers/memo_card_controller.js       |  15 +
 .../controllers/memo_form_controller.js       |  11 +
 .../controllers/search_controller.js          |  10 +
 app/jobs/application_job.rb                   |   7 +
 app/mailers/application_mailer.rb             |   4 +
 app/models/application_record.rb              |   3 +
 app/models/concerns/.keep                     |   0
 app/models/memo.rb                            |  11 +
 app/views/layouts/application.html.erb        |  18 +
 app/views/layouts/mailer.html.erb             |  13 +
 app/views/layouts/mailer.text.erb             |   1 +
 app/views/memos/_empty_results.html.erb       |  11 +
 app/views/memos/_form.html.erb                |  31 ++
 app/views/memos/_memo.html.erb                |  36 ++
 app/views/memos/create.turbo_stream.erb       |   1 +
 app/views/memos/destroy.turbo_stream.erb      |   1 +
 app/views/memos/edit.html.erb                 |   4 +
 app/views/memos/index.html.erb                |  39 +++
 app/views/memos/index.turbo_stream.erb        |  11 +
 app/views/memos/new.html.erb                  |   4 +
 app/views/memos/update.turbo_stream.erb       |   1 +
 bin/bundle                                    | 109 ++++++
 bin/dev                                       |  16 +
 bin/docker-entrypoint                         |   8 +
 bin/importmap                                 |   4 +
 bin/jobs                                      |   6 +
 bin/rails                                     |   4 +
 bin/rake                                      |   4 +
 bin/setup                                     |  33 ++
 config.ru                                     |   6 +
 config/application.rb                         |  30 ++
 config/boot.rb                                |   4 +
 config/cable.yml                              |  10 +
 config/cache.yml                              |  16 +
 config/credentials.yml.enc                    |   1 +
 config/database.yml                           |  34 ++
 config/environment.rb                         |   5 +
 config/environments/development.rb            |  79 +++++
 config/environments/production.rb             |  98 ++++++
 config/environments/test.rb                   |  64 ++++
 config/importmap.rb                           |   7 +
 config/initializers/assets.rb                 |  12 +
 .../initializers/content_security_policy.rb   |  11 +
 .../initializers/filter_parameter_logging.rb  |   8 +
 config/initializers/inflections.rb            |  16 +
 config/initializers/pagy.rb                   |   1 +
 config/initializers/permissions_policy.rb     |  13 +
 config/locales/en.yml                         |  31 ++
 config/puma.rb                                |  44 +++
 config/queue.yml                              |  18 +
 config/recurring.yml                          |  10 +
 config/routes.rb                              |  15 +
 config/storage.yml                            |  34 ++
 config/tailwind.config.js                     |  23 ++
 db/cache_schema.rb                            |  24 ++
 db/migrate/20250219123840_create_memos.rb     |   8 +
 db/queue_schema.rb                            | 141 ++++++++
 db/schema.rb                                  |  19 +
 db/seeds.rb                                   |   9 +
 lib/assets/.keep                              |   0
 lib/tasks/.keep                               |   0
 log/.keep                                     |   0
 public/404.html                               |  67 ++++
 public/422.html                               |  67 ++++
 public/500.html                               |  66 ++++
 public/apple-touch-icon-precomposed.png       |   0
 public/apple-touch-icon.png                   |   0
 public/favicon.ico                            |   0
 public/robots.txt                             |   1 +
 recovered.sql                                 |  35 ++
 repaired.sql                                  |  30 ++
 storage/.keep                                 |   0
 test/application_system_test_case.rb          |   5 +
 .../application_cable/connection_test.rb      |  13 +
 test/controllers/.keep                        |   0
 test/controllers/memos_controller_test.rb     |  23 ++
 test/fixtures/files/.keep                     |   0
 test/fixtures/memos.yml                       |   7 +
 test/helpers/.keep                            |   0
 test/integration/.keep                        |   0
 test/mailers/.keep                            |   0
 test/models/.keep                             |   0
 test/models/memo_test.rb                      |   7 +
 test/system/.keep                             |   0
 test/test_helper.rb                           |  15 +
 tmp/.keep                                     |   0
 tmp/pids/.keep                                |   0
 tmp/storage/.keep                             |   0
 vendor/.keep                                  |   0
 vendor/javascript/.keep                       |   0
 118 files changed, 2244 insertions(+)
 create mode 100644 .dockerignore
 create mode 100644 .erb_lint.yml
 create mode 100644 .gitattributes
 create mode 100644 .gitignore
 create mode 100644 .ruby-version
 create mode 100644 Dockerfile
 create mode 100644 Gemfile
 create mode 100644 Gemfile.lock
 create mode 100644 Procfile.dev
 create mode 100644 README.md
 create mode 100644 Rakefile
 create mode 100644 app/assets/builds/.keep
 create mode 100644 app/assets/config/manifest.js
 create mode 100644 app/assets/images/.keep
 create mode 100644 app/assets/stylesheets/application.css
 create mode 100644 app/assets/stylesheets/application.tailwind.css
 create mode 100644 app/assets/tailwind/application.css
 create mode 100644 app/channels/application_cable/channel.rb
 create mode 100644 app/channels/application_cable/connection.rb
 create mode 100644 app/controllers/application_controller.rb
 create mode 100644 app/controllers/concerns/.keep
 create mode 100644 app/controllers/memos_controller.rb
 create mode 100644 app/helpers/application_helper.rb
 create mode 100644 app/helpers/memos_helper.rb
 create mode 100644 app/javascript/application.js
 create mode 100644 app/javascript/controllers/application.js
 create mode 100644 app/javascript/controllers/hello_controller.js
 create mode 100644 app/javascript/controllers/index.js
 create mode 100644 app/javascript/controllers/memo_card_controller.js
 create mode 100644 app/javascript/controllers/memo_form_controller.js
 create mode 100644 app/javascript/controllers/search_controller.js
 create mode 100644 app/jobs/application_job.rb
 create mode 100644 app/mailers/application_mailer.rb
 create mode 100644 app/models/application_record.rb
 create mode 100644 app/models/concerns/.keep
 create mode 100644 app/models/memo.rb
 create mode 100644 app/views/layouts/application.html.erb
 create mode 100644 app/views/layouts/mailer.html.erb
 create mode 100644 app/views/layouts/mailer.text.erb
 create mode 100644 app/views/memos/_empty_results.html.erb
 create mode 100644 app/views/memos/_form.html.erb
 create mode 100644 app/views/memos/_memo.html.erb
 create mode 100644 app/views/memos/create.turbo_stream.erb
 create mode 100644 app/views/memos/destroy.turbo_stream.erb
 create mode 100644 app/views/memos/edit.html.erb
 create mode 100644 app/views/memos/index.html.erb
 create mode 100644 app/views/memos/index.turbo_stream.erb
 create mode 100644 app/views/memos/new.html.erb
 create mode 100644 app/views/memos/update.turbo_stream.erb
 create mode 100755 bin/bundle
 create mode 100755 bin/dev
 create mode 100755 bin/docker-entrypoint
 create mode 100755 bin/importmap
 create mode 100755 bin/jobs
 create mode 100755 bin/rails
 create mode 100755 bin/rake
 create mode 100755 bin/setup
 create mode 100644 config.ru
 create mode 100644 config/application.rb
 create mode 100644 config/boot.rb
 create mode 100644 config/cable.yml
 create mode 100644 config/cache.yml
 create mode 100644 config/credentials.yml.enc
 create mode 100644 config/database.yml
 create mode 100644 config/environment.rb
 create mode 100644 config/environments/development.rb
 create mode 100644 config/environments/production.rb
 create mode 100644 config/environments/test.rb
 create mode 100644 config/importmap.rb
 create mode 100644 config/initializers/assets.rb
 create mode 100644 config/initializers/content_security_policy.rb
 create mode 100644 config/initializers/filter_parameter_logging.rb
 create mode 100644 config/initializers/inflections.rb
 create mode 100644 config/initializers/pagy.rb
 create mode 100644 config/initializers/permissions_policy.rb
 create mode 100644 config/locales/en.yml
 create mode 100644 config/puma.rb
 create mode 100644 config/queue.yml
 create mode 100644 config/recurring.yml
 create mode 100644 config/routes.rb
 create mode 100644 config/storage.yml
 create mode 100644 config/tailwind.config.js
 create mode 100644 db/cache_schema.rb
 create mode 100644 db/migrate/20250219123840_create_memos.rb
 create mode 100644 db/queue_schema.rb
 create mode 100644 db/schema.rb
 create mode 100644 db/seeds.rb
 create mode 100644 lib/assets/.keep
 create mode 100644 lib/tasks/.keep
 create mode 100644 log/.keep
 create mode 100644 public/404.html
 create mode 100644 public/422.html
 create mode 100644 public/500.html
 create mode 100644 public/apple-touch-icon-precomposed.png
 create mode 100644 public/apple-touch-icon.png
 create mode 100644 public/favicon.ico
 create mode 100644 public/robots.txt
 create mode 100644 recovered.sql
 create mode 100644 repaired.sql
 create mode 100644 storage/.keep
 create mode 100644 test/application_system_test_case.rb
 create mode 100644 test/channels/application_cable/connection_test.rb
 create mode 100644 test/controllers/.keep
 create mode 100644 test/controllers/memos_controller_test.rb
 create mode 100644 test/fixtures/files/.keep
 create mode 100644 test/fixtures/memos.yml
 create mode 100644 test/helpers/.keep
 create mode 100644 test/integration/.keep
 create mode 100644 test/mailers/.keep
 create mode 100644 test/models/.keep
 create mode 100644 test/models/memo_test.rb
 create mode 100644 test/system/.keep
 create mode 100644 test/test_helper.rb
 create mode 100644 tmp/.keep
 create mode 100644 tmp/pids/.keep
 create mode 100644 tmp/storage/.keep
 create mode 100644 vendor/.keep
 create mode 100644 vendor/javascript/.keep

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..9612375
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,37 @@
+# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.
+
+# Ignore git directory.
+/.git/
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore all environment files (except templates).
+/.env*
+!/.env*.erb
+
+# Ignore all default key files.
+/config/master.key
+/config/credentials/*.key
+
+# Ignore all logfiles and tempfiles.
+/log/*
+/tmp/*
+!/log/.keep
+!/tmp/.keep
+
+# Ignore pidfiles, but keep the directory.
+/tmp/pids/*
+!/tmp/pids/.keep
+
+# Ignore storage (uploaded files in development and any SQLite databases).
+/storage/*
+!/storage/.keep
+/tmp/storage/*
+!/tmp/storage/.keep
+
+# Ignore assets.
+/node_modules/
+/app/assets/builds/*
+!/app/assets/builds/.keep
+/public/assets
diff --git a/.erb_lint.yml b/.erb_lint.yml
new file mode 100644
index 0000000..e69de29
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..8dc4323
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,9 @@
+# See https://git-scm.com/docs/gitattributes for more about git attribute files.
+
+# Mark the database schema as having been generated.
+db/schema.rb linguist-generated
+
+# Mark any vendored files as having been vendored.
+vendor/* linguist-vendored
+config/credentials/*.yml.enc diff=rails_credentials
+config/credentials.yml.enc diff=rails_credentials
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b66b15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+#   git config --global core.excludesfile '~/.gitignore_global'
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore all environment files (except templates).
+/.env*
+!/.env*.erb
+
+# Ignore all logfiles and tempfiles.
+/log/*
+/tmp/*
+!/log/.keep
+!/tmp/.keep
+
+# Ignore pidfiles, but keep the directory.
+/tmp/pids/*
+!/tmp/pids/
+!/tmp/pids/.keep
+
+# Ignore storage (uploaded files in development and any SQLite databases).
+/storage/*
+!/storage/.keep
+/tmp/storage/*
+!/tmp/storage/
+!/tmp/storage/.keep
+
+/public/assets
+
+# Ignore master key for decrypting credentials and more.
+/config/master.key
+
+/app/assets/builds/*
+!/app/assets/builds/.keep
diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 0000000..408069a
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+ruby-3.4.1
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..580a73e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,62 @@
+# syntax = docker/dockerfile:1
+
+# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
+ARG RUBY_VERSION=3.4.1
+FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
+
+# Rails app lives here
+WORKDIR /rails
+
+# Set production environment
+ENV RAILS_ENV="production" \
+    BUNDLE_DEPLOYMENT="1" \
+    BUNDLE_PATH="/usr/local/bundle" \
+    BUNDLE_WITHOUT="development"
+
+
+# Throw-away build stage to reduce size of final image
+FROM base as build
+
+# Install packages needed to build gems
+RUN apt-get update -qq && \
+    apt-get install --no-install-recommends -y build-essential git libvips pkg-config
+
+# Install application gems
+COPY Gemfile Gemfile.lock ./
+RUN bundle install && \
+    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
+    bundle exec bootsnap precompile --gemfile
+
+# Copy application code
+COPY . .
+
+# Precompile bootsnap code for faster boot times
+RUN bundle exec bootsnap precompile app/ lib/
+
+# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
+RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
+
+
+# Final stage for app image
+FROM base
+
+# Install packages needed for deployment
+RUN apt-get update -qq && \
+    apt-get install --no-install-recommends -y curl libsqlite3-0 libvips && \
+    rm -rf /var/lib/apt/lists /var/cache/apt/archives
+
+# Copy built artifacts: gems, application
+COPY --from=build /usr/local/bundle /usr/local/bundle
+COPY --from=build /rails /rails
+
+# Run and own only the runtime files as a non-root user for security
+RUN useradd rails --create-home --shell /bin/bash && \
+    chown -R rails:rails db log storage tmp
+USER rails:rails
+
+# Entrypoint prepares the database.
+ENTRYPOINT ["/rails/bin/docker-entrypoint"]
+
+# Start the server by default, this can be overwritten at runtime
+EXPOSE 3000
+CMD ["./bin/rails", "server"]
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..73825c6
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,76 @@
+source 'https://rubygems.org'
+
+ruby '3.4.1'
+
+# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
+gem 'rails', '8.0.1'
+
+gem 'rails-i18n'
+
+# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
+gem 'sprockets-rails'
+
+# Use sqlite3 as the database for Active Record
+gem 'sqlite3', '>= 1.4'
+
+gem 'solid_cache'
+gem 'solid_queue'
+
+# Use the Puma web server [https://github.com/puma/puma]
+gem 'puma', '>= 5.0'
+
+# Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails]
+gem 'importmap-rails'
+
+# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
+gem 'turbo-rails'
+
+# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
+gem 'stimulus-rails'
+
+# Build JSON APIs with ease [https://github.com/rails/jbuilder]
+gem 'jbuilder'
+
+# Use Redis adapter to run Action Cable in production
+# gem "redis", ">= 4.0.1"
+
+# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
+# gem "kredis"
+
+# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
+# gem "bcrypt", "~> 3.1.7"
+
+# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
+gem 'tzinfo-data', platforms: %i[windows jruby]
+
+# Reduces boot times through caching; required in config/boot.rb
+gem 'bootsnap', require: false
+
+# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
+# gem "image_processing", "~> 1.2"
+
+group :development, :test do
+  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
+  gem 'debug', platforms: %i[mri windows]
+end
+
+group :development do
+  # Use console on exceptions pages [https://github.com/rails/web-console]
+  gem 'web-console'
+
+  # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
+  # gem "rack-mini-profiler"
+
+  # Speed up commands on slow machines / big apps [https://github.com/rails/spring]
+  # gem "spring"
+end
+
+group :test do
+  # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
+  gem 'capybara'
+  gem 'selenium-webdriver'
+end
+
+gem 'tailwindcss-rails', '~> 4.0'
+
+gem 'pagy'
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..32901a0
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,328 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    actioncable (8.0.1)
+      actionpack (= 8.0.1)
+      activesupport (= 8.0.1)
+      nio4r (~> 2.0)
+      websocket-driver (>= 0.6.1)
+      zeitwerk (~> 2.6)
+    actionmailbox (8.0.1)
+      actionpack (= 8.0.1)
+      activejob (= 8.0.1)
+      activerecord (= 8.0.1)
+      activestorage (= 8.0.1)
+      activesupport (= 8.0.1)
+      mail (>= 2.8.0)
+    actionmailer (8.0.1)
+      actionpack (= 8.0.1)
+      actionview (= 8.0.1)
+      activejob (= 8.0.1)
+      activesupport (= 8.0.1)
+      mail (>= 2.8.0)
+      rails-dom-testing (~> 2.2)
+    actionpack (8.0.1)
+      actionview (= 8.0.1)
+      activesupport (= 8.0.1)
+      nokogiri (>= 1.8.5)
+      rack (>= 2.2.4)
+      rack-session (>= 1.0.1)
+      rack-test (>= 0.6.3)
+      rails-dom-testing (~> 2.2)
+      rails-html-sanitizer (~> 1.6)
+      useragent (~> 0.16)
+    actiontext (8.0.1)
+      actionpack (= 8.0.1)
+      activerecord (= 8.0.1)
+      activestorage (= 8.0.1)
+      activesupport (= 8.0.1)
+      globalid (>= 0.6.0)
+      nokogiri (>= 1.8.5)
+    actionview (8.0.1)
+      activesupport (= 8.0.1)
+      builder (~> 3.1)
+      erubi (~> 1.11)
+      rails-dom-testing (~> 2.2)
+      rails-html-sanitizer (~> 1.6)
+    activejob (8.0.1)
+      activesupport (= 8.0.1)
+      globalid (>= 0.3.6)
+    activemodel (8.0.1)
+      activesupport (= 8.0.1)
+    activerecord (8.0.1)
+      activemodel (= 8.0.1)
+      activesupport (= 8.0.1)
+      timeout (>= 0.4.0)
+    activestorage (8.0.1)
+      actionpack (= 8.0.1)
+      activejob (= 8.0.1)
+      activerecord (= 8.0.1)
+      activesupport (= 8.0.1)
+      marcel (~> 1.0)
+    activesupport (8.0.1)
+      base64
+      benchmark (>= 0.3)
+      bigdecimal
+      concurrent-ruby (~> 1.0, >= 1.3.1)
+      connection_pool (>= 2.2.5)
+      drb
+      i18n (>= 1.6, < 2)
+      logger (>= 1.4.2)
+      minitest (>= 5.1)
+      securerandom (>= 0.3)
+      tzinfo (~> 2.0, >= 2.0.5)
+      uri (>= 0.13.1)
+    addressable (2.8.7)
+      public_suffix (>= 2.0.2, < 7.0)
+    base64 (0.2.0)
+    benchmark (0.4.0)
+    bigdecimal (3.1.9)
+    bindex (0.8.1)
+    bootsnap (1.18.4)
+      msgpack (~> 1.2)
+    builder (3.3.0)
+    capybara (3.40.0)
+      addressable
+      matrix
+      mini_mime (>= 0.1.3)
+      nokogiri (~> 1.11)
+      rack (>= 1.6.0)
+      rack-test (>= 0.6.3)
+      regexp_parser (>= 1.5, < 3.0)
+      xpath (~> 3.2)
+    concurrent-ruby (1.3.5)
+    connection_pool (2.5.0)
+    crass (1.0.6)
+    date (3.4.1)
+    debug (1.10.0)
+      irb (~> 1.10)
+      reline (>= 0.3.8)
+    drb (2.2.1)
+    erubi (1.13.1)
+    et-orbi (1.2.11)
+      tzinfo
+    fugit (1.11.1)
+      et-orbi (~> 1, >= 1.2.11)
+      raabro (~> 1.4)
+    globalid (1.2.1)
+      activesupport (>= 6.1)
+    i18n (1.14.7)
+      concurrent-ruby (~> 1.0)
+    importmap-rails (2.1.0)
+      actionpack (>= 6.0.0)
+      activesupport (>= 6.0.0)
+      railties (>= 6.0.0)
+    io-console (0.8.0)
+    irb (1.15.1)
+      pp (>= 0.6.0)
+      rdoc (>= 4.0.0)
+      reline (>= 0.4.2)
+    jbuilder (2.13.0)
+      actionview (>= 5.0.0)
+      activesupport (>= 5.0.0)
+    logger (1.6.6)
+    loofah (2.24.0)
+      crass (~> 1.0.2)
+      nokogiri (>= 1.12.0)
+    mail (2.8.1)
+      mini_mime (>= 0.1.1)
+      net-imap
+      net-pop
+      net-smtp
+    marcel (1.0.4)
+    matrix (0.4.2)
+    mini_mime (1.1.5)
+    minitest (5.25.4)
+    msgpack (1.8.0)
+    net-imap (0.5.6)
+      date
+      net-protocol
+    net-pop (0.1.2)
+      net-protocol
+    net-protocol (0.2.2)
+      timeout
+    net-smtp (0.5.1)
+      net-protocol
+    nio4r (2.7.4)
+    nokogiri (1.18.3-aarch64-linux-gnu)
+      racc (~> 1.4)
+    nokogiri (1.18.3-aarch64-linux-musl)
+      racc (~> 1.4)
+    nokogiri (1.18.3-arm-linux-gnu)
+      racc (~> 1.4)
+    nokogiri (1.18.3-arm-linux-musl)
+      racc (~> 1.4)
+    nokogiri (1.18.3-arm64-darwin)
+      racc (~> 1.4)
+    nokogiri (1.18.3-x86_64-darwin)
+      racc (~> 1.4)
+    nokogiri (1.18.3-x86_64-linux-gnu)
+      racc (~> 1.4)
+    nokogiri (1.18.3-x86_64-linux-musl)
+      racc (~> 1.4)
+    pagy (9.3.3)
+    pp (0.6.2)
+      prettyprint
+    prettyprint (0.2.0)
+    psych (5.2.3)
+      date
+      stringio
+    public_suffix (6.0.1)
+    puma (6.6.0)
+      nio4r (~> 2.0)
+    raabro (1.4.0)
+    racc (1.8.1)
+    rack (3.1.10)
+    rack-session (2.1.0)
+      base64 (>= 0.1.0)
+      rack (>= 3.0.0)
+    rack-test (2.2.0)
+      rack (>= 1.3)
+    rackup (2.2.1)
+      rack (>= 3)
+    rails (8.0.1)
+      actioncable (= 8.0.1)
+      actionmailbox (= 8.0.1)
+      actionmailer (= 8.0.1)
+      actionpack (= 8.0.1)
+      actiontext (= 8.0.1)
+      actionview (= 8.0.1)
+      activejob (= 8.0.1)
+      activemodel (= 8.0.1)
+      activerecord (= 8.0.1)
+      activestorage (= 8.0.1)
+      activesupport (= 8.0.1)
+      bundler (>= 1.15.0)
+      railties (= 8.0.1)
+    rails-dom-testing (2.2.0)
+      activesupport (>= 5.0.0)
+      minitest
+      nokogiri (>= 1.6)
+    rails-html-sanitizer (1.6.2)
+      loofah (~> 2.21)
+      nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
+    rails-i18n (8.0.1)
+      i18n (>= 0.7, < 2)
+      railties (>= 8.0.0, < 9)
+    railties (8.0.1)
+      actionpack (= 8.0.1)
+      activesupport (= 8.0.1)
+      irb (~> 1.13)
+      rackup (>= 1.0.0)
+      rake (>= 12.2)
+      thor (~> 1.0, >= 1.2.2)
+      zeitwerk (~> 2.6)
+    rake (13.2.1)
+    rdoc (6.12.0)
+      psych (>= 4.0.0)
+    regexp_parser (2.10.0)
+    reline (0.6.0)
+      io-console (~> 0.5)
+    rexml (3.4.1)
+    rubyzip (2.4.1)
+    securerandom (0.4.1)
+    selenium-webdriver (4.28.0)
+      base64 (~> 0.2)
+      logger (~> 1.4)
+      rexml (~> 3.2, >= 3.2.5)
+      rubyzip (>= 1.2.2, < 3.0)
+      websocket (~> 1.0)
+    solid_cache (1.0.7)
+      activejob (>= 7.2)
+      activerecord (>= 7.2)
+      railties (>= 7.2)
+    solid_queue (1.1.3)
+      activejob (>= 7.1)
+      activerecord (>= 7.1)
+      concurrent-ruby (>= 1.3.1)
+      fugit (~> 1.11.0)
+      railties (>= 7.1)
+      thor (~> 1.3.1)
+    sprockets (4.2.1)
+      concurrent-ruby (~> 1.0)
+      rack (>= 2.2.4, < 4)
+    sprockets-rails (3.5.2)
+      actionpack (>= 6.1)
+      activesupport (>= 6.1)
+      sprockets (>= 3.0.0)
+    sqlite3 (2.5.0-aarch64-linux-gnu)
+    sqlite3 (2.5.0-aarch64-linux-musl)
+    sqlite3 (2.5.0-arm-linux-gnu)
+    sqlite3 (2.5.0-arm-linux-musl)
+    sqlite3 (2.5.0-arm64-darwin)
+    sqlite3 (2.5.0-x86_64-darwin)
+    sqlite3 (2.5.0-x86_64-linux-gnu)
+    sqlite3 (2.5.0-x86_64-linux-musl)
+    stimulus-rails (1.3.4)
+      railties (>= 6.0.0)
+    stringio (3.1.3)
+    tailwindcss-rails (4.0.0)
+      railties (>= 7.0.0)
+      tailwindcss-ruby (~> 4.0)
+    tailwindcss-ruby (4.0.6)
+    tailwindcss-ruby (4.0.6-aarch64-linux-gnu)
+    tailwindcss-ruby (4.0.6-aarch64-linux-musl)
+    tailwindcss-ruby (4.0.6-arm64-darwin)
+    tailwindcss-ruby (4.0.6-x86_64-darwin)
+    tailwindcss-ruby (4.0.6-x86_64-linux-gnu)
+    tailwindcss-ruby (4.0.6-x86_64-linux-musl)
+    thor (1.3.2)
+    timeout (0.4.3)
+    turbo-rails (2.0.11)
+      actionpack (>= 6.0.0)
+      railties (>= 6.0.0)
+    tzinfo (2.0.6)
+      concurrent-ruby (~> 1.0)
+    uri (1.0.2)
+    useragent (0.16.11)
+    web-console (4.2.1)
+      actionview (>= 6.0.0)
+      activemodel (>= 6.0.0)
+      bindex (>= 0.4.0)
+      railties (>= 6.0.0)
+    websocket (1.2.11)
+    websocket-driver (0.7.7)
+      base64
+      websocket-extensions (>= 0.1.0)
+    websocket-extensions (0.1.5)
+    xpath (3.2.0)
+      nokogiri (~> 1.8)
+    zeitwerk (2.7.2)
+
+PLATFORMS
+  aarch64-linux-gnu
+  aarch64-linux-musl
+  arm-linux-gnu
+  arm-linux-musl
+  arm64-darwin
+  x86_64-darwin
+  x86_64-linux
+  x86_64-linux-gnu
+  x86_64-linux-musl
+
+DEPENDENCIES
+  bootsnap
+  capybara
+  debug
+  importmap-rails
+  jbuilder
+  pagy
+  puma (>= 5.0)
+  rails (= 8.0.1)
+  rails-i18n
+  selenium-webdriver
+  solid_cache
+  solid_queue
+  sprockets-rails
+  sqlite3 (>= 1.4)
+  stimulus-rails
+  tailwindcss-rails (~> 4.0)
+  turbo-rails
+  tzinfo-data
+  web-console
+
+RUBY VERSION
+   ruby 3.4.1p0
+
+BUNDLED WITH
+   2.6.2
diff --git a/Procfile.dev b/Procfile.dev
new file mode 100644
index 0000000..da151fe
--- /dev/null
+++ b/Procfile.dev
@@ -0,0 +1,2 @@
+web: bin/rails server
+css: bin/rails tailwindcss:watch
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..faf005d
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+simple memo application composed of Rails 8, SQLite, and Hotwire Turbo. for technical verification purposes.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..9a5ea73
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require_relative "config/application"
+
+Rails.application.load_tasks
diff --git a/app/assets/builds/.keep b/app/assets/builds/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
new file mode 100644
index 0000000..b06fc42
--- /dev/null
+++ b/app/assets/config/manifest.js
@@ -0,0 +1,5 @@
+//= link_tree ../images
+//= link_directory ../stylesheets .css
+//= link_tree ../../javascript .js
+//= link_tree ../../../vendor/javascript .js
+//= link_tree ../builds
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
new file mode 100644
index 0000000..288b9ab
--- /dev/null
+++ b/app/assets/stylesheets/application.css
@@ -0,0 +1,15 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
+ * vendor/assets/stylesheets directory can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS
+ * files in this directory. Styles in this file should be added after the last require_* statement.
+ * It is generally better to create a new file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ */
diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css
new file mode 100644
index 0000000..25bc20d
--- /dev/null
+++ b/app/assets/stylesheets/application.tailwind.css
@@ -0,0 +1,16 @@
+@layer components {
+  .fade-in {
+    @apply opacity-0 animate-[fadeIn_0.5s_ease-out_forwards];
+  }
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+    transform: translateY(10px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
diff --git a/app/assets/tailwind/application.css b/app/assets/tailwind/application.css
new file mode 100644
index 0000000..f1d8c73
--- /dev/null
+++ b/app/assets/tailwind/application.css
@@ -0,0 +1 @@
+@import "tailwindcss";
diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb
new file mode 100644
index 0000000..d672697
--- /dev/null
+++ b/app/channels/application_cable/channel.rb
@@ -0,0 +1,4 @@
+module ApplicationCable
+  class Channel < ActionCable::Channel::Base
+  end
+end
diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb
new file mode 100644
index 0000000..0ff5442
--- /dev/null
+++ b/app/channels/application_cable/connection.rb
@@ -0,0 +1,4 @@
+module ApplicationCable
+  class Connection < ActionCable::Connection::Base
+  end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 0000000..c2a36d8
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,4 @@
+class ApplicationController < ActionController::Base
+  protect_from_forgery with: :exception
+  include Pagy::Backend
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/controllers/memos_controller.rb b/app/controllers/memos_controller.rb
new file mode 100644
index 0000000..4825eb8
--- /dev/null
+++ b/app/controllers/memos_controller.rb
@@ -0,0 +1,61 @@
+class MemosController < ApplicationController
+  before_action :set_memo, only: %i[edit update destroy]
+
+  def index
+    @pagy, @memos = pagy_countless(Memo.search(params[:query]), items: 12)
+
+    respond_to do |format|
+      format.html
+      format.turbo_stream
+    end
+  end
+
+  def new
+    @memo = Memo.new
+  end
+
+  def edit; end
+
+  def create
+    @memo = Memo.new(memo_params)
+    respond_to do |format|
+      if @memo.save
+        format.html { redirect_to memos_path, status: :see_other }
+        format.turbo_stream
+      else
+        format.html { render :new, status: :unprocessable_entity }
+        format.turbo_stream { render :new, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  def update
+    respond_to do |format|
+      if @memo.update(memo_params)
+        format.html { redirect_to memos_path, status: :see_other }
+        format.turbo_stream { render turbo_stream: turbo_stream.replace(@memo) }
+      else
+        format.html { render :edit, status: :unprocessable_entity }
+        format.turbo_stream { render :edit, status: :unprocessable_entity }
+      end
+    end
+  end
+
+  def destroy
+    @memo.destroy
+    respond_to do |format|
+      format.html { redirect_to memos_path, status: :see_other }
+      format.turbo_stream
+    end
+  end
+
+  private
+
+  def set_memo
+    @memo = Memo.find(params[:id])
+  end
+
+  def memo_params
+    params.require(:memo).permit(:content)
+  end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000..ed6a048
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,3 @@
+module ApplicationHelper
+  include Pagy::Frontend
+end
diff --git a/app/helpers/memos_helper.rb b/app/helpers/memos_helper.rb
new file mode 100644
index 0000000..0e732a1
--- /dev/null
+++ b/app/helpers/memos_helper.rb
@@ -0,0 +1,2 @@
+module MemosHelper
+end
diff --git a/app/javascript/application.js b/app/javascript/application.js
new file mode 100644
index 0000000..b525ba3
--- /dev/null
+++ b/app/javascript/application.js
@@ -0,0 +1,7 @@
+import { Turbo } from "@hotwired/turbo-rails";
+import "controllers";
+
+Turbo.StreamActions.redirect = function () {
+  const url = this.getAttribute("url") || "/";
+  Turbo.visit(url, { frame: "_top", action: "advance" });
+};
diff --git a/app/javascript/controllers/application.js b/app/javascript/controllers/application.js
new file mode 100644
index 0000000..1213e85
--- /dev/null
+++ b/app/javascript/controllers/application.js
@@ -0,0 +1,9 @@
+import { Application } from "@hotwired/stimulus"
+
+const application = Application.start()
+
+// Configure Stimulus development experience
+application.debug = false
+window.Stimulus   = application
+
+export { application }
diff --git a/app/javascript/controllers/hello_controller.js b/app/javascript/controllers/hello_controller.js
new file mode 100644
index 0000000..5975c07
--- /dev/null
+++ b/app/javascript/controllers/hello_controller.js
@@ -0,0 +1,7 @@
+import { Controller } from "@hotwired/stimulus"
+
+export default class extends Controller {
+  connect() {
+    this.element.textContent = "Hello World!"
+  }
+}
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
new file mode 100644
index 0000000..3c56bdf
--- /dev/null
+++ b/app/javascript/controllers/index.js
@@ -0,0 +1,3 @@
+import { application } from "./application";
+import SearchController from "./search_controller";
+application.register("search", SearchController);
diff --git a/app/javascript/controllers/memo_card_controller.js b/app/javascript/controllers/memo_card_controller.js
new file mode 100644
index 0000000..258ee22
--- /dev/null
+++ b/app/javascript/controllers/memo_card_controller.js
@@ -0,0 +1,15 @@
+import { Controller } from "@hotwired/stimulus";
+
+export default class extends Controller {
+  connect() {
+    this.element.classList.add("opacity-0");
+    this.element.classList.add("translate-y-4");
+
+    requestAnimationFrame(() => {
+      this.element.classList.remove("opacity-0");
+      this.element.classList.remove("translate-y-4");
+      this.element.classList.add("transition-all");
+      this.element.classList.add("duration-300");
+    });
+  }
+}
diff --git a/app/javascript/controllers/memo_form_controller.js b/app/javascript/controllers/memo_form_controller.js
new file mode 100644
index 0000000..f2357be
--- /dev/null
+++ b/app/javascript/controllers/memo_form_controller.js
@@ -0,0 +1,11 @@
+import { Controller } from "@hotwired/stimulus";
+
+export default class extends Controller {
+  static targets = ["textarea"];
+
+  connect() {
+    if (this.hasTextareaTarget) {
+      this.textareaTarget.focus();
+    }
+  }
+}
diff --git a/app/javascript/controllers/search_controller.js b/app/javascript/controllers/search_controller.js
new file mode 100644
index 0000000..25ca422
--- /dev/null
+++ b/app/javascript/controllers/search_controller.js
@@ -0,0 +1,10 @@
+import { Controller } from "@hotwired/stimulus";
+
+export default class extends Controller {
+  submit() {
+    clearTimeout(this.timeout);
+    this.timeout = setTimeout(() => {
+      this.element.requestSubmit();
+    }, 300);
+  }
+}
diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb
new file mode 100644
index 0000000..d394c3d
--- /dev/null
+++ b/app/jobs/application_job.rb
@@ -0,0 +1,7 @@
+class ApplicationJob < ActiveJob::Base
+  # Automatically retry jobs that encountered a deadlock
+  # retry_on ActiveRecord::Deadlocked
+
+  # Most jobs are safe to ignore if the underlying records are no longer available
+  # discard_on ActiveJob::DeserializationError
+end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644
index 0000000..3c34c81
--- /dev/null
+++ b/app/mailers/application_mailer.rb
@@ -0,0 +1,4 @@
+class ApplicationMailer < ActionMailer::Base
+  default from: "from@example.com"
+  layout "mailer"
+end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 0000000..b63caeb
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
+class ApplicationRecord < ActiveRecord::Base
+  primary_abstract_class
+end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/app/models/memo.rb b/app/models/memo.rb
new file mode 100644
index 0000000..d6125fd
--- /dev/null
+++ b/app/models/memo.rb
@@ -0,0 +1,11 @@
+class Memo < ApplicationRecord
+  validates :content, presence: true
+
+  def self.search(query)
+    if query.present?
+      where('content LIKE ?', "%#{query}%").order(created_at: :desc)
+    else
+      order(created_at: :desc)
+    end
+  end
+end
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
new file mode 100644
index 0000000..4dcb41a
--- /dev/null
+++ b/app/views/layouts/application.html.erb
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>rails8-memoapp</title>
+    <meta name="viewport" content="width=device-width,initial-scale=1">
+    <%= csrf_meta_tags %>
+    <%= csp_meta_tag %>
+    <%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
+    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
+    <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
+    <%= javascript_importmap_tags %>
+  </head>
+  <body class="bg-gray-50">
+    <div class="max-w-2xl mx-auto px-4">
+      <%= yield %>
+    </div>
+  </body>
+</html>
diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb
new file mode 100644
index 0000000..3aac900
--- /dev/null
+++ b/app/views/layouts/mailer.html.erb
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <style>
+      /* Email styles need to be inline */
+    </style>
+  </head>
+
+  <body>
+    <%= yield %>
+  </body>
+</html>
diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb
new file mode 100644
index 0000000..37f0bdd
--- /dev/null
+++ b/app/views/layouts/mailer.text.erb
@@ -0,0 +1 @@
+<%= yield %>
diff --git a/app/views/memos/_empty_results.html.erb b/app/views/memos/_empty_results.html.erb
new file mode 100644
index 0000000..2641165
--- /dev/null
+++ b/app/views/memos/_empty_results.html.erb
@@ -0,0 +1,11 @@
+<div class="flex flex-col items-center justify-center py-12">
+  <svg class="w-16 h-16 text-gray-400 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
+  </svg>
+  <h3 class="text-lg font-medium text-gray-900 mb-2">
+    <%= query.present? ? "一致なし" : "無出力" %>
+  </h3>
+  <p class="text-gray-500 text-center mb-6">
+    <%= query.present? ? "顔なし" : "無気力" %>
+  </p>
+</div>
diff --git a/app/views/memos/_form.html.erb b/app/views/memos/_form.html.erb
new file mode 100644
index 0000000..6888049
--- /dev/null
+++ b/app/views/memos/_form.html.erb
@@ -0,0 +1,31 @@
+<div class="space-y-6">
+  <%= form_with(model: memo,
+      class: "space-y-6",
+      data: { turbo_frame: "_top" }) do |f| %>
+    <% if memo.errors.any? %>
+      <div class="bg-red-50 p-4 rounded-md">
+        <div class="text-red-700">
+          <h2><%= pluralize(memo.errors.count, "error") %></h2>
+          <ul>
+            <% memo.errors.each do |error| %>
+              <li><%= error.full_message %></li>
+            <% end %>
+          </ul>
+        </div>
+      </div>
+    <% end %>
+
+    <div>
+      <%= f.text_area :content,
+          class: "w-full h-64 p-4 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
+          placeholder: "毎時毎行" %>
+  </div>
+
+  <div class="flex gap-4 items-center">
+      <%= f.submit memo.new_record? ? "出力" : "修正",
+          class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" %>
+      <%= link_to "終了", memos_path,
+          class: "bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded" %>
+    </div>
+  <% end %>
+</div>
diff --git a/app/views/memos/_memo.html.erb b/app/views/memos/_memo.html.erb
new file mode 100644
index 0000000..eb5223c
--- /dev/null
+++ b/app/views/memos/_memo.html.erb
@@ -0,0 +1,36 @@
+<%= turbo_frame_tag dom_id(memo) do %>
+  <div data-controller="memo-card"
+       class="relative bg-white p-6 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 transform hover:-translate-y-1">
+    <%= link_to edit_memo_path(memo), class: "h-full flex flex-col", data: { turbo_frame: "_top" } do %>
+      <h2 class="text-xl font-semibold text-gray-800 mb-2 line-clamp-2">
+        <%= memo.content.lines.first.try(:strip) || "無題" %>
+      </h2>
+      <p class="text-gray-600 text-sm mb-4 line-clamp-3">
+        <%= memo.content.lines[1..3].join.strip %>
+      </p>
+      <div class="mt-auto pt-4">
+        <span class="text-gray-500 text-sm">
+          <%= l memo.created_at, format: :long %>
+        </span>
+      </div>
+    <% end %>
+
+    <div class="absolute top-4 right-4">
+      <%= button_to memo_path(memo),
+          method: :delete,
+          form: { data: { turbo_frame: "_top" } },
+          class: "p-2 rounded-full hover:bg-gray-100 transition-colors" do %>
+        <svg class="w-5 h-5 text-gray-400 hover:text-red-500"
+             xmlns="http://www.w3.org/2000/svg"
+             fill="none"
+             viewBox="0 0 24 24"
+             stroke="currentColor">
+          <path stroke-linecap="round"
+                stroke-linejoin="round"
+                stroke-width="2"
+                d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
+        </svg>
+      <% end %>
+    </div>
+  </div>
+<% end %>
diff --git a/app/views/memos/create.turbo_stream.erb b/app/views/memos/create.turbo_stream.erb
new file mode 100644
index 0000000..28b6653
--- /dev/null
+++ b/app/views/memos/create.turbo_stream.erb
@@ -0,0 +1 @@
+<turbo-stream action="redirect" url="<%= memos_path %>"></turbo-stream>
diff --git a/app/views/memos/destroy.turbo_stream.erb b/app/views/memos/destroy.turbo_stream.erb
new file mode 100644
index 0000000..28b6653
--- /dev/null
+++ b/app/views/memos/destroy.turbo_stream.erb
@@ -0,0 +1 @@
+<turbo-stream action="redirect" url="<%= memos_path %>"></turbo-stream>
diff --git a/app/views/memos/edit.html.erb b/app/views/memos/edit.html.erb
new file mode 100644
index 0000000..f1695af
--- /dev/null
+++ b/app/views/memos/edit.html.erb
@@ -0,0 +1,4 @@
+<div class="max-w-2xl mx-auto">
+  <h1 class="text-2xl font-bold text-gray-900 mb-6">修正</h1>
+  <%= render 'form', memo: @memo %>
+</div>
diff --git a/app/views/memos/index.html.erb b/app/views/memos/index.html.erb
new file mode 100644
index 0000000..d5d2681
--- /dev/null
+++ b/app/views/memos/index.html.erb
@@ -0,0 +1,39 @@
+<div class="mb-8 mt-8">
+  <div class="flex items-center gap-4">
+    <%= form_with url: memos_path, method: :get,
+        data: { turbo_frame: "search-results", controller: "search" } do |f| %>
+      <div class="relative">
+        <%= f.text_field :query,
+            class: "w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
+            placeholder: "検索...",
+            data: { action: "input->search#submit" },
+            value: params[:query] %>
+      </div>
+    <% end %>
+    <%= link_to new_memo_path, class: "bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-200" do %>
+      <span class="flex items-center">
+        </svg>
+        + 出力開始
+      </span>
+    <% end %>
+  </div>
+</div>
+
+<div id="memos">
+  <%= turbo_frame_tag "memos" do %>
+    <div class="flex flex-col gap-4">
+      <%= render @memos %>
+      <%= render "empty_results", query: params[:query] if @memos.empty? %>
+
+      </div>
+  <% end %>
+</div>
+
+<div id="load-more" class="text-center mt-8">
+  <% if @pagy.next %>
+    <%= link_to "もっと見る",
+        pagy_url_for(@pagy, @pagy.next),
+        class: "inline-flex items-center px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg transition-colors duration-200",
+        data: { turbo_method: :get } %>
+  <% end %>
+</div>
diff --git a/app/views/memos/index.turbo_stream.erb b/app/views/memos/index.turbo_stream.erb
new file mode 100644
index 0000000..6d4b460
--- /dev/null
+++ b/app/views/memos/index.turbo_stream.erb
@@ -0,0 +1,11 @@
+<%= turbo_stream.append "memos" do %>
+  <%= render @memos %>
+<% end %>
+<%= turbo_stream.update "load-more" do %>
+  <% if @pagy.next %>
+    <%= link_to "もっと見る",
+        pagy_url_for(@pagy, @pagy.next),
+        class: "inline-flex items-center px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg transition-colors duration-200",
+        data: { turbo_method: :get } %>
+  <% end %>
+<% end %>
diff --git a/app/views/memos/new.html.erb b/app/views/memos/new.html.erb
new file mode 100644
index 0000000..41fd2e6
--- /dev/null
+++ b/app/views/memos/new.html.erb
@@ -0,0 +1,4 @@
+<div class="max-w-2xl mx-auto">
+  <h1 class="text-2xl font-bold text-gray-900 mb-6">出力</h1>
+  <%= render 'form', memo: @memo %>
+</div>
diff --git a/app/views/memos/update.turbo_stream.erb b/app/views/memos/update.turbo_stream.erb
new file mode 100644
index 0000000..28b6653
--- /dev/null
+++ b/app/views/memos/update.turbo_stream.erb
@@ -0,0 +1 @@
+<turbo-stream action="redirect" url="<%= memos_path %>"></turbo-stream>
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 0000000..50da5fd
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,109 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+#
+# This file was generated by Bundler.
+#
+# The application 'bundle' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require "rubygems"
+
+m = Module.new do
+  module_function
+
+  def invoked_as_script?
+    File.expand_path($0) == File.expand_path(__FILE__)
+  end
+
+  def env_var_version
+    ENV["BUNDLER_VERSION"]
+  end
+
+  def cli_arg_version
+    return unless invoked_as_script? # don't want to hijack other binstubs
+    return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
+    bundler_version = nil
+    update_index = nil
+    ARGV.each_with_index do |a, i|
+      if update_index && update_index.succ == i && a.match?(Gem::Version::ANCHORED_VERSION_PATTERN)
+        bundler_version = a
+      end
+      next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
+      bundler_version = $1
+      update_index = i
+    end
+    bundler_version
+  end
+
+  def gemfile
+    gemfile = ENV["BUNDLE_GEMFILE"]
+    return gemfile if gemfile && !gemfile.empty?
+
+    File.expand_path("../Gemfile", __dir__)
+  end
+
+  def lockfile
+    lockfile =
+      case File.basename(gemfile)
+      when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
+      else "#{gemfile}.lock"
+      end
+    File.expand_path(lockfile)
+  end
+
+  def lockfile_version
+    return unless File.file?(lockfile)
+    lockfile_contents = File.read(lockfile)
+    return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
+    Regexp.last_match(1)
+  end
+
+  def bundler_requirement
+    @bundler_requirement ||=
+      env_var_version ||
+      cli_arg_version ||
+      bundler_requirement_for(lockfile_version)
+  end
+
+  def bundler_requirement_for(version)
+    return "#{Gem::Requirement.default}.a" unless version
+
+    bundler_gem_version = Gem::Version.new(version)
+
+    bundler_gem_version.approximate_recommendation
+  end
+
+  def load_bundler!
+    ENV["BUNDLE_GEMFILE"] ||= gemfile
+
+    activate_bundler
+  end
+
+  def activate_bundler
+    gem_error = activation_error_handling do
+      gem "bundler", bundler_requirement
+    end
+    return if gem_error.nil?
+    require_error = activation_error_handling do
+      require "bundler/version"
+    end
+    return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
+    warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
+    exit 42
+  end
+
+  def activation_error_handling
+    yield
+    nil
+  rescue StandardError, LoadError => e
+    e
+  end
+end
+
+m.load_bundler!
+
+if m.invoked_as_script?
+  load Gem.bin_path("bundler", "bundle")
+end
diff --git a/bin/dev b/bin/dev
new file mode 100755
index 0000000..ad72c7d
--- /dev/null
+++ b/bin/dev
@@ -0,0 +1,16 @@
+#!/usr/bin/env sh
+
+if ! gem list foreman -i --silent; then
+  echo "Installing foreman..."
+  gem install foreman
+fi
+
+# Default to port 3000 if not specified
+export PORT="${PORT:-3000}"
+
+# Let the debug gem allow remote connections,
+# but avoid loading until `debugger` is called
+export RUBY_DEBUG_OPEN="true"
+export RUBY_DEBUG_LAZY="true"
+
+exec foreman start -f Procfile.dev "$@"
diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint
new file mode 100755
index 0000000..67ef493
--- /dev/null
+++ b/bin/docker-entrypoint
@@ -0,0 +1,8 @@
+#!/bin/bash -e
+
+# If running the rails server then create or migrate existing database
+if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then
+  ./bin/rails db:prepare
+fi
+
+exec "${@}"
diff --git a/bin/importmap b/bin/importmap
new file mode 100755
index 0000000..36502ab
--- /dev/null
+++ b/bin/importmap
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+
+require_relative "../config/application"
+require "importmap/commands"
diff --git a/bin/jobs b/bin/jobs
new file mode 100755
index 0000000..dcf59f3
--- /dev/null
+++ b/bin/jobs
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+
+require_relative "../config/environment"
+require "solid_queue/cli"
+
+SolidQueue::Cli.start(ARGV)
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 0000000..efc0377
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+APP_PATH = File.expand_path("../config/application", __dir__)
+require_relative "../config/boot"
+require "rails/commands"
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 0000000..4fbf10b
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require_relative "../config/boot"
+require "rake"
+Rake.application.run
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 0000000..3cd5a9d
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+require "fileutils"
+
+# path to your application root.
+APP_ROOT = File.expand_path("..", __dir__)
+
+def system!(*args)
+  system(*args, exception: true)
+end
+
+FileUtils.chdir APP_ROOT do
+  # This script is a way to set up or update your development environment automatically.
+  # This script is idempotent, so that you can run it at any time and get an expectable outcome.
+  # Add necessary setup steps to this file.
+
+  puts "== Installing dependencies =="
+  system! "gem install bundler --conservative"
+  system("bundle check") || system!("bundle install")
+
+  # puts "\n== Copying sample files =="
+  # unless File.exist?("config/database.yml")
+  #   FileUtils.cp "config/database.yml.sample", "config/database.yml"
+  # end
+
+  puts "\n== Preparing database =="
+  system! "bin/rails db:prepare"
+
+  puts "\n== Removing old logs and tempfiles =="
+  system! "bin/rails log:clear tmp:clear"
+
+  puts "\n== Restarting application server =="
+  system! "bin/rails restart"
+end
diff --git a/config.ru b/config.ru
new file mode 100644
index 0000000..4a3c09a
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,6 @@
+# This file is used by Rack-based servers to start the application.
+
+require_relative "config/environment"
+
+run Rails.application
+Rails.application.load_server
diff --git a/config/application.rb b/config/application.rb
new file mode 100644
index 0000000..6b07b71
--- /dev/null
+++ b/config/application.rb
@@ -0,0 +1,30 @@
+require_relative 'boot'
+
+require 'rails/all'
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(*Rails.groups)
+
+module App
+  class Application < Rails::Application
+    # Initialize configuration defaults for originally generated Rails version.
+    config.load_defaults 8.0
+
+    # Please, add to the `ignore` list any other `lib` subdirectories that do
+    # not contain `.rb` files, or that should not be reloaded or eager loaded.
+    # Common ones are `templates`, `generators`, or `middleware`, for example.
+    config.autoload_lib(ignore: %w[assets tasks])
+
+    config.time_zone = 'Tokyo'
+    config.i18n.default_locale = :ja
+
+    # Configuration for the application, engines, and railties goes here.
+    #
+    # These settings can be overridden in specific environments using the files
+    # in config/environments, which are processed later.
+    #
+    # config.time_zone = "Central Time (US & Canada)"
+    # config.eager_load_paths << Rails.root.join("extras")
+  end
+end
diff --git a/config/boot.rb b/config/boot.rb
new file mode 100644
index 0000000..988a5dd
--- /dev/null
+++ b/config/boot.rb
@@ -0,0 +1,4 @@
+ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
+
+require "bundler/setup" # Set up gems listed in the Gemfile.
+require "bootsnap/setup" # Speed up boot time by caching expensive operations.
diff --git a/config/cable.yml b/config/cable.yml
new file mode 100644
index 0000000..f39dc04
--- /dev/null
+++ b/config/cable.yml
@@ -0,0 +1,10 @@
+development:
+  adapter: async
+
+test:
+  adapter: test
+
+production:
+  adapter: redis
+  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
+  channel_prefix: app_production
diff --git a/config/cache.yml b/config/cache.yml
new file mode 100644
index 0000000..19d4908
--- /dev/null
+++ b/config/cache.yml
@@ -0,0 +1,16 @@
+default: &default
+  store_options:
+    # Cap age of oldest cache entry to fulfill retention policies
+    # max_age: <%= 60.days.to_i %>
+    max_size: <%= 256.megabytes %>
+    namespace: <%= Rails.env %>
+
+development:
+  <<: *default
+
+test:
+  <<: *default
+
+production:
+  database: cache
+  <<: *default
diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc
new file mode 100644
index 0000000..6ec9329
--- /dev/null
+++ b/config/credentials.yml.enc
@@ -0,0 +1 @@
+lVVV1a429aFGtn7Mv01xEg6aRiriT047d26RchFwpZJx64Kg8Zz5bkAXY/O3q2Yyya7YJfVQhd+iA+5u82zEsFVf/suUgd/Gxwn7gGPLKJr4rPPrBIVBOxAV4RVNctre1CwBTCba0Y6Ep9Rrm83lGmeskoLBjYy4YTZQHTpIp7v49/AC9Ann+OxabNpnac5Ut+4vKVpMX1dyaE6kIbZR4NEnNzVSqj5VcYcGpqfPdwahe+v3S+gTlgT8v+CNbhD/LLIA/7FVzhPNuESeqNLQVjsbEI1Qvfnr6gg4uP9yTXdsg1Ce/0rnF0mn46kpSq1sbP4ATUDk4vGH2UdgKh5BUsggfz25bsQJ1SkyKTXXBoauDarFKDcJHVfONGXz/4DZALBqPqCexjIqiOwcy5ZAV/RW/V/d--1JErCHw+XYs1IliM--h2ZFjml/cQLUMgibd39Djw==
\ No newline at end of file
diff --git a/config/database.yml b/config/database.yml
new file mode 100644
index 0000000..7664832
--- /dev/null
+++ b/config/database.yml
@@ -0,0 +1,34 @@
+# SQLite. Versions 3.8.0 and up are supported.
+#   gem install sqlite3
+#
+#   Ensure the SQLite 3 gem is defined in your Gemfile
+#   gem "sqlite3"
+#
+default: &default
+  adapter: sqlite3
+  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+  timeout: 5000
+
+development:
+  primary:
+    <<: *default
+    database: storage/development.sqlite3
+  queue:
+    <<: *default
+    database: storage/development_queue.sqlite3
+    migrations_paths: db/queue_migrate
+  cache:
+    <<: *default
+    database: storage/development_cache.sqlite3
+    migrations_paths: db/cache_migrate
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+  <<: *default
+  database: storage/test.sqlite3
+
+production:
+  <<: *default
+  database: storage/production.sqlite3
diff --git a/config/environment.rb b/config/environment.rb
new file mode 100644
index 0000000..cac5315
--- /dev/null
+++ b/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the Rails application.
+require_relative "application"
+
+# Initialize the Rails application.
+Rails.application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 0000000..f562f4e
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,79 @@
+require 'active_support/core_ext/integer/time'
+
+Rails.application.configure do
+  # Settings specified here will take precedence over those in config/application.rb.
+
+  # In the development environment your application's code is reloaded any time
+  # it changes. This slows down response time but is perfect for development
+  # since you don't have to restart the web server when you make code changes.
+  config.enable_reloading = true
+
+  # Do not eager load code on boot.
+  config.eager_load = false
+
+  # Show full error reports.
+  config.consider_all_requests_local = true
+
+  # Enable server timing
+  config.server_timing = true
+
+  # Enable/disable caching. By default caching is disabled.
+  # Run rails dev:cache to toggle caching.
+  if Rails.root.join('tmp/caching-dev.txt').exist?
+    config.action_controller.perform_caching = true
+    config.action_controller.enable_fragment_cache_logging = true
+
+    config.cache_store = :memory_store
+    config.public_file_server.headers = {
+      'Cache-Control' => "public, max-age=#{2.days.to_i}"
+    }
+  else
+    config.action_controller.perform_caching = false
+
+    config.cache_store = :null_store
+  end
+
+  # Store uploaded files on the local file system (see config/storage.yml for options).
+  config.active_storage.service = :local
+
+  # Don't care if the mailer can't send.
+  config.action_mailer.raise_delivery_errors = false
+
+  config.action_mailer.perform_caching = false
+
+  # Print deprecation notices to the Rails logger.
+  config.active_support.deprecation = :log
+
+  # Raise exceptions for disallowed deprecations.
+  config.active_support.disallowed_deprecation = :raise
+
+  # Tell Active Support which deprecation messages to disallow.
+  config.active_support.disallowed_deprecation_warnings = []
+
+  # Raise an error on page load if there are pending migrations.
+  config.active_record.migration_error = :page_load
+
+  # Highlight code that triggered database queries in logs.
+  config.active_record.verbose_query_logs = true
+
+  # Highlight code that enqueued background job in logs.
+  config.active_job.verbose_enqueue_logs = true
+
+  # Suppress logger output for asset requests.
+  config.assets.quiet = true
+
+  config.active_job.queue_adapter = :solid_queue
+  config.solid_queue.connects_to = { database: { writing: :queue } }
+
+  # Raises error for missing translations.
+  # config.i18n.raise_on_missing_translations = true
+
+  # Annotate rendered view with file names.
+  # config.action_view.annotate_rendered_view_with_filenames = true
+
+  # Uncomment if you wish to allow Action Cable access from any origin.
+  # config.action_cable.disable_request_forgery_protection = true
+
+  # Raise error when a before_action's only/except options reference missing actions
+  config.action_controller.raise_on_missing_callback_actions = true
+end
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 0000000..7a6377d
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,98 @@
+require "active_support/core_ext/integer/time"
+
+Rails.application.configure do
+  # Settings specified here will take precedence over those in config/application.rb.
+
+  # Code is not reloaded between requests.
+  config.enable_reloading = false
+
+  # Eager load code on boot. This eager loads most of Rails and
+  # your application in memory, allowing both threaded web servers
+  # and those relying on copy on write to perform better.
+  # Rake tasks automatically ignore this option for performance.
+  config.eager_load = true
+
+  # Full error reports are disabled and caching is turned on.
+  config.consider_all_requests_local = false
+  config.action_controller.perform_caching = true
+
+  # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment
+  # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files).
+  # config.require_master_key = true
+
+  # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
+  # config.public_file_server.enabled = false
+
+  # Compress CSS using a preprocessor.
+  # config.assets.css_compressor = :sass
+
+  # Do not fall back to assets pipeline if a precompiled asset is missed.
+  config.assets.compile = false
+
+  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+  # config.asset_host = "http://assets.example.com"
+
+  # Specifies the header that your server uses for sending files.
+  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache
+  # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX
+
+  # Store uploaded files on the local file system (see config/storage.yml for options).
+  config.active_storage.service = :local
+
+  # Mount Action Cable outside main process or domain.
+  # config.action_cable.mount_path = nil
+  # config.action_cable.url = "wss://example.com/cable"
+  # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ]
+
+  # Assume all access to the app is happening through a SSL-terminating reverse proxy.
+  # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
+  # config.assume_ssl = true
+
+  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+  config.force_ssl = true
+
+  # Log to STDOUT by default
+  config.logger = ActiveSupport::Logger.new(STDOUT)
+    .tap  { |logger| logger.formatter = ::Logger::Formatter.new }
+    .then { |logger| ActiveSupport::TaggedLogging.new(logger) }
+
+  # Prepend all log lines with the following tags.
+  config.log_tags = [ :request_id ]
+
+  # "info" includes generic and useful information about system operation, but avoids logging too much
+  # information to avoid inadvertent exposure of personally identifiable information (PII). If you
+  # want to log everything, set the level to "debug".
+  config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
+
+  # Use a different cache store in production.
+  config.cache_store = :solid_cache_store
+
+  # Use a real queuing backend for Active Job (and separate queues per environment).
+  config.active_job.queue_adapter = :solid_queue
+  config.solid_queue.connects_to = { database: { writing: :queue } }
+  # config.active_job.queue_name_prefix = "app_production"
+
+  config.action_mailer.perform_caching = false
+
+  # Ignore bad email addresses and do not raise email delivery errors.
+  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+  # config.action_mailer.raise_delivery_errors = false
+
+  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+  # the I18n.default_locale when a translation cannot be found).
+  config.i18n.fallbacks = true
+
+  # Don't log any deprecations.
+  config.active_support.report_deprecations = false
+
+  # Do not dump schema after migrations.
+  config.active_record.dump_schema_after_migration = false
+
+  # Enable DNS rebinding protection and other `Host` header attacks.
+  # config.hosts = [
+  #   "example.com",     # Allow requests from example.com
+  #   /.*\.example\.com/ # Allow requests from subdomains like `www.example.com`
+  # ]
+  # Skip DNS rebinding protection for the default health check endpoint.
+  # config.host_authorization = { exclude: ->(request) { request.path == "/up" } }
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 0000000..adbb4a6
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,64 @@
+require "active_support/core_ext/integer/time"
+
+# The test environment is used exclusively to run your application's
+# test suite. You never need to work with it otherwise. Remember that
+# your test database is "scratch space" for the test suite and is wiped
+# and recreated between test runs. Don't rely on the data there!
+
+Rails.application.configure do
+  # Settings specified here will take precedence over those in config/application.rb.
+
+  # While tests run files are not watched, reloading is not necessary.
+  config.enable_reloading = false
+
+  # Eager loading loads your entire application. When running a single test locally,
+  # this is usually not necessary, and can slow down your test suite. However, it's
+  # recommended that you enable it in continuous integration systems to ensure eager
+  # loading is working properly before deploying your code.
+  config.eager_load = ENV["CI"].present?
+
+  # Configure public file server for tests with Cache-Control for performance.
+  config.public_file_server.enabled = true
+  config.public_file_server.headers = {
+    "Cache-Control" => "public, max-age=#{1.hour.to_i}"
+  }
+
+  # Show full error reports and disable caching.
+  config.consider_all_requests_local = true
+  config.action_controller.perform_caching = false
+  config.cache_store = :null_store
+
+  # Render exception templates for rescuable exceptions and raise for other exceptions.
+  config.action_dispatch.show_exceptions = :rescuable
+
+  # Disable request forgery protection in test environment.
+  config.action_controller.allow_forgery_protection = false
+
+  # Store uploaded files on the local file system in a temporary directory.
+  config.active_storage.service = :test
+
+  config.action_mailer.perform_caching = false
+
+  # Tell Action Mailer not to deliver emails to the real world.
+  # The :test delivery method accumulates sent emails in the
+  # ActionMailer::Base.deliveries array.
+  config.action_mailer.delivery_method = :test
+
+  # Print deprecation notices to the stderr.
+  config.active_support.deprecation = :stderr
+
+  # Raise exceptions for disallowed deprecations.
+  config.active_support.disallowed_deprecation = :raise
+
+  # Tell Active Support which deprecation messages to disallow.
+  config.active_support.disallowed_deprecation_warnings = []
+
+  # Raises error for missing translations.
+  # config.i18n.raise_on_missing_translations = true
+
+  # Annotate rendered view with file names.
+  # config.action_view.annotate_rendered_view_with_filenames = true
+
+  # Raise error when a before_action's only/except options reference missing actions
+  config.action_controller.raise_on_missing_callback_actions = true
+end
diff --git a/config/importmap.rb b/config/importmap.rb
new file mode 100644
index 0000000..909dfc5
--- /dev/null
+++ b/config/importmap.rb
@@ -0,0 +1,7 @@
+# Pin npm packages by running ./bin/importmap
+
+pin "application"
+pin "@hotwired/turbo-rails", to: "turbo.min.js"
+pin "@hotwired/stimulus", to: "stimulus.min.js"
+pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
+pin_all_from "app/javascript/controllers", under: "controllers"
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
new file mode 100644
index 0000000..2eeef96
--- /dev/null
+++ b/config/initializers/assets.rb
@@ -0,0 +1,12 @@
+# Be sure to restart your server when you modify this file.
+
+# Version of your assets, change this if you want to expire all your assets.
+Rails.application.config.assets.version = "1.0"
+
+# Add additional assets to the asset load path.
+# Rails.application.config.assets.paths << Emoji.images_path
+
+# Precompile additional assets.
+# application.js, application.css, and all non-JS/CSS in the app/assets
+# folder are already added.
+# Rails.application.config.assets.precompile += %w( admin.js admin.css )
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
new file mode 100644
index 0000000..256777e
--- /dev/null
+++ b/config/initializers/content_security_policy.rb
@@ -0,0 +1,11 @@
+Rails.application.config.content_security_policy do |policy|
+  policy.default_src :self
+  policy.font_src    :self
+  policy.img_src     :self
+  policy.script_src  :self
+  policy.style_src   :self
+  policy.connect_src :self
+  policy.frame_ancestors :none
+end
+
+Rails.application.config.content_security_policy_nonce_generator = ->(_request) { SecureRandom.base64(16) }
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 0000000..c2d89e2
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
+# Use this to limit dissemination of sensitive information.
+# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
+Rails.application.config.filter_parameters += [
+  :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
+]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 0000000..3860f65
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+#   inflect.plural /^(ox)$/i, "\\1en"
+#   inflect.singular /^(ox)en/i, "\\1"
+#   inflect.irregular "person", "people"
+#   inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+#   inflect.acronym "RESTful"
+# end
diff --git a/config/initializers/pagy.rb b/config/initializers/pagy.rb
new file mode 100644
index 0000000..09f56c9
--- /dev/null
+++ b/config/initializers/pagy.rb
@@ -0,0 +1 @@
+require 'pagy/extras/countless'
diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb
new file mode 100644
index 0000000..7db3b95
--- /dev/null
+++ b/config/initializers/permissions_policy.rb
@@ -0,0 +1,13 @@
+# Be sure to restart your server when you modify this file.
+
+# Define an application-wide HTTP permissions policy. For further
+# information see: https://developers.google.com/web/updates/2018/06/feature-policy
+
+# Rails.application.config.permissions_policy do |policy|
+#   policy.camera      :none
+#   policy.gyroscope   :none
+#   policy.microphone  :none
+#   policy.usb         :none
+#   policy.fullscreen  :self
+#   policy.payment     :self, "https://secure.example.com"
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
new file mode 100644
index 0000000..6c349ae
--- /dev/null
+++ b/config/locales/en.yml
@@ -0,0 +1,31 @@
+# Files in the config/locales directory are used for internationalization and
+# are automatically loaded by Rails. If you want to use locales other than
+# English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+#     I18n.t "hello"
+#
+# In views, this is aliased to just `t`:
+#
+#     <%= t("hello") %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+#     I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# To learn more about the API, please read the Rails Internationalization guide
+# at https://guides.rubyonrails.org/i18n.html.
+#
+# Be aware that YAML interprets the following case-insensitive strings as
+# booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings
+# must be quoted to be interpreted as strings. For example:
+#
+#     en:
+#       "yes": yup
+#       enabled: "ON"
+
+en:
+  hello: "Hello world"
diff --git a/config/puma.rb b/config/puma.rb
new file mode 100644
index 0000000..7a709d7
--- /dev/null
+++ b/config/puma.rb
@@ -0,0 +1,44 @@
+# This configuration file will be evaluated by Puma. The top-level methods that
+# are invoked here are part of Puma's configuration DSL. For more information
+# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html.
+
+# Puma can serve each request in a thread from an internal thread pool.
+# The `threads` method setting takes two numbers: a minimum and maximum.
+# Any libraries that use thread pools should be configured to match
+# the maximum value specified for Puma. Default is set to 5 threads for minimum
+# and maximum; this matches the default thread size of Active Record.
+max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
+min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
+threads min_threads_count, max_threads_count
+
+rails_env = ENV.fetch("RAILS_ENV") { "development" }
+
+if rails_env == "production"
+  # If you are running more than 1 thread per process, the workers count
+  # should be equal to the number of processors (CPU cores) in production.
+  #
+  # It defaults to 1 because it's impossible to reliably detect how many
+  # CPU cores are available. Make sure to set the `WEB_CONCURRENCY` environment
+  # variable to match the number of processors.
+  worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { 1 })
+  if worker_count > 1
+    workers worker_count
+  else
+    preload_app!
+  end
+end
+# Specifies the `worker_timeout` threshold that Puma will use to wait before
+# terminating a worker in development environments.
+worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
+
+# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
+port ENV.fetch("PORT") { 3000 }
+
+# Specifies the `environment` that Puma will run in.
+environment rails_env
+
+# Specifies the `pidfile` that Puma will use.
+pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
+
+# Allow puma to be restarted by `bin/rails restart` command.
+plugin :tmp_restart
diff --git a/config/queue.yml b/config/queue.yml
new file mode 100644
index 0000000..9eace59
--- /dev/null
+++ b/config/queue.yml
@@ -0,0 +1,18 @@
+default: &default
+  dispatchers:
+    - polling_interval: 1
+      batch_size: 500
+  workers:
+    - queues: "*"
+      threads: 3
+      processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
+      polling_interval: 0.1
+
+development:
+  <<: *default
+
+test:
+  <<: *default
+
+production:
+  <<: *default
diff --git a/config/recurring.yml b/config/recurring.yml
new file mode 100644
index 0000000..d045b19
--- /dev/null
+++ b/config/recurring.yml
@@ -0,0 +1,10 @@
+# production:
+#   periodic_cleanup:
+#     class: CleanSoftDeletedRecordsJob
+#     queue: background
+#     args: [ 1000, { batch_size: 500 } ]
+#     schedule: every hour
+#   periodic_command:
+#     command: "SoftDeletedRecord.due.delete_all"
+#     priority: 2
+#     schedule: at 5am every day
diff --git a/config/routes.rb b/config/routes.rb
new file mode 100644
index 0000000..f1d5e41
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,15 @@
+Rails.application.routes.draw do
+  get 'memos/index'
+  get 'memos/new'
+  get 'memos/edit'
+  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
+
+  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
+  # Can be used by load balancers and uptime monitors to verify that the app is live.
+  get 'up' => 'rails/health#show', as: :rails_health_check
+  root 'memos#index'
+  resources :memos
+
+  # Defines the root path route ("/")
+  # root "posts#index"
+end
diff --git a/config/storage.yml b/config/storage.yml
new file mode 100644
index 0000000..4942ab6
--- /dev/null
+++ b/config/storage.yml
@@ -0,0 +1,34 @@
+test:
+  service: Disk
+  root: <%= Rails.root.join("tmp/storage") %>
+
+local:
+  service: Disk
+  root: <%= Rails.root.join("storage") %>
+
+# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
+# amazon:
+#   service: S3
+#   access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
+#   secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
+#   region: us-east-1
+#   bucket: your_own_bucket-<%= Rails.env %>
+
+# Remember not to checkin your GCS keyfile to a repository
+# google:
+#   service: GCS
+#   project: your_project
+#   credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
+#   bucket: your_own_bucket-<%= Rails.env %>
+
+# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
+# microsoft:
+#   service: AzureStorage
+#   storage_account_name: your_account_name
+#   storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
+#   container: your_container_name-<%= Rails.env %>
+
+# mirror:
+#   service: Mirror
+#   primary: local
+#   mirrors: [ amazon, google, microsoft ]
diff --git a/config/tailwind.config.js b/config/tailwind.config.js
new file mode 100644
index 0000000..cb85099
--- /dev/null
+++ b/config/tailwind.config.js
@@ -0,0 +1,23 @@
+module.exports = {
+  content: [
+    "./app/views/**/*.erb",
+    "./app/helpers/**/*.rb",
+    "./app/javascript/**/*.js",
+  ],
+  theme: {
+    extend: {
+      keyframes: {
+        flashFade: {
+          "0%": { transform: "translateX(180px)", opacity: 0 },
+          "20%": { transform: "translateX(0)", opacity: 1 },
+          "80%": { transform: "translateX(0)", opacity: 1 },
+          "100%": { transform: "translateX(180px)", opacity: 0 },
+        },
+      },
+      animation: {
+        flashFade: "flashFade 5s ease-in-out forwards",
+      },
+    },
+  },
+  plugins: [],
+};
diff --git a/db/cache_schema.rb b/db/cache_schema.rb
new file mode 100644
index 0000000..fc99b30
--- /dev/null
+++ b/db/cache_schema.rb
@@ -0,0 +1,24 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# This file is the source Rails uses to define your schema when running `bin/rails
+# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema[8.0].define(version: 1) do
+  create_table "solid_cache_entries", force: :cascade do |t|
+    t.binary "key", limit: 1024, null: false
+    t.binary "value", limit: 536870912, null: false
+    t.datetime "created_at", null: false
+    t.integer "key_hash", limit: 8, null: false
+    t.integer "byte_size", limit: 4, null: false
+    t.index ["byte_size"], name: "index_solid_cache_entries_on_byte_size"
+    t.index ["key_hash", "byte_size"], name: "index_solid_cache_entries_on_key_hash_and_byte_size"
+    t.index ["key_hash"], name: "index_solid_cache_entries_on_key_hash", unique: true
+  end
+end
diff --git a/db/migrate/20250219123840_create_memos.rb b/db/migrate/20250219123840_create_memos.rb
new file mode 100644
index 0000000..bee1afb
--- /dev/null
+++ b/db/migrate/20250219123840_create_memos.rb
@@ -0,0 +1,8 @@
+class CreateMemos < ActiveRecord::Migration[7.1]
+  def change
+    create_table :memos do |t|
+      t.text :content, null: false
+      t.timestamps
+    end
+  end
+end
diff --git a/db/queue_schema.rb b/db/queue_schema.rb
new file mode 100644
index 0000000..4b2cdcd
--- /dev/null
+++ b/db/queue_schema.rb
@@ -0,0 +1,141 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# This file is the source Rails uses to define your schema when running `bin/rails
+# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema[8.0].define(version: 1) do
+  create_table "solid_queue_blocked_executions", force: :cascade do |t|
+    t.bigint "job_id", null: false
+    t.string "queue_name", null: false
+    t.integer "priority", default: 0, null: false
+    t.string "concurrency_key", null: false
+    t.datetime "expires_at", null: false
+    t.datetime "created_at", null: false
+    t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release"
+    t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance"
+    t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true
+  end
+
+  create_table "solid_queue_claimed_executions", force: :cascade do |t|
+    t.bigint "job_id", null: false
+    t.bigint "process_id"
+    t.datetime "created_at", null: false
+    t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true
+    t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id"
+  end
+
+  create_table "solid_queue_failed_executions", force: :cascade do |t|
+    t.bigint "job_id", null: false
+    t.text "error"
+    t.datetime "created_at", null: false
+    t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true
+  end
+
+  create_table "solid_queue_jobs", force: :cascade do |t|
+    t.string "queue_name", null: false
+    t.string "class_name", null: false
+    t.text "arguments"
+    t.integer "priority", default: 0, null: false
+    t.string "active_job_id"
+    t.datetime "scheduled_at"
+    t.datetime "finished_at"
+    t.string "concurrency_key"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id"
+    t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name"
+    t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at"
+    t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering"
+    t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting"
+  end
+
+  create_table "solid_queue_pauses", force: :cascade do |t|
+    t.string "queue_name", null: false
+    t.datetime "created_at", null: false
+    t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true
+  end
+
+  create_table "solid_queue_processes", force: :cascade do |t|
+    t.string "kind", null: false
+    t.datetime "last_heartbeat_at", null: false
+    t.bigint "supervisor_id"
+    t.integer "pid", null: false
+    t.string "hostname"
+    t.text "metadata"
+    t.datetime "created_at", null: false
+    t.string "name", null: false
+    t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at"
+    t.index ["name", "supervisor_id"], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true
+    t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id"
+  end
+
+  create_table "solid_queue_ready_executions", force: :cascade do |t|
+    t.bigint "job_id", null: false
+    t.string "queue_name", null: false
+    t.integer "priority", default: 0, null: false
+    t.datetime "created_at", null: false
+    t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true
+    t.index ["priority", "job_id"], name: "index_solid_queue_poll_all"
+    t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue"
+  end
+
+  create_table "solid_queue_recurring_executions", force: :cascade do |t|
+    t.bigint "job_id", null: false
+    t.string "task_key", null: false
+    t.datetime "run_at", null: false
+    t.datetime "created_at", null: false
+    t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true
+    t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true
+  end
+
+  create_table "solid_queue_recurring_tasks", force: :cascade do |t|
+    t.string "key", null: false
+    t.string "schedule", null: false
+    t.string "command", limit: 2048
+    t.string "class_name"
+    t.text "arguments"
+    t.string "queue_name"
+    t.integer "priority", default: 0
+    t.boolean "static", default: true, null: false
+    t.text "description"
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["key"], name: "index_solid_queue_recurring_tasks_on_key", unique: true
+    t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static"
+  end
+
+  create_table "solid_queue_scheduled_executions", force: :cascade do |t|
+    t.bigint "job_id", null: false
+    t.string "queue_name", null: false
+    t.integer "priority", default: 0, null: false
+    t.datetime "scheduled_at", null: false
+    t.datetime "created_at", null: false
+    t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true
+    t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all"
+  end
+
+  create_table "solid_queue_semaphores", force: :cascade do |t|
+    t.string "key", null: false
+    t.integer "value", default: 1, null: false
+    t.datetime "expires_at", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at"
+    t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value"
+    t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true
+  end
+
+  add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+  add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+  add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+  add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+  add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+  add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade
+end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 0000000..a0409ce
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,19 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# This file is the source Rails uses to define your schema when running `bin/rails
+# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema[8.0].define(version: 2025_02_19_123840) do
+  create_table "memos", force: :cascade do |t|
+    t.text "content", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+  end
+end
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 0000000..4fbd6ed
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,9 @@
+# This file should ensure the existence of records required to run the application in every environment (production,
+# development, test). The code here should be idempotent so that it can be executed at any point in every environment.
+# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
+#
+# Example:
+#
+#   ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
+#     MovieGenre.find_or_create_by!(name: genre_name)
+#   end
diff --git a/lib/assets/.keep b/lib/assets/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/lib/tasks/.keep b/lib/tasks/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/log/.keep b/log/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 0000000..2be3af2
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>The page you were looking for doesn't exist (404)</title>
+  <meta name="viewport" content="width=device-width,initial-scale=1">
+  <style>
+  .rails-default-error-page {
+    background-color: #EFEFEF;
+    color: #2E2F30;
+    text-align: center;
+    font-family: arial, sans-serif;
+    margin: 0;
+  }
+
+  .rails-default-error-page div.dialog {
+    width: 95%;
+    max-width: 33em;
+    margin: 4em auto 0;
+  }
+
+  .rails-default-error-page div.dialog > div {
+    border: 1px solid #CCC;
+    border-right-color: #999;
+    border-left-color: #999;
+    border-bottom-color: #BBB;
+    border-top: #B00100 solid 4px;
+    border-top-left-radius: 9px;
+    border-top-right-radius: 9px;
+    background-color: white;
+    padding: 7px 12% 0;
+    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
+  }
+
+  .rails-default-error-page h1 {
+    font-size: 100%;
+    color: #730E15;
+    line-height: 1.5em;
+  }
+
+  .rails-default-error-page div.dialog > p {
+    margin: 0 0 1em;
+    padding: 1em;
+    background-color: #F7F7F7;
+    border: 1px solid #CCC;
+    border-right-color: #999;
+    border-left-color: #999;
+    border-bottom-color: #999;
+    border-bottom-left-radius: 4px;
+    border-bottom-right-radius: 4px;
+    border-top-color: #DADADA;
+    color: #666;
+    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
+  }
+  </style>
+</head>
+
+<body class="rails-default-error-page">
+  <!-- This file lives in public/404.html -->
+  <div class="dialog">
+    <div>
+      <h1>The page you were looking for doesn't exist.</h1>
+      <p>You may have mistyped the address or the page may have moved.</p>
+    </div>
+    <p>If you are the application owner check the logs for more information.</p>
+  </div>
+</body>
+</html>
diff --git a/public/422.html b/public/422.html
new file mode 100644
index 0000000..c08eac0
--- /dev/null
+++ b/public/422.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>The change you wanted was rejected (422)</title>
+  <meta name="viewport" content="width=device-width,initial-scale=1">
+  <style>
+  .rails-default-error-page {
+    background-color: #EFEFEF;
+    color: #2E2F30;
+    text-align: center;
+    font-family: arial, sans-serif;
+    margin: 0;
+  }
+
+  .rails-default-error-page div.dialog {
+    width: 95%;
+    max-width: 33em;
+    margin: 4em auto 0;
+  }
+
+  .rails-default-error-page div.dialog > div {
+    border: 1px solid #CCC;
+    border-right-color: #999;
+    border-left-color: #999;
+    border-bottom-color: #BBB;
+    border-top: #B00100 solid 4px;
+    border-top-left-radius: 9px;
+    border-top-right-radius: 9px;
+    background-color: white;
+    padding: 7px 12% 0;
+    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
+  }
+
+  .rails-default-error-page h1 {
+    font-size: 100%;
+    color: #730E15;
+    line-height: 1.5em;
+  }
+
+  .rails-default-error-page div.dialog > p {
+    margin: 0 0 1em;
+    padding: 1em;
+    background-color: #F7F7F7;
+    border: 1px solid #CCC;
+    border-right-color: #999;
+    border-left-color: #999;
+    border-bottom-color: #999;
+    border-bottom-left-radius: 4px;
+    border-bottom-right-radius: 4px;
+    border-top-color: #DADADA;
+    color: #666;
+    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
+  }
+  </style>
+</head>
+
+<body class="rails-default-error-page">
+  <!-- This file lives in public/422.html -->
+  <div class="dialog">
+    <div>
+      <h1>The change you wanted was rejected.</h1>
+      <p>Maybe you tried to change something you didn't have access to.</p>
+    </div>
+    <p>If you are the application owner check the logs for more information.</p>
+  </div>
+</body>
+</html>
diff --git a/public/500.html b/public/500.html
new file mode 100644
index 0000000..78a030a
--- /dev/null
+++ b/public/500.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>We're sorry, but something went wrong (500)</title>
+  <meta name="viewport" content="width=device-width,initial-scale=1">
+  <style>
+  .rails-default-error-page {
+    background-color: #EFEFEF;
+    color: #2E2F30;
+    text-align: center;
+    font-family: arial, sans-serif;
+    margin: 0;
+  }
+
+  .rails-default-error-page div.dialog {
+    width: 95%;
+    max-width: 33em;
+    margin: 4em auto 0;
+  }
+
+  .rails-default-error-page div.dialog > div {
+    border: 1px solid #CCC;
+    border-right-color: #999;
+    border-left-color: #999;
+    border-bottom-color: #BBB;
+    border-top: #B00100 solid 4px;
+    border-top-left-radius: 9px;
+    border-top-right-radius: 9px;
+    background-color: white;
+    padding: 7px 12% 0;
+    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
+  }
+
+  .rails-default-error-page h1 {
+    font-size: 100%;
+    color: #730E15;
+    line-height: 1.5em;
+  }
+
+  .rails-default-error-page div.dialog > p {
+    margin: 0 0 1em;
+    padding: 1em;
+    background-color: #F7F7F7;
+    border: 1px solid #CCC;
+    border-right-color: #999;
+    border-left-color: #999;
+    border-bottom-color: #999;
+    border-bottom-left-radius: 4px;
+    border-bottom-right-radius: 4px;
+    border-top-color: #DADADA;
+    color: #666;
+    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
+  }
+  </style>
+</head>
+
+<body class="rails-default-error-page">
+  <!-- This file lives in public/500.html -->
+  <div class="dialog">
+    <div>
+      <h1>We're sorry, but something went wrong.</h1>
+    </div>
+    <p>If you are the application owner check the logs for more information.</p>
+  </div>
+</body>
+</html>
diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png
new file mode 100644
index 0000000..e69de29
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 0000000..e69de29
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..c19f78a
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1 @@
+# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
diff --git a/recovered.sql b/recovered.sql
new file mode 100644
index 0000000..a6f999a
--- /dev/null
+++ b/recovered.sql
@@ -0,0 +1,35 @@
+BEGIN;
+PRAGMA writable_schema = on;
+PRAGMA encoding = 'UTF-8';
+PRAGMA page_size = '4096';
+PRAGMA auto_vacuum = '0';
+PRAGMA user_version = '0';
+PRAGMA application_id = '0';
+CREATE TABLE sqlite_sequence(name,seq);
+CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
+CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
+CREATE TABLE "memos" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "content" text NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
+INSERT INTO sqlite_schema VALUES('table', 'memos_fts', 'memos_fts', 0, 'CREATE VIRTUAL TABLE memos_fts USING fts5(
+        content,
+        content=''memos'',
+        content_rowid=''id''
+      )');
+CREATE TABLE 'memos_fts_data'(id INTEGER PRIMARY KEY, block BLOB);
+CREATE TABLE 'memos_fts_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID;
+CREATE TABLE 'memos_fts_docsize'(id INTEGER PRIMARY KEY, sz BLOB);
+CREATE TABLE 'memos_fts_config'(k PRIMARY KEY, v) WITHOUT ROWID;
+INSERT OR IGNORE INTO 'schema_migrations'(_rowid_, 'version') VALUES (1, '20250219123840');
+INSERT OR IGNORE INTO 'schema_migrations'(_rowid_, 'version') VALUES (2, '20250220023521');
+INSERT OR IGNORE INTO 'ar_internal_metadata'(_rowid_, 'key', 'value', 'created_at', 'updated_at') VALUES (1, 'environment', 'development', '2025-02-19 12:40:36.453523', '2025-02-19 12:40:36.453525');
+INSERT OR IGNORE INTO 'memos'('id', 'content', 'created_at', 'updated_at') VALUES (40, 'あああ', '2025-02-20 04:51:55.262127', '2025-02-20 04:51:55.262127');
+INSERT OR IGNORE INTO 'memos'('id', 'content', 'created_at', 'updated_at') VALUES (41, 'aaaaa', '2025-02-20 04:52:03.476448', '2025-02-20 04:52:03.476448');
+INSERT OR IGNORE INTO 'memos_fts_data'('id', 'block') VALUES (1, X'0300');
+INSERT OR IGNORE INTO 'memos_fts_data'('id', 'block') VALUES (10, X'00000000000000');
+INSERT OR IGNORE INTO 'memos_fts_docsize'('id', 'sz') VALUES (1, X'00');
+INSERT OR IGNORE INTO 'memos_fts_docsize'('id', 'sz') VALUES (2, X'00');
+INSERT OR IGNORE INTO 'memos_fts_docsize'('id', 'sz') VALUES (3, X'00');
+INSERT OR IGNORE INTO 'memos_fts_config'('k', 'v') VALUES ('version', 4);
+DELETE FROM sqlite_sequence;
+INSERT OR IGNORE INTO 'sqlite_sequence'(_rowid_, 'name', 'seq') VALUES (1, 'memos', 41);
+PRAGMA writable_schema = off;
+COMMIT;
diff --git a/repaired.sql b/repaired.sql
new file mode 100644
index 0000000..67f7576
--- /dev/null
+++ b/repaired.sql
@@ -0,0 +1,30 @@
+/* WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE IF NOT EXISTS "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
+INSERT INTO schema_migrations VALUES('20250219123840');
+INSERT INTO schema_migrations VALUES('20250220023521');
+CREATE TABLE IF NOT EXISTS "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
+INSERT INTO ar_internal_metadata VALUES('environment','development','2025-02-19 12:40:36.453523','2025-02-19 12:40:36.453525');
+CREATE TABLE IF NOT EXISTS "memos" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "content" text NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
+INSERT INTO memos VALUES(40,'あああ','2025-02-20 04:51:55.262127','2025-02-20 04:51:55.262127');
+INSERT INTO memos VALUES(41,'aaaaa','2025-02-20 04:52:03.476448','2025-02-20 04:52:03.476448');
+PRAGMA writable_schema=ON;
+INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)VALUES('table','memos_fts','memos_fts',0,'CREATE VIRTUAL TABLE memos_fts USING fts5(
+        content,
+        content=''memos'',
+        content_rowid=''id''
+      )');
+CREATE TABLE IF NOT EXISTS 'memos_fts_data'(id INTEGER PRIMARY KEY, block BLOB);
+INSERT INTO memos_fts_data VALUES(1,X'0300');
+INSERT INTO memos_fts_data VALUES(10,X'00000000000000');
+CREATE TABLE IF NOT EXISTS 'memos_fts_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID;
+CREATE TABLE IF NOT EXISTS 'memos_fts_docsize'(id INTEGER PRIMARY KEY, sz BLOB);
+INSERT INTO memos_fts_docsize VALUES(1,X'00');
+INSERT INTO memos_fts_docsize VALUES(2,X'00');
+INSERT INTO memos_fts_docsize VALUES(3,X'00');
+CREATE TABLE IF NOT EXISTS 'memos_fts_config'(k PRIMARY KEY, v) WITHOUT ROWID;
+INSERT INTO memos_fts_config VALUES('version',4);
+INSERT INTO sqlite_sequence VALUES('memos',41);
+PRAGMA writable_schema=OFF;
+COMMIT;
diff --git a/storage/.keep b/storage/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb
new file mode 100644
index 0000000..d19212a
--- /dev/null
+++ b/test/application_system_test_case.rb
@@ -0,0 +1,5 @@
+require "test_helper"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+  driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
+end
diff --git a/test/channels/application_cable/connection_test.rb b/test/channels/application_cable/connection_test.rb
new file mode 100644
index 0000000..6340bf9
--- /dev/null
+++ b/test/channels/application_cable/connection_test.rb
@@ -0,0 +1,13 @@
+require "test_helper"
+
+module ApplicationCable
+  class ConnectionTest < ActionCable::Connection::TestCase
+    # test "connects with cookies" do
+    #   cookies.signed[:user_id] = 42
+    #
+    #   connect
+    #
+    #   assert_equal connection.user_id, "42"
+    # end
+  end
+end
diff --git a/test/controllers/.keep b/test/controllers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/controllers/memos_controller_test.rb b/test/controllers/memos_controller_test.rb
new file mode 100644
index 0000000..9d98b2d
--- /dev/null
+++ b/test/controllers/memos_controller_test.rb
@@ -0,0 +1,23 @@
+require "test_helper"
+
+class MemosControllerTest < ActionDispatch::IntegrationTest
+  test "should get index" do
+    get memos_index_url
+    assert_response :success
+  end
+
+  test "should get show" do
+    get memos_show_url
+    assert_response :success
+  end
+
+  test "should get new" do
+    get memos_new_url
+    assert_response :success
+  end
+
+  test "should get edit" do
+    get memos_edit_url
+    assert_response :success
+  end
+end
diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/memos.yml b/test/fixtures/memos.yml
new file mode 100644
index 0000000..37793a4
--- /dev/null
+++ b/test/fixtures/memos.yml
@@ -0,0 +1,7 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+  content: MyText
+
+two:
+  content: MyText
diff --git a/test/helpers/.keep b/test/helpers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/integration/.keep b/test/integration/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/mailers/.keep b/test/mailers/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/models/.keep b/test/models/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/models/memo_test.rb b/test/models/memo_test.rb
new file mode 100644
index 0000000..7d2fb54
--- /dev/null
+++ b/test/models/memo_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class MemoTest < ActiveSupport::TestCase
+  # test "the truth" do
+  #   assert true
+  # end
+end
diff --git a/test/system/.keep b/test/system/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 0000000..0c22470
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,15 @@
+ENV["RAILS_ENV"] ||= "test"
+require_relative "../config/environment"
+require "rails/test_help"
+
+module ActiveSupport
+  class TestCase
+    # Run tests in parallel with specified workers
+    parallelize(workers: :number_of_processors)
+
+    # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
+    fixtures :all
+
+    # Add more helper methods to be used by all tests here...
+  end
+end
diff --git a/tmp/.keep b/tmp/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/tmp/pids/.keep b/tmp/pids/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/tmp/storage/.keep b/tmp/storage/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/.keep b/vendor/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/vendor/javascript/.keep b/vendor/javascript/.keep
new file mode 100644
index 0000000..e69de29