> For the complete documentation index, see [llms.txt](https://docs.empe.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.empe.io/getting-started/tutorial/project-setup.md).

# Project Setup

**What We Are Doing:**

* Initializing a Node.js/Express project.
* Installing a minimal set of dependencies.
* Preparing the base structure for talking to the Issuer and Verifier HTTP API.

**Why:** We need a backend server that:

* Calls the Issuer API to create credential offers.
* Calls the Verifier API to create authorization (presentation) requests and check results.
* Serves a small frontend for user input and QR code display.

The Issuer and Verifier are exposed as a plain HTTP API (issuance follows OpenID4VCI, verification follows OpenID4VP). Our app speaks to the API directly with the built-in `fetch`, sending a standard OIDC Bearer token on every request — no client library is needed. That keeps the dependency list small: an HTTP server, an env loader, and a JWT helper.

**Steps:**

1. Create a new directory and initialize a Node.js project:

```bash
    mkdir -p evdi-tutorial/{src,public} && \
    touch evdi-tutorial/src/{index.js,issuer-routes.js,verifier-routes.js,verification-flows.js,authorization-routes.js} \
      evdi-tutorial/public/{index.html,dashboard.html} \
      evdi-tutorial/.env
    cd evdi-tutorial
    npm init -y
    npm pkg set type=module
```

The `npm pkg set type=module` step marks the package as an ES module — all the code in this tutorial uses `import`/`export` syntax, which Node.js only accepts in `.js` files when `package.json` contains `"type": "module"`.

Project structure:

```
 evdi-tutorial/
   src/
     index.js                 # Express app entrypoint
     issuer-routes.js         # routes that call the Issuer API
     verifier-routes.js       # routes that call the Verifier API
     verification-flows.js    # the "kyc" verification flow + app-token helper
     authorization-routes.js  # session-token decode + protected dashboard routes
   public/
     index.html               # issuance page (shows the offer QR)
     dashboard.html           # protected page shown after verification
   .env
```

2. Install dependencies:

```bash
 npm install express dotenv jsonwebtoken
```

* **express** — runs our backend and serves the frontend pages.
* **dotenv** — loads the Issuer/Verifier URLs and token from `.env`.
* **jsonwebtoken** — signs and verifies our own short-lived app session token (used later to gate the protected dashboard).

We use the built-in `fetch` for HTTP calls (available in Node.js 18+), so no extra HTTP client is needed.

3. Add the API configuration to your `.env` file. The app authenticates to the Issuer and Verifier with an OIDC access token (an admin Bearer token from the deployment's Keycloak) sent as `Authorization: Bearer <token>`, so we store the base URLs and the per-service tokens here:

```
# Base URLs of the deployed Issuer and Verifier
ISSUER_BASE_URL=https://your-issuer.evdi.app
VERIFIER_BASE_URL=https://your-deployment.evdi.app

# Admin access tokens (Bearer/JWT) sent as: Authorization: Bearer <token>
ISSUER_ACCESS_TOKEN=your-oidc-access-token
VERIFIER_ACCESS_TOKEN=your-oidc-access-token

# Secret our app uses to sign its own short-lived session tokens
# (any long random string; used by the dashboard flow later in the tutorial)
JWT_SECRET=replace-with-a-long-random-string

# Port our tutorial app listens on
PORT=4000
```

These values are accessible in your code as `process.env.ISSUER_BASE_URL`, `process.env.VERIFIER_BASE_URL`, `process.env.ISSUER_ACCESS_TOKEN`, and `process.env.VERIFIER_ACCESS_TOKEN`. We will obtain the access tokens and fill in the base URLs in the next steps, when we create the Issuer and Verifier. Next, we will look at how authentication works — the OIDC Bearer token that every request in this tutorial carries.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.empe.io/getting-started/tutorial/project-setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
