diff --git a/package.json b/package.json
index 107cf1ae..867af2b1 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
     "version": "0.0.0",
     "scripts": {
         "dev": "vite",
+        "dev-server": "node server/server.js",
         "build": "vite build",
         "serve": "vite preview"
     },
diff --git a/server/model/monitor.js b/server/model/monitor.js
index 1b25270f..9c491146 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -1,6 +1,18 @@
 const dayjs = require("dayjs");
+const utc = require('dayjs/plugin/utc')
+var timezone = require('dayjs/plugin/timezone')
+dayjs.extend(utc)
+dayjs.extend(timezone)
+const axios = require("axios");
+const {R} = require("redbean-node");
 const {BeanModel} = require("redbean-node/dist/bean-model");
 
+
+/**
+ * status:
+ *      0 = DOWN
+ *      1 = UP
+ */
 class Monitor extends BeanModel {
 
     toJSON() {
@@ -16,9 +28,36 @@ class Monitor extends BeanModel {
     }
 
     start(io) {
-        const beat = () => {
+        const beat = async () => {
             console.log(`Monitor ${this.id}: Heartbeat`)
-            io.to(this.user_id).emit("heartbeat", dayjs().unix());
+
+            let bean = R.dispense("heartbeat")
+            bean.monitor_id = this.id;
+            bean.time = R.isoDateTime(dayjs.utc());
+            bean.status = 0;
+
+            try {
+                if (this.type === "http") {
+                    let startTime = dayjs().valueOf();
+                    let res = await axios.get(this.url)
+                    bean.msg = `${res.status} - ${res.statusText}`
+                    bean.ping = dayjs().valueOf() - startTime;
+                    bean.status = 1;
+                }
+
+            } catch (error) {
+                bean.msg = error.message;
+            }
+
+            io.to(this.user_id).emit("heartbeat", {
+                monitorID: this.id,
+                status: bean.status,
+                time: bean.time,
+                msg: bean.msg,
+                ping: bean.ping,
+            });
+
+            await R.store(bean)
         }
 
         beat();
diff --git a/server/server.js b/server/server.js
index e30f6e7e..e9f62c49 100644
--- a/server/server.js
+++ b/server/server.js
@@ -4,7 +4,6 @@ const http = require('http');
 const server = http.createServer(app);
 const { Server } = require("socket.io");
 const io = new Server(server);
-const axios = require('axios');
 const dayjs = require("dayjs");
 const {R} = require("redbean-node");
 const passwordHash = require('password-hash');
@@ -12,7 +11,6 @@ const jwt = require('jsonwebtoken');
 const Monitor = require("./model/monitor");
 const {sleep} = require("./util");
 
-
 let stop = false;
 let interval = 6000;
 let totalClient = 0;
@@ -21,12 +19,11 @@ let loadFromDatabase = true;
 let monitorList = {};
 
 (async () => {
-
     R.setup('sqlite', {
-        filename: '../data/kuma.db'
+        filename: './data/kuma.db'
     });
     R.freeze(true)
-    await R.autoloadModels("./model");
+    await R.autoloadModels("./server/model");
 
     await initDatabase();
 
@@ -118,15 +115,54 @@ let monitorList = {};
                 bean.user_id = socket.userID
                 await R.store(bean)
 
+                await startMonitor(socket.userID, bean.id);
+                await sendMonitorList(socket);
+
                 callback({
                     ok: true,
                     msg: "Added Successfully.",
                     monitorID: bean.id
                 });
 
+            } catch (e) {
+                callback({
+                    ok: false,
+                    msg: e.message
+                });
+            }
+        });
+
+        socket.on("editMonitor", async (monitor, callback) => {
+            try {
+                checkLogin(socket)
+
+                let bean = await R.findOne("monitor", " id = ? ", [ monitor.id ])
+
+                if (bean.user_id !== socket.userID) {
+                    throw new Error("Permission denied.")
+                }
+
+                bean.name = monitor.name
+                bean.type = monitor.type
+                bean.url = monitor.url
+                bean.interval = monitor.interval
+
+                await R.store(bean)
+
+                if (bean.active) {
+                    await restartMonitor(socket.userID, bean.id)
+                }
+
                 await sendMonitorList(socket);
 
+                callback({
+                    ok: true,
+                    msg: "Saved.",
+                    monitorID: bean.id
+                });
+
             } catch (e) {
+                console.log(e)
                 callback({
                     ok: false,
                     msg: e.message
@@ -294,14 +330,14 @@ async function afterLogin(socket, user) {
 }
 
 async function getMonitorJSONList(userID) {
-    let result = [];
+    let result = {};
 
-    let monitorList = await R.find("monitor", " user_id = ? ORDER BY weight DESC ", [
+    let monitorList = await R.find("monitor", " user_id = ? ORDER BY active DESC, name ASC ", [
         userID
     ])
 
     for (let monitor of monitorList) {
-        result.push(monitor.toJSON())
+        result[monitor.id] = monitor.toJSON();
     }
 
     return result;
@@ -346,10 +382,18 @@ async function startMonitor(userID, monitorID) {
         monitorID
     ])
 
+    if (monitor.id in monitorList) {
+        monitorList[monitor.id].stop();
+    }
+
     monitorList[monitor.id] = monitor;
     monitor.start(io)
 }
 
+async function restartMonitor(userID, monitorID) {
+    return await startMonitor(userID, monitorID)
+}
+
 async function pauseMonitor(userID, monitorID) {
     await checkOwner(userID, monitorID)
 
diff --git a/src/assets/vars.scss b/src/assets/vars.scss
index dd1bcc0b..31b0262d 100644
--- a/src/assets/vars.scss
+++ b/src/assets/vars.scss
@@ -1,4 +1,5 @@
 $primary: #5CDD8B;
+$danger: #DC3545;
 $link-color: #111;
 $border-radius: 50rem;
 
diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue
index bba0fa54..ede199ee 100644
--- a/src/components/HeartbeatBar.vue
+++ b/src/components/HeartbeatBar.vue
@@ -1,7 +1,7 @@
 <template>
     <div class="wrap" :style="wrapStyle" ref="wrap">
         <div class="hp-bar-big" :style="barStyle">
-            <div class="beat"  :style="beatStyle" v-for="(beat, index) in shortBeatList" :key="index">
+            <div class="beat" :class="{ 'empty' : (beat === 0), 'down' : (beat.status === 0) }" :style="beatStyle" v-for="(beat, index) in shortBeatList" :key="index">
             </div>
         </div>
     </div>
@@ -11,12 +11,15 @@
 
 
 export default {
+    props: {
+        size: {
+            type: String,
+            default: "big"
+        },
+        monitorId: Number
+    },
     data() {
         return {
-            i: 1,
-            beatList: [
-
-            ],
             beatWidth: 10,
             beatHeight: 30,
             hoverScale: 1.5,
@@ -25,26 +28,38 @@ export default {
             maxBeat: -1,
         }
     },
-    destroyed() {
+    unmounted() {
         window.removeEventListener("resize", this.resize);
     },
     mounted() {
+        if (this.size === "small") {
+            this.beatWidth = 5.6;
+            this.beatMargin = 2.4;
+            this.beatHeight = 16
+        }
+
         window.addEventListener("resize", this.resize);
         this.resize();
-
-        setInterval(() => {
-            this.beatList.push(this.i++)
-        }, 3000)
-
     },
     methods: {
         resize() {
-            this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
+            if (this.$refs.wrap) {
+                this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
+            }
         }
     },
     computed: {
 
+        beatList() {
+            if (! (this.monitorId in this.$root.heartbeatList)) {
+                this.$root.heartbeatList[this.monitorId] = [];
+            }
+            return this.$root.heartbeatList[this.monitorId]
+        },
+
         shortBeatList() {
+            let placeholders = []
+
             let start = this.beatList.length - this.maxBeat;
 
             if (this.move) {
@@ -52,10 +67,16 @@ export default {
             }
 
             if (start < 0) {
+                // Add empty placeholder
+                for (let i = start; i < 0; i++) {
+                    placeholders.push(0)
+                }
                 start = 0;
             }
 
-            return this.beatList.slice(start)
+
+
+            return placeholders.concat(this.beatList.slice(start))
         },
 
         wrapStyle() {
@@ -104,7 +125,6 @@ export default {
     watch: {
         beatList: {
             handler(val, oldVal) {
-                console.log("add beat2")
                 this.move = true;
 
                 setTimeout(() => {
@@ -131,14 +151,17 @@ export default {
         display: inline-block;
         background-color: $primary;
         border-radius: 50rem;
-        transition: all ease-in-out 0.15s;
 
-        &.new-beat {
+        &.empty {
             background-color: aliceblue;
         }
 
+        &.down {
+            background-color: $danger;
+        }
 
-        &:hover {
+        &:not(.empty):hover {
+            transition: all ease-in-out 0.15s;
             opacity: 0.8;
             transform: scale(var(--hover-scale));
         }
diff --git a/src/layouts/EmptyLayout.vue b/src/layouts/EmptyLayout.vue
new file mode 100644
index 00000000..7b720447
--- /dev/null
+++ b/src/layouts/EmptyLayout.vue
@@ -0,0 +1,13 @@
+<template>
+    <router-view />
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style scoped>
+
+</style>
diff --git a/src/main.js b/src/main.js
index 085c25f2..112512e5 100644
--- a/src/main.js
+++ b/src/main.js
@@ -3,6 +3,7 @@ import {createRouter, createWebHistory} from 'vue-router'
 
 import App from './App.vue'
 import Layout from './layouts/Layout.vue'
+import EmptyLayout from './layouts/EmptyLayout.vue'
 import Settings from "./pages/Settings.vue";
 import Dashboard from "./pages/Dashboard.vue";
 import DashboardHome from "./pages/DashboardHome.vue";
@@ -30,17 +31,23 @@ const routes = [
                         component: DashboardHome,
                         children: [
                             {
-                                path: ':id',
-                                component: Details,
+                                path: '/dashboard/:id',
+                                component: EmptyLayout,
+                                children: [
+                                    {
+                                        path: '',
+                                        component: Details,
+                                    },
+                                    {
+                                        path: '/edit/:id',
+                                        component: EditMonitor,
+                                    },
+                                ]
                             },
                             {
                                 path: '/add',
                                 component: EditMonitor,
                             },
-                            {
-                                path: '/edit/:id',
-                                component: EditMonitor,
-                            },
                         ]
                     },
                     {
diff --git a/src/mixins/socket.js b/src/mixins/socket.js
index a55a1d3e..1592e700 100644
--- a/src/mixins/socket.js
+++ b/src/mixins/socket.js
@@ -21,7 +21,10 @@ export default {
             ],
             importantHeartbeatList: [
 
-            ]
+            ],
+            heartbeatList: {
+
+            },
         }
     },
 
@@ -34,6 +37,16 @@ export default {
             this.monitorList = data;
         });
 
+        socket.on('heartbeat', (data) => {
+
+            if (! (data.monitorID in this.heartbeatList)) {
+                this.heartbeatList[data.monitorID] = [];
+            }
+
+            this.heartbeatList[data.monitorID].push(data)
+        });
+
+
         socket.on('disconnect', () => {
             this.socket.connected = false;
         });
@@ -53,9 +66,11 @@ export default {
     },
 
     methods: {
+
         getSocket() {
           return socket;
         },
+
         toastRes(res) {
             if (res.ok) {
                 toast.success(res.msg);
@@ -63,6 +78,7 @@ export default {
                 toast.error(res.msg);
             }
         },
+
         login(username, password, callback) {
             socket.emit("login", {
                 username,
@@ -81,18 +97,19 @@ export default {
                 callback(res)
             })
         },
+
         loginByToken(token) {
             socket.emit("loginByToken", token, (res) => {
                 this.allowLoginDialog = true;
 
                 if (! res.ok) {
                     this.logout()
-                    console.log(res.msg)
                 } else {
                     this.loggedIn = true;
                 }
             })
         },
+
         logout() {
             storage.removeItem("token");
             this.socket.token = null;
@@ -102,19 +119,59 @@ export default {
                 toast.success("Logout Successfully")
             })
         },
+
         add(monitor, callback) {
             socket.emit("add", monitor, callback)
         },
+
         deleteMonitor(monitorID, callback) {
             socket.emit("deleteMonitor", monitorID, callback)
         },
-        loadMonitor(monitorID) {
 
-        }
     },
 
     computed: {
+        lastHeartbeatList() {
+            let result = {}
 
+            for (let monitorID in this.heartbeatList) {
+                let index = this.heartbeatList[monitorID].length - 1;
+                result[monitorID] = this.heartbeatList[monitorID][index];
+            }
+
+            return result;
+        },
+
+        statusList() {
+            let result = {}
+
+            let unknown = {
+                text: "Unknown",
+                color: "secondary"
+            }
+
+            for (let monitorID in this.lastHeartbeatList) {
+                let lastHeartBeat = this.lastHeartbeatList[monitorID]
+
+                if (! lastHeartBeat) {
+                    result[monitorID] = unknown;
+                } else if (lastHeartBeat.status === 1) {
+                    result[monitorID] = {
+                        text: "Up",
+                        color: "primary"
+                    };
+                } else if (lastHeartBeat.status === 0) {
+                    result[monitorID] = {
+                        text: "Down",
+                        color: "danger"
+                    };
+                } else {
+                    result[monitorID] = unknown;
+                }
+            }
+
+            return result;
+        }
     }
 
 }
diff --git a/src/pages/Dashboard.vue b/src/pages/Dashboard.vue
index 25903f0b..87950b6d 100644
--- a/src/pages/Dashboard.vue
+++ b/src/pages/Dashboard.vue
@@ -23,20 +23,7 @@
 
                             </div>
                         	<div class="col-6">
-                                <div class="hp-bar">
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                    <div></div>
-                                </div>
+                                <HeartbeatBar size="small" :monitor-id="item.id" />
                             </div>
                         </div>
 
@@ -54,8 +41,11 @@
 
 <script>
 
+import HeartbeatBar from "../components/HeartbeatBar.vue";
+
 export default {
     components: {
+        HeartbeatBar
     },
     data() {
         return {
@@ -78,6 +68,8 @@ export default {
 
 .list {
     margin-top: 25px;
+    height: auto;
+    min-height: calc(100vh - 200px);
 
     .item {
         display: block;
@@ -92,6 +84,8 @@ export default {
 
         .info {
             white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
         }
 
         &:hover {
@@ -118,6 +112,10 @@ export default {
         border-radius: 50rem;
         transition: all ease-in-out 0.15s;
 
+        &.empty {
+            background-color: aliceblue;
+        }
+
         &:hover {
             opacity: 0.8;
             transform: scale(1.5);
diff --git a/src/pages/DashboardHome.vue b/src/pages/DashboardHome.vue
index b9ecfefb..80b1db71 100644
--- a/src/pages/DashboardHome.vue
+++ b/src/pages/DashboardHome.vue
@@ -61,15 +61,19 @@
 
             	<div class="col">
                     <h3>Up</h3>
-                    <span class="num">2</span>
+                    <span class="num">{{ stats.up }}</span>
                 </div>
             	<div class="col">
                     <h3>Down</h3>
-                    <span class="num text-danger">0</span>
+                    <span class="num text-danger">{{ stats.down }}</span>
+                </div>
+                <div class="col">
+                    <h3>Unknown</h3>
+                    <span class="num text-secondary">{{ stats.unknown }}</span>
                 </div>
                 <div class="col">
                     <h3>Pause</h3>
-                    <span class="num">0</span>
+                    <span class="num text-secondary">{{ stats.pause }}</span>
                 </div>
             </div>
         </div>
@@ -107,7 +111,37 @@
 <script>
 export default {
     computed: {
+        stats() {
+            let result = {
+                up: 0,
+                down: 0,
+                unknown: 0,
+                pause: 0,
+            };
 
+            for (let monitorID in this.$root.monitorList) {
+                let beat = this.$root.lastHeartbeatList[monitorID];
+                let monitor = this.$root.monitorList[monitorID]
+
+                if (monitor && ! monitor.active) {
+                    result.pause++;
+                } else if (beat) {
+                    if (beat.status === 1) {
+                        result.up++;
+                    } else if (beat.status === 0) {
+                        result.down++;
+                    } else {
+                        result.unknown++;
+                    }
+                } else {
+                    console.log(monitorID + " Unknown?")
+                    console.log(beat)
+                    result.unknown++;
+                }
+            }
+
+            return result;
+        },
     }
 }
 </script>
diff --git a/src/pages/Details.vue b/src/pages/Details.vue
index c5d263d9..ffd70494 100644
--- a/src/pages/Details.vue
+++ b/src/pages/Details.vue
@@ -1,6 +1,6 @@
 <template>
-    <h1>{{ monitor.name }}</h1>
-    <h2>{{ monitor.url }}</h2>
+    <h1> {{ monitor.name }}</h1>
+    <p class="url"><a :href="monitor.url" target="_blank" v-if="monitor.type === 'http'">{{ monitor.url }}</a></p>
 
     <div class="functions">
         <button class="btn btn-light" @click="pauseDialog" v-if="monitor.active">Pause</button>
@@ -11,14 +11,15 @@
 
     <div class="shadow-box">
 
-        <HeartbeatBar />
+
 
         <div class="row">
             <div class="col-md-8">
-
+                <HeartbeatBar :monitor-id="monitor.id" />
+                <span class="word">Check every {{ monitor.interval }} seconds.</span>
             </div>
-            <div class="col-md-4">
-
+            <div class="col-md-4 text-center">
+                <span class="badge rounded-pill" :class=" 'bg-' + status.color " style="font-size: 30px">{{ status.text }}</span>
             </div>
         </div>
     </div>
@@ -53,15 +54,28 @@ export default {
     },
     computed: {
         monitor() {
-            let id = parseInt(this.$route.params.id)
+            let id = this.$route.params.id
+            return this.$root.monitorList[id];
+        },
+
+        lastHeartBeat() {
+            if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
+                return this.$root.lastHeartbeatList[this.monitor.id]
+            } else {
+                return { status: -1 }
+            }
+        },
+
+        status() {
+            if (this.$root.statusList[this.monitor.id]) {
+                return this.$root.statusList[this.monitor.id]
+            } else {
+                return {
 
-            for (let monitor of this.$root.monitorList) {
-                if (monitor.id === id) {
-                    return monitor;
                 }
             }
-            return {};
-        },
+        }
+
     },
     methods: {
         pauseDialog() {
@@ -97,9 +111,14 @@ export default {
 <style lang="scss" scoped>
 @import "../assets/vars.scss";
 
-h2 {
+.url {
     color: $primary;
     margin-bottom: 20px;
+    font-weight: bold;
+
+    a {
+        color: $primary;
+    }
 }
 
 .functions {
@@ -112,4 +131,9 @@ h2 {
     padding: 20px;
     margin-top: 25px;
 }
+
+.word {
+    color: #AAA;
+    font-size: 14px;
+}
 </style>
diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue
index 143806a7..1bc16bb8 100644
--- a/src/pages/EditMonitor.vue
+++ b/src/pages/EditMonitor.vue
@@ -29,7 +29,7 @@
 
                     <div class="mb-3">
                         <label for="interval" class="form-label">Heartbeat Interval (Every {{ monitor.interval }} seconds)</label>
-                        <input type="number" class="form-control" id="interval" v-model="monitor.interval" required min="20" step="20">
+                        <input type="number" class="form-control" id="interval" v-model="monitor.interval" required min="20">
                     </div>
 
                     <div>
@@ -59,24 +59,7 @@ export default {
 
     },
     mounted() {
-
-        if (this.isAdd) {
-            this.monitor = {
-                type: "http",
-                name: "",
-                url: "https://",
-                interval: 60,
-            }
-        } else {
-            this.$root.getSocket().emit("getMonitor", this.$route.params.id, (res) => {
-                if (res.ok) {
-                    this.monitor = res.monitor;
-                } else {
-                    toast.error(res.msg)
-                }
-            })
-        }
-
+        this.init();
     },
     data() {
         return {
@@ -90,9 +73,33 @@ export default {
         },
         isAdd() {
             return this.$route.path === "/add";
+        },
+        isEdit() {
+            return this.$route.path.startsWith("/edit");
         }
     },
     methods: {
+        init() {
+            if (this.isAdd) {
+                console.log("??????")
+                this.monitor = {
+                    type: "http",
+                    name: "",
+                    url: "https://",
+                    interval: 60,
+                }
+            } else if (this.isEdit) {
+                this.$root.getSocket().emit("getMonitor", this.$route.params.id, (res) => {
+                    if (res.ok) {
+                        this.monitor = res.monitor;
+                    } else {
+                        toast.error(res.msg)
+                    }
+                })
+            }
+
+        },
+
         submit() {
             this.processing = true;
 
@@ -109,10 +116,18 @@ export default {
 
                 })
             } else {
-
+                this.$root.getSocket().emit("editMonitor", this.monitor, (res) => {
+                    this.processing = false;
+                    this.$root.toastRes(res)
+                })
             }
         }
-    }
+    },
+    watch: {
+        '$route.fullPath' () {
+            this.init();
+        }
+    },
 }
 </script>