{"id":14967642,"url":"https://github.com/zhukovsd/typing-test","last_synced_at":"2025-09-06T04:40:59.428Z","repository":{"id":92040740,"uuid":"130485535","full_name":"zhukovsd/typing-test","owner":"zhukovsd","description":"Full-stack hobby project built with microservices","archived":false,"fork":false,"pushed_at":"2019-01-06T15:14:16.000Z","size":213,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-07T10:11:21.285Z","etag":null,"topics":["circleci","docker","docker-swarm","es6","kotlin","maven","pugjs","spring","webpack"],"latest_commit_sha":null,"homepage":"http://typing-test.zhukovsd.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zhukovsd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-21T15:15:25.000Z","updated_at":"2024-01-21T11:28:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"9abc4dd9-de25-42c0-87f3-3d94fb040b4d","html_url":"https://github.com/zhukovsd/typing-test","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zhukovsd/typing-test","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhukovsd%2Ftyping-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhukovsd%2Ftyping-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhukovsd%2Ftyping-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhukovsd%2Ftyping-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zhukovsd","download_url":"https://codeload.github.com/zhukovsd/typing-test/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhukovsd%2Ftyping-test/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273858851,"owners_count":25180766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["circleci","docker","docker-swarm","es6","kotlin","maven","pugjs","spring","webpack"],"created_at":"2024-09-24T13:38:23.824Z","updated_at":"2025-09-06T04:40:59.388Z","avatar_url":"https://github.com/zhukovsd.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n## Project overview\n\nThe app built from production branch runs here - [88.99.12.213](http://88.99.12.213/)\n\ntyping-test is a hobby project. It is a simple 1-minute typing speed test with frontend built with ES6/Pug.js. Each test result gets submitted to the backend (built with Kotlin/Spring) which responds with player's placement and stores typing speed characteristics (characters per minute, typos count) to the persistent Redis DB.\n\nThe primary motivation behind the project is to learn new technologies and approaches, such as microservices, and apply them to the project which is not too hard, so I won't be stuck into solving unnecessarily complicated things, and not too easy, so the acquired experience will be relevant for the future projects.\n\nApplied technologies, languages and tools: Kotlin, Spring, Maven, ES6, Pug.js, Webpack, CircleCI, Docker, Docker Swarm.\n\n## Run it locally\n- clone the repo\n- `docker-compose -f docker-compose-dev.yml up` to start an instance of the app\n- open the app by accessing `localhost` in your web browser, if you use run Docker on Linux or Docker for Windows, or `192.168.99.100` (replace with an IP of your Docker machine) if you use Docker Toolbox\n\n## Architecture overview\n\nThe app contains [two microservices](https://github.com/zhukovsd/typing-test/blob/master/stack.template.yml), the first one encapsulates Tomcat, which runs Spring application. The second microservice runs Redis instance.\n\nThe primary building and dependency management tool is Maven. Is assembles a WAR (web archive) with the Spring app, which includes Frontend resources an exposes them to the root context path of the running application.\n\nDuring building, Maven (config - [pom.xml](https://github.com/zhukovsd/typing-test/blob/master/pom.xml)) executes Webpack to build the frontend app by running an [npm script](https://github.com/zhukovsd/typing-test/blob/master/frontend/package.json#L10).\n\n[Webpack config](https://github.com/zhukovsd/typing-test/blob/master/frontend/webpack.common.js) defines a number of steps:\n- Transpile ES6 to ES5 with Babel, combine application code and vendor code to the output bundled Javascript file (minify for the production build, include source maps for the dev build)\n- Compile Pug templates to HTML\n- Bundle CSS (minify for the production build, include source maps for the dev build)\n- Enable versioning for JS and CSS assets by calculating output file hashes on each build. Hash changes only when the content of the file changes so that clients can cache web assets\n\nMicroservices run in Docker containers, which orchestrated by docker-compose (locally) or Docker Swarm (in production). Spring application wrapped into Docker image ([Dockerfile](https://github.com/zhukovsd/typing-test/blob/master/Dockerfile)) based on `tomcat:8-jre8` image.\n\nRedis microservice is also defined by a custom Docker image ([Dockerfile](https://github.com/zhukovsd/typing-test/blob/master/redis-docker-image/Dockerfile)), which enables persistent storage and allows to mount a Docker volume to the Redis data directory.\n\nThis project has plenty of things to automate with a CI tool. I chose [CircleCI](https://circleci.com/) due to its native and deep integration with Docker - ability to run CI runners in containers created from custom images, and ability to easily [run Docker commands](https://circleci.com/docs/2.0/building-docker-images/) (for example, `stack deploy` or `image push`) by creating a separate environment with access to Docker Host and CLI.\n\nCI defines multiple steps to build and deploy the project ([ci config](https://github.com/zhukovsd/typing-test/blob/master/.circleci/config.yml)). Git branch name defines which steps to run.\n- Build the project with Maven (which internally runs Webpack for the frontend)\n- Build and push a Docker image for Tomcat microservice (this microservice runs the compiled Spring app)\n- Refresh production Docker Swarm stack by remote execution of `docker stack deploy`\n\nLog of jobs executed on CircleCI - https://circleci.com/gh/zhukovsd/typing-test","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhukovsd%2Ftyping-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzhukovsd%2Ftyping-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhukovsd%2Ftyping-test/lists"}