{"id":48037842,"url":"https://github.com/zients/vue-node-online-chess","last_synced_at":"2026-04-04T14:00:41.738Z","repository":{"id":39330683,"uuid":"218715568","full_name":"zients/vue-node-online-chess","owner":"zients","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-04T23:51:40.000Z","size":2390,"stargazers_count":0,"open_issues_count":34,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-23T18:30:57.775Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zients.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-31T08:10:29.000Z","updated_at":"2023-06-12T04:25:22.000Z","dependencies_parsed_at":"2023-02-03T00:45:31.710Z","dependency_job_id":null,"html_url":"https://github.com/zients/vue-node-online-chess","commit_stats":null,"previous_names":["zients/vue-node-online-chess"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/zients/vue-node-online-chess","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zients%2Fvue-node-online-chess","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zients%2Fvue-node-online-chess/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zients%2Fvue-node-online-chess/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zients%2Fvue-node-online-chess/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zients","download_url":"https://codeload.github.com/zients/vue-node-online-chess/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zients%2Fvue-node-online-chess/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31402277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-04T14:00:28.392Z","updated_at":"2026-04-04T14:00:41.728Z","avatar_url":"https://github.com/zients.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Catalog/目錄\n\n## English\n\n[GettingStarted](#GettingStarted)\n\n[GameRoom](#GameRoom)\n\n[LoginRegister](#LoginRegister)\n\n## 中文\n\n[啟動](#啟動)\n\n[簡介](#簡介)\n\n[遊戲房間](#遊戲房間)\n\n[登入註冊](#登入註冊)\n\n# GettingStarted\n\nHello, you can start this project by installing Vue and others modules with front-end and back-end by npm.\n\n```\n$ npm install\n```\n\nThen, we need to run the front-end and backend server.\n\n## Vue\n\n```\n$ npm run serve\n```\n\n## Node\n\n```\n$ npm run start\n```\n\n# Introduction\n\nThis is an online chess game where players can play with others.\n\nThe front-end is developed by vue.\n\nManage the statement by vuex and config the router by vue-router.\n\nI choose socket.io to build the real-time online chess application.\n\nThe back-end is developed by node/express.\n\nIt receives requests, including chess board and login/registration info, etc.\n\nAnd mongoDB, NoSQL, will save data which pass by Joi validation.\n\n# GameRoom\n\nAfter you login, you can enter the room to play and chat with other players.\n\nSo first you choose the room from the room list and join.\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/room.jpg' alt=''\u003e\n\nIf you enter the room paramaters and this room is not exist, you will return the room list.\n\nIf the room is full, you will quit by system. Then, you need to find the new room.\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/roomfull.jpg' alt=''\u003e\n\nIf you aren't login, you can't play with others.\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/beforeLogin.jpg' alt=''\u003e\n\nWhen you enter the room, client will emit the userid and room name from vuex by socket.io. Server will save these info.\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/game.jpg' alt=''\u003e\n\nAfter entering the room, the chess board lock until another player enter. Otherwise, when this turn is not your turn, your chess board will lock.\n\nHowever, one player leaves room or win the chess game. system will reset the chess board after 5 seconds.\n\n```\nrace setting:\n\n    turn: true,       true:white turn false: black turn\n    gamewatching: true      true:can move piece\n\n```\n\n```\n\nsocket server:\n\n  socket.on(\"sendMsg\", (msg, userid, roomName) =\u003e {\n    socket.to(roomName).emit(\"recMsg\", { msg, userid });\n  });\n  ....\n\nsocket client:\n      this.$socket.emit(\"sendMsg\", this.msgInput, this.userid, this.roomName);\n\n```\n\n```\n\nVue socket.io setting:\n\nimport VueSocketIO from \"vue-socket.io\";\nimport io from \"socket.io-client\";\n\nVue.use(\n  new VueSocketIO({\n    debug: true,\n    connection: io(\"http://localhost:1111\"),\n    vuex: {}\n  })\n);\n\n```\n\nIf player leaves room, the socket.io listener will be unsubscribed to avoid the multiple same listener when web mount the same component.\n\n```\n\nbeforeRouteLeave(to, from, next) {\n   this.sockets.unsubscribe(\"recMsg\");\n   ...\n}\n\n    mounted(){\n   this.sockets.subscribe(\"recMsg\", data =\u003e {\n      this.appendMsg(`${data.userid}:${data.msg}`);\n    });\n    }\n\n```\n\n# LoginRegister\n\nLogin:\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/Login.jpg'\u003e\n\nRegistration:\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/register.jpg' alt=''\u003e\n\nFirst, I set the model to process the account info.\n\n```\n\nDataBase setting:\n\n.env:\nDB_CONNECT = your mongoDB setting\n\nserver:\n\nconst mongoose = require(\"mongoose\");\nconst dotenv = require(\"dotenv\");\n\ndotenv.config();\n\nmongoose.connect(\n  process.env.DB_CONNECT,\n  { useNewUrlParser: true, useUnifiedTopology: true },\n  () =\u003e {\n    console.log(\"connect to db\");\n  }\n);\n\n\n\n```\n\n```\nschema setting:\n\nconst userSchema = new mongoose.Schema({\n  name: {\n    type: String,\n    required: true,\n    max: 255,\n    min: 6\n  },\n  ....\n\n```\n\nExpress router configs the API router.\n\nJoi validates the info ,then byscript hashes the password.\n\n```\n\nJoi:\n  const schema = Joi.object({\n    name: Joi.string()\n      .min(6)\n      .required(),\n      ....\n      ....\n\n      return schema.validate(data);\n\nbyscript:\n  const salt = await bcrypt.genSalt(10);\n  const hashpwd = await bcrypt.hash(req.body.password, salt);\n\n```\n\nIf the account email is existed when you register, system will send error message.\n\n```\n\n  const emailExist = await User.findOne({ email: req.body.email });\n  if (emailExist) {\n    return res.status(400).send(\"Email already exists\");\n  }\n\n```\n\nWhen you login, system will check the mongoDB account table.\n\n```\n\n  const user = await User.findOne({ email: req.body.email });\n  if (!user) {\n    return res.status(400).send(\"Email or password is wrong.\");\n  }\n\n    const validPass = await bcrypt.compare(req.body.password, user.password);\n  if (!validPass) {\n    return res.status(400).send(\"Invalid password\");\n  }\n\n```\n\nWhen registration examination is ok , model will help me deal with the account info, then save to mongoDB.\n\n```\n\n  const user = new User({\n    name: req.body.name,\n    email: req.body.email,\n    password: hashpwd\n  });\n\n  try {\n    const savedUser = await user.save();\n    res.send(user._id);\n  } catch (err) {\n    res.status(400).send(err);\n  }\n\n```\n\nWhen you login, system will authorize and send token and userid.\n\n```\n  const username = user.name;\n  const token = jwt.sign({ _id: user.id }, process.env.TOKEN_SECRET);\n  res\n    .header(\"auth-token\", { token: token, userid: username })\n    .send({ token: token, userid: username });\n\n\n```\n\nVuex manage the statement, including the authorization info.\n\nThis is state, mutations settings.\n\nIf you are interested in actions settings or detail statement info, you can get from store.js.\n\n```\n\n state:\n    token: localStorage.getItem(\"token\") || null,\n    userid: localStorage.getItem(\"userid\") || null,\n    type: \"\",\n    error: null\n\n  mutations:\n    Auth_Start(state)\n    ...,\n    Auth_Success(state, token, userid)\n    ...,\n    Auth_Fail(state)\n    ...,\n    Auth_Logout(state)\n    ...,\n\n  actions:\n    login({ commit }, user)\n    ...\n    ... ,\n    register({ commit }, user)\n    ...\n    ... ,\n    logout({ commit })\n    ...\n    ... ,\n\n```\n\n# 啟動\n\n## 前端\n\nVue/Vuex 開發。\n\n請先安裝 Node 與 Npm。\n\n並輸入下面的指令安裝 modules。\n\n```\n$ npm install\n```\n\n啟動伺服器\n\n```\n$ npm run serve\n```\n\n預設 Port 為 8080，位於 localhost。\n\n此外也可以經由 Build 使用打包後的版本。\n\n## 後端\n\nNode/Express 開發。\n\n安裝所需 modules。\n\n```\n$ npm install\n```\n\n安裝完成後，啟動伺服器 Server。\n\n```\n$ npm run start\n```\n\n# 簡介\n\n這是一個線上西洋棋網站，玩家可以在網路上與其他人進行即時對戰。\n\n前端使用 Vue 來處理，使用 Router 設定路由，搭配棋子移動與棋子繪製的模塊，使用 Socket.io 來傳遞即時資料等，讓雙方玩家可以享受即時對戰的樂趣。\n\n後端則是會處理接受到的資訊，登入註冊方面設定 model 以及 API，連接 mongoDB 並儲存，\n\n首頁可以張貼一些相關公告。\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/Home.jpg' alt=''\u003e\n\n# 遊戲房間\n\n使用者登入後可以進入房間與其他玩家遊玩，而且可以與其他玩家聊天。\n\n所以要先從房間清單，尋找自己想玩的房間並加入。\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/room.jpg' alt=''\u003e\n\n如果房間並未存在，玩家會自動彈出，重新尋找房間。\n\n如果房間人數已達兩人，第三個進去的玩家會被系統彈出，請重新尋找房間。\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/roomfull.jpg' alt=''\u003e\n\n當然，如果您未登入，將無法進行遊玩。\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/beforeLogin.jpg' alt=''\u003e\n\n進入房間時，socket.io 會發送 Vuex 儲存的帳號名稱，和房間名稱，讓伺服器知道是誰進入了這個房間。\n\n進入房間後，棋盤功能會被鎖定，直到有其他玩家加入，在下棋過程中如果不是你的回合，有人離開房間，或是勝利了，功能亦會被鎖定，而後兩者會將棋盤重置。\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/game.jpg' alt=''\u003e\n\n```\nrace setting:\n\n    turn: true,       true:white turn false: black turn\n    gamewatching: true      true:can move piece\n\n```\n\n```\n\nsocket server:\n\n  socket.on(\"sendMsg\", (msg, userid, roomName) =\u003e {\n    socket.to(roomName).emit(\"recMsg\", { msg, userid });\n  });\n  ....\n\nsocket client:\n      this.$socket.emit(\"sendMsg\", this.msgInput, this.userid, this.roomName);\n\n```\n\n```\n\nVue socket.io setting:\n\nimport VueSocketIO from \"vue-socket.io\";\nimport io from \"socket.io-client\";\n\nVue.use(\n  new VueSocketIO({\n    debug: true,\n    connection: io(\"http://localhost:1111\"),\n    vuex: {}\n  })\n);\n\n```\n\n而當玩家離開房間時，會 unsubscribe socket 的監聽器，以免引發效能以及 SPA 多個監聽器等問題。\n\n```\n\nbeforeRouteLeave(to, from, next) {\n   this.sockets.unsubscribe(\"recMsg\");\n   ...\n}\n\n    mounted(){\n   this.sockets.subscribe(\"recMsg\", data =\u003e {\n      this.appendMsg(`${data.userid}:${data.msg}`);\n    });\n    }\n\n```\n\n# 登入註冊\n\n登入頁面:\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/Login.jpg'\u003e\n\n註冊頁面:\n\n\u003cimg src='https://raw.githubusercontent.com/tsen1220/VueNodeOnlineXChess/master/introimg/register.jpg' alt=''\u003e\n\n基本上這兩個原理是相同的，首先會設定 model，來處理相關資訊。\n\n```\n\nDataBase setting:\n\n.env:\nDB_CONNECT = your mongoDB setting\n\nserver:\n\nconst mongoose = require(\"mongoose\");\nconst dotenv = require(\"dotenv\");\n\ndotenv.config();\n\nmongoose.connect(\n  process.env.DB_CONNECT,\n  { useNewUrlParser: true, useUnifiedTopology: true },\n  () =\u003e {\n    console.log(\"connect to db\");\n  }\n);\n\n\n\n```\n\n```\nschema setting:\n\nconst userSchema = new mongoose.Schema({\n  name: {\n    type: String,\n    required: true,\n    max: 255,\n    min: 6\n  },\n  ....\n\n```\n\n之後使用 Express Router 設定 API 的相關路由。\n\n再來使用設定好的 model schema，搭配 Joi 檢查 Post 的資訊符不符合設定標準、由 byscript 來 hash 我們的密碼。\n\n```\n\nJoi:\n  const schema = Joi.object({\n    name: Joi.string()\n      .min(6)\n      .required(),\n      ....\n      ....\n\n      return schema.validate(data);\n\nbyscript:\n  const salt = await bcrypt.genSalt(10);\n  const hashpwd = await bcrypt.hash(req.body.password, salt);\n\n```\n\n註冊時會先檢查帳號是否已存在。\n\n```\n\n  const emailExist = await User.findOne({ email: req.body.email });\n  if (emailExist) {\n    return res.status(400).send(\"Email already exists\");\n  }\n\n```\n\n而登入時會檢查帳號與密碼是否相符。\n\n```\n\n  const user = await User.findOne({ email: req.body.email });\n  if (!user) {\n    return res.status(400).send(\"Email or password is wrong.\");\n  }\n\n    const validPass = await bcrypt.compare(req.body.password, user.password);\n  if (!validPass) {\n    return res.status(400).send(\"Invalid password\");\n  }\n\n```\n\n註冊方面確定都沒問題會依照 Schema 將資料放置於 mongoDB 內。\n\n```\n\n  const user = new User({\n    name: req.body.name,\n    email: req.body.email,\n    password: hashpwd\n  });\n\n  try {\n    const savedUser = await user.save();\n    res.send(user._id);\n  } catch (err) {\n    res.status(400).send(err);\n  }\n\n```\n\n登入成功則會給予 token，使用 jwt，並回傳 token 與 userid。\n\n```\n  const username = user.name;\n  const token = jwt.sign({ _id: user.id }, process.env.TOKEN_SECRET);\n  res\n    .header(\"auth-token\", { token: token, userid: username })\n    .send({ token: token, userid: username });\n\n\n```\n\n而傳到前端的資訊會由 Vuex 進行狀態管理，登入註冊的觸發細節位於 actions，在此為一些基本設定。\n\n```\n state:\n    token: localStorage.getItem(\"token\") || null,\n    userid: localStorage.getItem(\"userid\") || null,\n    type: \"\",\n    error: null\n\n  mutations:\n    Auth_Start(state)\n    ...,\n    Auth_Success(state, token, userid)\n    ...,\n    Auth_Fail(state)\n    ...,\n    Auth_Logout(state)\n    ...,\n\n  actions:\n    login({ commit }, user)\n    ...\n    ... ,\n    register({ commit }, user)\n    ...\n    ... ,\n    logout({ commit })\n    ...\n    ... ,\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzients%2Fvue-node-online-chess","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzients%2Fvue-node-online-chess","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzients%2Fvue-node-online-chess/lists"}