diff --git a/.gitignore b/.gitignore
index 0ffe02c..026fb0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 .qlot
 public/dist.css
+node_modules
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6e473ab
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+install: ## Install dependencies
+	@qlot install
+
+watch: ## Run watch mode
+	@bun run tailwindcss -i ./public/style.css -o ./public/dist.css --watch=always
+
+build: ## Build
+	@bun run tailwindcss -i ./public/style.css -o ./public/dist.css
+
+help: ## Show options
+	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
+		awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
\ No newline at end of file
diff --git a/bun.lockb b/bun.lockb
new file mode 100755
index 0000000..ca8f5b8
Binary files /dev/null and b/bun.lockb differ
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..f59efc1
--- /dev/null
+++ b/package.json
@@ -0,0 +1,6 @@
+{
+  "devDependencies": {
+    "daisyui": "^4.12.2",
+    "tailwindcss": "^3.4.4"
+  }
+}
\ No newline at end of file
diff --git a/public/style.css b/public/style.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/public/style.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/src/app.lisp b/src/app.lisp
index c8222e9..7dba06b 100644
--- a/src/app.lisp
+++ b/src/app.lisp
@@ -10,13 +10,19 @@
            #:update))
 (in-package #:hp)
 
+(defparameter *watch-process* nil)
+
 (defparameter *app* (jg:make-app :address "localhost"
                                  :port env:*port*))
 
 (defun start ()
+  (when (env:dev-mode-p)
+    (setf *watch-process* (uiop:launch-program "make watch")))
   (jg:start *app*))
 
 (defun stop ()
+  (when (env:dev-mode-p)
+    (uiop:terminate-process *watch-process*))
   (jg:stop *app*))
 
 (defun setup ()
diff --git a/src/response.lisp b/src/response.lisp
index 37b1cb9..0fd39d9 100644
--- a/src/response.lisp
+++ b/src/response.lisp
@@ -12,8 +12,7 @@
      (head
        (meta :charset "UTF-8")
        (meta :name "viewport" :content "width=device-width, initial-scale=1")
-       (link :rel "stylesheet" :href "https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css")
-       (script :src "https://cdn.jsdelivr.net/npm/uikit@3.21.5/dist/js/uikit.min.js")
+       (link :rel "stylesheet" :href "/dist.css")
        (script :src "https://cdn.jsdelivr.net/npm/htmx.org@1.9.12/dist/htmx.min.js")
        (script :src "https://cdn.jsdelivr.net/npm/htmx.org@1.9.12/dist/ext/head-support.js")
        (script :src "https://cdn.jsdelivr.net/npm/alpinejs@3.14.0/dist/cdn.min.js" :defer t)
@@ -22,7 +21,7 @@
          :name "description"
          :content (or description "pakuの個人サイト"))
        (body :hx-ext "head-support"
-         (main :class "container"
+         (main :class "container mx-auto"
            children))))))
 
 (defun response (page &key status metadata)
diff --git a/src/routes/index.lisp b/src/routes/index.lisp
index 119a724..9e68226 100644
--- a/src/routes/index.lisp
+++ b/src/routes/index.lisp
@@ -7,7 +7,8 @@
 
 (defcomp page ()
   (hsx
-   (h1 "こんにちは")))
+   (h1 :class "text-primary"
+     "こんにちは")))
 
 (defun handle-get (params)
   (declare (ignore params))
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 0000000..f5337ec
--- /dev/null
+++ b/tailwind.config.js
@@ -0,0 +1,14 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+  content: [
+    "./src/response.lisp",
+    "./src/routes/**/*.lisp",
+    "./src/components/**/*.lisp",
+  ],
+  theme: {
+    extend: {},
+  },
+  plugins: [
+    require('daisyui'),
+  ],
+}