{"id":27958984,"url":"https://github.com/yxuco/vue-nft-delivery","last_synced_at":"2026-05-09T04:31:15.727Z","repository":{"id":96633971,"uuid":"468175333","full_name":"yxuco/vue-nft-delivery","owner":"yxuco","description":"An web3 app using Vue.js and Node.js to authenticate Ethereum user and verify NFT ownership.","archived":false,"fork":false,"pushed_at":"2022-03-10T22:30:28.000Z","size":365,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T18:37:03.127Z","etag":null,"topics":["nft","nodejs","signature","tutorial","vuejs","web3"],"latest_commit_sha":null,"homepage":"","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/yxuco.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,"zenodo":null}},"created_at":"2022-03-10T03:08:16.000Z","updated_at":"2022-03-10T23:37:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"64432cd2-1ae8-47a5-a26d-5eb4c984d46c","html_url":"https://github.com/yxuco/vue-nft-delivery","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yxuco/vue-nft-delivery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yxuco%2Fvue-nft-delivery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yxuco%2Fvue-nft-delivery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yxuco%2Fvue-nft-delivery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yxuco%2Fvue-nft-delivery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yxuco","download_url":"https://codeload.github.com/yxuco/vue-nft-delivery/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yxuco%2Fvue-nft-delivery/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32807147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"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":["nft","nodejs","signature","tutorial","vuejs","web3"],"created_at":"2025-05-07T18:27:15.228Z","updated_at":"2026-05-09T04:31:15.715Z","avatar_url":"https://github.com/yxuco.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NFT Token Ownership Verification with Vue.js and Node.js\n\nThis project uses an [NFT](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/) usecase to illustrate how to implement a Web3 application from scratch.\n\nWe choose to use the [Express](https://expressjs.com/) Node.js application framework to implement the backend API service, and [Vue.js](https://vuejs.org/) JavaScript framework to implement the web user interface.\n\nThe application can verify that a crypto wallet owner really owns a specified NFT token.  In the application's web UI, a user can enter an NFT contract address and a token ID to be verified.  The UI will send a message signing request to the user's wallet plugin (assuming that user is logged in to a MetaMask Chrome plugin), and prompt the user to sign a message containing the NFT contract address and token ID.  After the user signs the message by using the private key in the wallet, the signature will be sent to a backend API service for verification.  The API service will extract the signer's public address from the signature, and query the blockchain to retrieve the owner of the specified NFT token, and then return both the verified signer's address and the token owner's address.  If these 2 addresses match, it proves that wallet owner must be the current owner of the specified NFT token.\n\n## Prerequisite \n\n### Install Node.js\n\nI use `zsh` on a Mac, and installed `Node.js` by using [nvm](https://github.com/nvm-sh/nvm#installing-and-updating) i.e.,\n\n```sh\ntouch ~/.zshrc\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash\nnvm install node\n```\n\nVerify that `Node.js` and `npm` are installed correctly, i.e.,\n\n```sh\nnvm -v\nnpm -v\nnode -v\n```\n\n### Configuration\n\nInstall MetaMask plugin for Chrome from [here](https://metamask.io/download/), and then create an account if you do not already have a wallet.\n\nCreate an account at [infura.io](https://infura.io/), and then create an Ethereum project.  Copy the endpoint URL for the `rinkeby` test network, and use the URL in the API server configuration file, [api/config.json](./api/config.json).\n\n## Start the application as is\n\nFor development by default, this application will start a backend API server on port `3070`, and a Vue web UI proxy on port `8082`.  You can start these processes in separate terminals as follows.\n\n```sh\n# start the Node.js API server on port 3070\ncd api\nnpm install\nnpm run dev\n\n# start the Vue.js UI proxy on port 8082\ncd nft-app\nnpm install\nnpm run serve\n```\n\nView the web UI in a Chrome browser at http://localhost:8082/. Login to your wallet in MetaMask browser plugin.  In the web UI, enter a Token ID of `1` through `4`, and select an NFT contract, then click the `Sign` button to see the verification result, which should look like the following:\n\n![Verify Signature](verify.png)\n\n## Implement the API service from scratch\n\nIn an empty project folder, e.g., `~/jsprojects/vue-nft-delivery`, create a JavaScript project from scratch, i.e,\n\n```sh\nmkdir api -P \u0026\u0026 cd api\nnpm init\n```\n\nEnter the following parameters when prompted by the command `npm init`:\n\n```\npackage name: (api)\nversion: (1.0.0)\ndescription: backend for nft-delivery\nentry point: (index.js) server.js\ntest command: test\ngit repository: https://github.com/johndoe/vue-nft-delivery\nkeywords: nft\nauthor: John Doe\nlicense: (ISC)\n```\n\nThis will create a file [package.json](./api/package.json), which you can edit if you want to change any of the parameters.\n\nWe use the [Express](https://expressjs.com/) framework to implement backend service APIs.  Besides, for convenience during the development, we use [nodemon](https://nodemon.io/) to restart the API server automatically whenever the code is updated.  So, add these dependencies for runtime and dev-only.\n\n```sh\nnpm install --save express\nnpm install --save-dev nodemon\n```\n\nThe service APIs will use [ethers.js](https://docs.ethers.io/v5/) to verify message signature, and use [web3.js](https://web3js.readthedocs.io/en/v1.7.1/) to connect to an Ethereum node and call smart contract methods.  For development, we use [webpack](https://webpack.js.org/) to build production bundle of the application scripts and assets.  So add these dependencies as well.\n\n```sh\nnpm install --save ethers web3\nnpm install --save-dev webpack webpack-cli\n```\n\nWe are now ready to write the API code.  All APIs are implemented in [server.js](./api/server.js).  If you are not familiar with the `express` framework, you may find the references at the end of this doc helpful.\n\nThe `server.js` implements 2 APIs:\n\n* `/api/contracts` will return a list of pre-configured NFT contracts whose tokens can be verified by this application.\n* `/api/verify` will verify the user's signature of a NFT token ID, and retrieve the owner of a specified NFT token from an Ethereum node.\n\nIt also uses [express.static](https://expressjs.com/en/starter/static-files.html) to serve static web content in a `/public` folder, as well as the application bundle of the web UI in `/nft-app`, which we'll implement in the next section.\n\nDuring the development, the API server will listen on an HTTP port, but for production build, we should change it to use HTTPS.\n\nThe configuration parameters are read from the file [config.json](./api/config.json), which includes\n\n* `port` is the API server's listen port.\n* `infura` is the URL of Ethereum node in [infura](https://infura.io/).  You can create a free account in `infura`, and then create a project, and copy the project's endpoint for the Ethereum network where your NFT is minted and/or traded.\n* `contracts` is a list of NFT contracts to be handled by this application.  The sample entries list 2 NFT contracts that I created on the `rinkeby` test network.  This list will be displayed as a selection list on the web UI that we'll implement in the next section.  If you are interested in how to create such NFT contracts from scratch, refer to the [Sample NFT](https://github.com/yxuco/enft) project.\n\nThe API `/api/verify` uses the contract ABI of the standard ERC-721 specification to fetch the owner address of a specified token.  Thus, we store a copy of the ABI definition in [erc721.json](./api/erc721.json).\n\nCreate [webpack.config.js](./api/webpack.config.js) for production bundle.  Note that we'll build the production bundle to a parent `../dist` folder where we can add the web UI bundle later.  We also added a rule to avoid the build error `Can't resolve 'electron'` for `web3.js`.\n\nEdit the scripts in [package.json](./api/package.json) for development and production.  The production `start` script assumes that the application bundle is produced in the parent `../dist` folder.  \n\nStart the API server using command `npm run dev`, which uses `nodemon` to watch files, and so the API server will automatically restart whenever the code is updated.\n\nVerify the API server by sending a request from another terminal: `curl http://localhost:3070/api/contracts`.\n\nBuild the production bundle using command `npm run build`.  Start the production server using command `npm run start`.\n\n## Implement the Vue web UI from scratch\n\nIn the project folder, e.g., `~/jsprojects/vue-nft-delivery`, create a `Vue.js` project named `nft-app`:\n\n```sh\n# install Vue CLI globally if it is not done already\nnpm install -g @vue/cli\n\n# create new project\nvue create nft-app\n```\n\nWe use the [Bootstrap Vue 3](https://www.npmjs.com/package/bootstrap-vue-3) framework to build responsive web UI.  It uses `BootstrapVue` web components as described [here](https://bootstrap-vue.org/docs/components), and `Bootstrap` CSS classes as described [here](https://getbootstrap.com/docs/5.1/utilities/api/).\n\nThe web UI uses [ethers.js](https://docs.ethers.io/v5/) to sign messages, and uses [axios](https://axios-http.com/docs/intro) to call backend APIs over HTTP/HTTPS.  So add these dependencies:\n\n```sh\ncd nft-app\n\n# dependencies for message signature and verification\nnpm install --save axios ethers\n\n# dependencies for UI components and css classes\nnpm install --save bootstrap bootstrap-vue-3\n```\n\nWe are now ready to write code for the web UI. If you are not familiar with the `vue.js` or `bootstrap-vue` framework, you may find the references at the end of this doc helpful.\n\nEdit the scripts in [package.json](./nft-app/package.json) to make it `serve` on port `8082`.\n\nEdit the configuration file [vue.config.js](./nft-app/vue.config.js) to specify the URL of the backend API server as specified in the previous section, i.e., http://localhost:3070.  It also specifies the output folder for production bundle, which we'll build later in this section.\n\nEdit the file [main.js](./nft-app/src/main.js) to register `bootstrap-vue`, so it will be available for all the application components.\n\nThe file [SigService.js](./nft-app/src/services/SigService.js) implements service functions for the UI to interact with MetaMask wallet for signature calculation, and to call backend service APIs.\n\nThe only Vue.js UI component for this application is implemented in [SignMessage.vue](./nft-app/src/components/SignMessage.vue).  When the component is loaded, it calls the backend API `/api/contracts` and uses the returned result to initialize the NFT contract selection list.  When the user clicks the `Sign` button, it send a request to MetaMask wallet where the user can sign a message by using the private key in the wallet.  When the signature is updated, a watcher method will pick the updated signature and call the backend API `/api/verify`, and then display the verification result.  When HTTPS transport is used by the backend API server, this approach could be a reliable mechanism for web3 user authentication.  For even better security, however, we may add a step to request a random `nounce` from the backend server, and so the user will sign a dynamically generated random message, instead of a static NFT token ID.\n\nEdit the root component [App.vue](./nft-app/src/App.vue) to include the `SignMessage` as a child component under the root.\n\nNote that the file [.eslintrc.js](./nft-app/src/components/.eslintrc.js) contains an `ESLint` rule to disable the syntax check for `multi-word-component-names`, and so component names do not have to use multiple words.  It is not necessary for this project because the only component of the project, `SignMessage` contains 2 words.  However, if you add a component with a single-word name, e.g., `Header`, you will see a compilation error:\n\n```\nerror  Component name \"Header\" should always be multi-word  vue/multi-word-component-names\n```\n\nThe additional ESLint rule  in [.eslintrc.js](./nft-app/src/components/.eslintrc.js) would be necessary to override the default behavior.\n\nStart the web UI proxy server by using the following command.  It'll pick up code changes automatically, and thus you do not have to restart it during development.\n\n```sh\ncd nft-app\nnpm run serve\n```\n\nView the web UI in a Chrome browser at http://localhost:8082/, and start testing.\n\n## Build production bundle\n\nFor production, we can build the applicaton bundle to the same `../dist` folder and so the same `Node.js` server will serve both the API service and the web UI, as well as other static content in a `public` folder.  As described in the API service implementation [server.js](./api/server.js), the API server bundle will be output to the root of `../dist`, and the web UI bundle will be output to the sub-folder `../dist/nft-app`.  The following scripts will perform the build tasks.\n\n```sh\ncd ../api\nnpm run build\n\ncd ../nft-app\nnpm run build\n```\n\nStart the production application server using the following command.\n\n```sh\ncd ../dist\nnode serer.bundle.js\n```\n\nView the web UI in a Chrome browser at http://localhost:3070/. Login to your wallet in MetaMask browser plugin.  In the web UI, enter a Token ID of `1` through `4`, and select an NFT contract, then click the `Sign` button to see the verification result.\n\nYou can add any other static HTML pages, such as sample files under [/public](./api/public/) to the folder `../dist/public`, and so they can be viewed at http://localhost:3070/public.\n\nIf you update the server port and/or other configuration parameters in [config.json](./api/config.json), you'll have to rebuild the production bundles, and then restart the `Node.js` server.\n\n## References\n\n* [Node.js Express Tutorial](https://www.digitalocean.com/community/tutorials/nodejs-express-basics)\n* [Setup HTTPS for Express Server](https://adamtheautomator.com/https-nodejs/)\n* [Express API Reference](https://expressjs.com/en/5x/api.html)\n* [Webpack Tutorial](https://dev.to/antonmelnyk/how-to-configure-webpack-from-scratch-for-a-basic-website-46a5)\n* [Web3 Call Smart Contract](https://ethereum.org/en/developers/tutorials/calling-a-smart-contract-from-javascript/)\n* [Web3.js API Reference](https://web3js.readthedocs.io/en/v1.7.1/web3.html#setprovider)\n* [BootstrapVue Tutorial](https://blog.logrocket.com/getting-started-with-bootstrapvue-2d8bf907ef11/)\n* [Bootstrap css Reference](https://getbootstrap.com/docs/5.1/utilities/api/)\n* [BootstrapVue Component Reference](https://bootstrap-vue.org/docs/components)\n* [Web Application with Node.js and Vue](https://levelup.gitconnected.com/vue-node-web-application-59d3376e403e)\n* [Vue.js and Node.js Example](https://github.com/bbachi/vuejs-nodejs-example.git)\n* [Ethers MetaMask Message Signature](https://codesandbox.io/s/react-eth-metamask-signatures-ibuxj)\n* [Write mobile web3 crypto apps on iOS and Android](https://nickconfrey.medium.com/how-to-write-mobile-web3-crypto-apps-on-ios-and-android-3c0854e2110f)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyxuco%2Fvue-nft-delivery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyxuco%2Fvue-nft-delivery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyxuco%2Fvue-nft-delivery/lists"}