{"id":30375515,"url":"https://github.com/hackardox/x-borg","last_synced_at":"2025-08-20T12:14:49.093Z","repository":{"id":240859769,"uuid":"627860204","full_name":"hackardoX/x-borg","owner":"hackardoX","description":null,"archived":false,"fork":false,"pushed_at":"2023-04-21T12:37:05.000Z","size":330,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-16T08:41:17.587Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://x-borg.vercel.app","language":"TypeScript","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/hackardoX.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-14T11:08:44.000Z","updated_at":"2023-04-20T13:49:06.000Z","dependencies_parsed_at":"2024-05-21T06:12:19.647Z","dependency_job_id":"1a519235-066f-40d8-8369-f2b7df4fd915","html_url":"https://github.com/hackardoX/x-borg","commit_stats":null,"previous_names":["andrea11/x-borg","hackardox/x-borg"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hackardoX/x-borg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackardoX%2Fx-borg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackardoX%2Fx-borg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackardoX%2Fx-borg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackardoX%2Fx-borg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hackardoX","download_url":"https://codeload.github.com/hackardoX/x-borg/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hackardoX%2Fx-borg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271314526,"owners_count":24738188,"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-08-20T02:00:09.606Z","response_time":69,"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":[],"created_at":"2025-08-20T12:14:43.531Z","updated_at":"2025-08-20T12:14:49.007Z","avatar_url":"https://github.com/hackardoX.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# X-Borg Task\n\n- [Tech Challenge: Implementing Authentication Flow with Metamask, PostgreSQL, and Front-End](#tech-challenge--implementing-authentication-flow-with-metamask--postgresql--and-front-end)\n    + [Objective](#objective-)\n    + [Requirements](#requirements-)\n    + [Instructions](#instructions-)\n    + [Technical Details](#technical-details-)\n    + [Evaluation Criteria](#evaluation-criteria-)\n        * [Relevant documentation](#relevant-documentation-)\n- [Solution description](#solution-description)\n    + [Architecture](#architecture)\n        * [Contracts](#contracts)\n        * [Database](#database)\n        * [Frontend](#frontend)\n        * [Backend](#backend)\n            + [Authentication flow](#authentication-flow)\n            + [User details flow](#user-details-flow)\n    + [Getting started](#getting-started)\n        * [General](#general)\n            + [Testing](#testing)\n        * [Docker](#docker)\n        * [Local development](#local-development)\n            + [Backend](#backend-1)\n                * [Testing](#testing-1)\n            + [Frontend](#frontend-1)\n                * [Testing](#testing-2)\n- [Demo](#demo)\n\n\u003csmall\u003e\u003ci\u003e\u003ca href='http://ecotrust-canada.github.io/markdown-toc/'\u003eTable of contents generated with\n          markdown-toc\u003c/a\u003e\u003c/i\u003e\u003c/small\u003e\n\n## Tech Challenge: Implementing Authentication Flow with Metamask, PostgreSQL, and Front-End\n\n### Objective:\n\nTo build an authentication flow that allows a user to authenticate with their Metamask wallet and store the user's\ndetails in a PostgreSQL database using wallet signature.\n\n#### Requirements:\n\nKnowledge of Metamask, PostgreSQL, and front-end technologies (HTML, CSS, and JavaScript)\nExperience with backend development and RESTful APIs\n\n#### Instructions:\n\nBuild a backend RESTful API that supports two endpoints: POST /auth and GET /user.\nThe POST /auth endpoint should accept a wallet signature from Metamask and authenticate the user.\nAfter authentication, store the user's details (e.g., public address) in a PostgreSQL database.\nThe GET /user endpoint should return the user's details from the database.\nBuild a front-end interface that allows the user to initiate the authentication process and display the user's details\nafter authentication.\n\n#### Technical Details:\n\nUse Metamask to sign messages for authentication. You can use the web3 library to interact with Metamask.\nUse a PostgreSQL database to store the user's details (e.g., public address).\nThe backend should be built using Node.js\nThe front-end interface can be built using HTM and JavaScript or any front-end framework of your choice (Ideally\nReact.js/Next.js).\n\n##### Evaluation Criteria:\n\n- Functionality: Does the application meet the requirements outlined above?\n- Code Quality: Is the code well-organized, readable, and maintainable?\n- Security: Does the application implement security best practices for handling user authentication and storing\n  sensitive user data?\n\n##### Relevant documentation:\n\n- https://docs.metamask.io/guide/\n- https://docs.walletconnect.com/2.0\n\n## Solution description\n\n### Architecture\n\n#### Contracts\n\nI used contracts (defined thanks to ts-rest), to define the API of the backend.\nIt makes it easy to handle request and response both on the backend and frontend.\nFurthermore, it provides typescript types support.\n\n#### Database\n\nI used PostgreSQL via NeonDB. I chose NeonDB because it is a cloud\nhosted PostgreSQL database that is easy to setup and use. It also has a free tier\nthat is perfect for this project.\n\n#### Frontend\n\nNext.js is used for the frontend. Next.js is a React framework that makes it easy to\ncreate server-side rendered React applications. It also has built in support for\nserverless functions which is perfect for this project. The frontend is responsible\nfor handling the user's interaction with the application. It uses Web3 to sign\nmessages and send them to the backend for validation. It also uses prisma to\nfetch the user's details from the database.\n\n#### Backend\n\nBecause the requirement were not clear about the possibility to use a serverless function as a backend, I decided to\nimplement two backends.\nThe first backend is a serverless function provided by NextJS. It can work with Vercel, and it can be deployed on every\ncommit.\nThe second backend is a Node.js express server.\nBoth backends are responsible for handling the authentication flow and storing the user's details in the database.\nIt uses Web3 to validate the signature sent by the user and stores the user's details in the database using prisma.\n(See the [Getting started](#Getting started) section for more details)\n\n#### Authentication flow\n\nThe authentication flow is the following:\n\n1. The user clicks on the \"Login\" button\n2. The frontend shares the same hardcoded message with the backend (ideally this should be generated on the fly). \n   It sends a POST request to the /auth backend endpoint with the signature of the message\n3. The backend validates the signature and stores the user id in the database\n4. The backend reply with an empty response, and with a cookie setting up the auth token to the frontend\n\n#### User details flow\n1. Once the user is authenticated, the frontend automatically fetch the user's details by sending a GET request to the /user backend\n   endpoint.\n2. The backend fetches the user's details from the database and replies with the user's details\n3. The frontend displays the user's details\n\n### Getting started\n\n#### General\n\n1. Install dependencies\n\n```bash \nnpm install\n```\n\n2. Create a .env file (using the .env.example as template) in the root directory. You can opt for 2 values for\n   the `NEXT_PUBLIC_API_URL_ENTRYPOINT` environment variables:\n\n```bash\nNEXT_PUBLIC_API_URL_ENTRYPOINT=\"http://localhost:3000/api\" # -\u003e for the serverless backend\n# or\nNEXT_PUBLIC_API_URL_ENTRYPOINT=\"http://localhost:8000/api\" # -\u003e for the express backend\n```\n\n##### Testing\n\nYou can run the tests using the following command:\n\n```bash\nnpm run test\n```\n\n#### Docker\n\nYou can use docker to run the project. \nIt will run the express node backend, the frontend/serverless function, and the DB in 3 different containers.\nYou can still use the `NEXT_PUBLIC_API_URL_ENTRYPOINT` environment variable to choose which backend to use.\nYou can use the following command to start the project:\n\n```bash\ndocker-compose up -d\n```\n\n#### Local development\n\nFollow the instructions below to run the project locally.\n\n##### Backend\n\n1. Run the backend\n\n```bash\nnpm run build:server \u0026\u0026 npm run start:server\n```\n\n###### Testing\n\nYou can run the tests using the following command:\n\n```bash\nnpm run test:server\n```\n\n##### Frontend\n\n1. Run the frontend\n\n```bash\nnpm run build:ui \u0026\u0026 npm run start:ui\n```\n\n###### Testing\n\nYou can run the tests using the following command:\n\n```bash\nnpm run test:ui\n```\n\n## Demo\nFor a demo, please visit https://x-borg.vercel.app/","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhackardox%2Fx-borg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhackardox%2Fx-borg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhackardox%2Fx-borg/lists"}