# Node Tutorial - Part 2: Project Graph Run the command: `npx nx graph`. A browser should open up with the following contents: ![Initial Project Graph](/shared/node-tutorial/initial-project-graph.png) This is still different from the design from the start of Part 1: ![Our Workspace Requirements](/shared/node-tutorial/requirements-diagram.svg) The Project Graph is derived from the source code of your workspace. Make the following adjustments to your existing projects, so that our Project Graph will match the design: ### `products-data-client` Update the contents of the generated `products-data-client.ts` file: ```typescript {% fileName="libs/products-data-client/src/lib/products-data-client.ts" %} export interface Product { id: string; name: string; price: number; } export interface ProductsDataClient { getProducts(): Promise; getProductById(id: string): Promise; } export const exampleProducts: Record = { '1': { id: '1', name: 'Product 1', price: 100 }, '2': { id: '2', name: 'Product 2', price: 200 }, }; export function createProductsDataClient(): ProductsDataClient { return { getProducts() { return Promise.resolve(Object.values(exampleProducts)); }, getProductById(id) { return Promise.resolve(exampleProducts[id]); }, }; } ``` ### `products-cli` Update the generated `main.ts` file of this project to import the `createProductsDataClient()` function. Use the data client to print the product matching the id provided at the command-line. If no id was provided, print all products as an array: ```typescript {% fileName="apps/products-cli/src/main.ts" %} import { createProductsDataClient } from '@my-products/products-data-client'; main(); async function main() { const productsDataClient = createProductsDataClient(); const id = getProvidedId(); if (id != null) { const product = await productsDataClient.getProductById(id); console.log(JSON.stringify(product, null, 2)); } else { const products = await productsDataClient.getProducts(); console.log(JSON.stringify(products, null, 2)); } } function getProvidedId() { return process.argv[2]; } ``` ### `products-api` Update the generated `main.ts` file of this project to also import the `createProductsDataClient()` function. Use the data client and Express to create an Express app with 2 GET request handlers: ```javascript {% fileName="apps/products-api/src/main.ts" %} /** * This is not a production server yet! * This is only a minimal backend to get started. */ import * as express from 'express'; import { createProductsDataClient } from '@my-products/products-data-client'; const app = express(); const productsDataClient = createProductsDataClient(); app.get('/products', async (_req, res) => { const products = await productsDataClient.getProducts(); res.send(products); }); app.get('/products/:id', async (req, res) => { const id = req.params.id; const product = await productsDataClient.getProductById(id); if (product == null) { res.status(404).send(); return; } res.send(product); }); const port = process.env.port || 3333; const server = app.listen(port, () => { console.log(`Listening at http://localhost:${port}`); }); server.on('error', console.error); ``` Now run `npx nx graph` again: {% side-by-side %} ![Matching Graph](/shared/node-tutorial/matching-graph.png) ![Our Workspace Requirements](/shared/node-tutorial/requirements-diagram.svg) {% /side-by-side %} Your graph now matches the original design. The Project Graph is more than just a visualization - Nx provides tooling to optimize your task-running and even automate your CI based on this graph. This will be covered in more detail in: [4: Workspace Optimization](/node-tutorial/4-workspace-optimization). ## What's Next - Continue to [3: Task Running](/node-tutorial/3-task-running)