diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 0000000..b8626c4
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+4
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..b7a02c0
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "puma"
+gem "rackup"
+gem "rake"
+gem "roda"
+gem "sentry-ruby"
+
+group :development do
+ gem "irb"
+ gem "minitest"
+end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..25a8a6c
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,81 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ bigdecimal (4.0.1)
+ concurrent-ruby (1.3.6)
+ date (3.5.1)
+ erb (6.0.1)
+ io-console (0.8.2)
+ irb (1.16.0)
+ pp (>= 0.6.0)
+ rdoc (>= 4.0.0)
+ reline (>= 0.4.2)
+ minitest (6.0.1)
+ prism (~> 1.5)
+ nio4r (2.7.5)
+ pp (0.6.3)
+ prettyprint
+ prettyprint (0.2.0)
+ prism (1.8.0)
+ psych (5.3.1)
+ date
+ stringio
+ puma (7.1.0)
+ nio4r (~> 2.0)
+ rack (3.2.4)
+ rackup (2.3.1)
+ rack (>= 3)
+ rake (13.3.1)
+ rdoc (7.0.3)
+ erb
+ psych (>= 4.0.0)
+ tsort
+ reline (0.6.3)
+ io-console (~> 0.5)
+ roda (3.100.0)
+ rack
+ sentry-ruby (6.2.0)
+ bigdecimal
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ stringio (3.2.0)
+ tsort (0.2.0)
+
+PLATFORMS
+ arm64-darwin-25
+ ruby
+
+DEPENDENCIES
+ irb
+ minitest
+ puma
+ rackup
+ rake
+ roda
+ sentry-ruby
+
+CHECKSUMS
+ bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
+ concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
+ date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
+ erb (6.0.1) sha256=28ecdd99c5472aebd5674d6061e3c6b0a45c049578b071e5a52c2a7f13c197e5
+ io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
+ irb (1.16.0) sha256=2abe56c9ac947cdcb2f150572904ba798c1e93c890c256f8429981a7675b0806
+ minitest (6.0.1) sha256=7854c74f48e2e975969062833adc4013f249a4b212f5e7b9d5c040bf838d54bb
+ nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
+ pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
+ prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
+ prism (1.8.0) sha256=84453a16ef5530ea62c5f03ec16b52a459575ad4e7b9c2b360fd8ce2c39c1254
+ psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974
+ puma (7.1.0) sha256=e45c10cb124f224d448c98db653a75499794edbecadc440ad616cf50f2fd49dd
+ rack (3.2.4) sha256=5d74b6f75082a643f43c1e76b419c40f0e5527fcfee1e669ac1e6b73c0ccb6f6
+ rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868
+ rake (13.3.1) sha256=8c9e89d09f66a26a01264e7e3480ec0607f0c497a861ef16063604b1b08eb19c
+ rdoc (7.0.3) sha256=dfe3d0981d19b7bba71d9dbaeb57c9f4e3a7a4103162148a559c4fc687ea81f9
+ reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
+ roda (3.100.0) sha256=35d36f43c68d2bd1974dc77ade8c873558265a191018e1ada88ca662f1fa8e62
+ sentry-ruby (6.2.0) sha256=d7b8a358a3a0d0536bd194b19cc282c85f295b6d242731e9b4a934ccdb71ac17
+ stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
+ tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
+
+BUNDLED WITH
+ 4.0.3
diff --git a/config.ru b/config.ru
new file mode 100644
index 0000000..4ba397e
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,37 @@
+require "roda"
+
+class App < Roda
+ route do |r|
+ # GET / request
+ r.root do
+ r.redirect "/hello"
+ end
+
+ # /hello branch
+ r.on "hello" do
+ # Set variable for all routes in /hello branch
+ @greeting = "Hello"
+
+ # GET /hello/world request
+ r.get "world" do
+ "#{@greeting} world!"
+ end
+
+ # /hello request
+ r.is do
+ # GET /hello request
+ r.get do
+ "#{@greeting}!"
+ end
+
+ # POST /hello request
+ r.post do
+ puts "Someone said #{@greeting}!"
+ r.redirect
+ end
+ end
+ end
+ end
+end
+
+run App.freeze.app