diff --git a/node/generate-pdf/.gitignore b/node/generate-pdf/.gitignore
new file mode 100644
index 00000000..6a7d6d8e
--- /dev/null
+++ b/node/generate-pdf/.gitignore
@@ -0,0 +1,130 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+web_modules/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variable files
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+out
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+.temp
+.cache
+
+# Docusaurus cache and generated files
+.docusaurus
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+# yarn v2
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
\ No newline at end of file
diff --git a/node/generate-pdf/.prettierrc.json b/node/generate-pdf/.prettierrc.json
new file mode 100644
index 00000000..0a725205
--- /dev/null
+++ b/node/generate-pdf/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+  "trailingComma": "es5",
+  "tabWidth": 2,
+  "semi": true,
+  "singleQuote": true
+}
diff --git a/node/generate-pdf/README.md b/node/generate-pdf/README.md
new file mode 100644
index 00000000..28ef8eb0
--- /dev/null
+++ b/node/generate-pdf/README.md
@@ -0,0 +1,31 @@
+# 📄 Node.js Generate PDF Function
+
+Document containing sample invoice in PDF format
+
+## 🧰 Usage
+
+### `GET`
+
+Returns a PDF invoice
+
+No parameters required.
+
+**Response**
+
+Sample `200` Response:
+
+Returns a binary stream of the generated PDF document. The `Content-Type` of the response will be set as `application/pdf`.
+
+## ⚙️ Configuration
+
+| Setting           | Value         |
+| ----------------- | ------------- |
+| Runtime           | Node (18.0)   |
+| Entrypoint        | `src/main.js` |
+| Build Commands    | `npm install` |
+| Permissions       | `any`         |
+| Timeout (Seconds) | 15            |
+
+## 🔒 Environment Variables
+
+No environment variables required.
\ No newline at end of file
diff --git a/node/generate-pdf/package-lock.json b/node/generate-pdf/package-lock.json
new file mode 100644
index 00000000..0d2f8aad
--- /dev/null
+++ b/node/generate-pdf/package-lock.json
@@ -0,0 +1,87 @@
+{
+  "name": "generate-pdf",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "generate-pdf",
+      "version": "1.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "@faker-js/faker": "^8.0.2",
+        "pdf-lib": "^1.17.1"
+      },
+      "devDependencies": {
+        "prettier": "^3.0.0"
+      }
+    },
+    "node_modules/@faker-js/faker": {
+      "version": "8.0.2",
+      "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.2.tgz",
+      "integrity": "sha512-Uo3pGspElQW91PCvKSIAXoEgAUlRnH29sX2/p89kg7sP1m2PzCufHINd0FhTXQf6DYGiUlVncdSPa2F9wxed2A==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/fakerjs"
+        }
+      ],
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0",
+        "npm": ">=6.14.13"
+      }
+    },
+    "node_modules/@pdf-lib/standard-fonts": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
+      "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==",
+      "dependencies": {
+        "pako": "^1.0.6"
+      }
+    },
+    "node_modules/@pdf-lib/upng": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz",
+      "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==",
+      "dependencies": {
+        "pako": "^1.0.10"
+      }
+    },
+    "node_modules/pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+    },
+    "node_modules/pdf-lib": {
+      "version": "1.17.1",
+      "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz",
+      "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==",
+      "dependencies": {
+        "@pdf-lib/standard-fonts": "^1.0.0",
+        "@pdf-lib/upng": "^1.0.1",
+        "pako": "^1.0.11",
+        "tslib": "^1.11.1"
+      }
+    },
+    "node_modules/prettier": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+      "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
+      "dev": true,
+      "bin": {
+        "prettier": "bin/prettier.cjs"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/prettier/prettier?sponsor=1"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+    }
+  }
+}
diff --git a/node/generate-pdf/package.json b/node/generate-pdf/package.json
new file mode 100644
index 00000000..a63d8f96
--- /dev/null
+++ b/node/generate-pdf/package.json
@@ -0,0 +1,17 @@
+{
+  "name": "generate-pdf",
+  "version": "1.0.0",
+  "description": "",
+  "main": "src/main.js",
+  "type": "module",
+  "scripts": {
+    "format": "prettier --write ."
+  },
+  "dependencies": {
+    "@faker-js/faker": "^8.0.2",
+    "pdf-lib": "^1.17.1"
+  },
+  "devDependencies": {
+    "prettier": "^3.0.0"
+  }
+}
diff --git a/node/generate-pdf/src/main.js b/node/generate-pdf/src/main.js
new file mode 100644
index 00000000..722d8fe6
--- /dev/null
+++ b/node/generate-pdf/src/main.js
@@ -0,0 +1,70 @@
+import { PDFDocument } from 'pdf-lib';
+import { faker } from '@faker-js/faker';
+
+export default async ({ res, log }) => {
+  const fakeOrder = generateFakeOrder();
+  log(`Generated fake order: ${JSON.stringify(fakeOrder, null, 2)}`);
+
+  const pdfBuffer = await createPdf(fakeOrder);
+  log('PDF created.');
+
+  return res.send(pdfBuffer, 200, { 'Content-Type': 'application/pdf' });
+};
+
+function generateFakeOrder() {
+  const items = Array.from(
+    { length: faker.number.int({ min: 1, max: 5 }) },
+    () => ({
+      description: faker.commerce.productName(),
+      quantity: faker.number.int({ min: 1, max: 10 }),
+      cost: faker.commerce.price(),
+    })
+  );
+
+  return {
+    id: faker.string.uuid(),
+    date: faker.date.past(),
+    name: faker.person.fullName(),
+    items,
+    total: items.reduce((acc, { cost }) => acc + parseFloat(cost), 0),
+  };
+}
+
+async function createPdf({ id, date, name, items, total }) {
+  const document = await PDFDocument.create();
+  const page = document.addPage([595.28, 841.89]); // A4 size
+
+  page.drawText('Sample Invoice', { x: 50, y: 750, size: 20 });
+  page.drawText(new Date(date).toLocaleDateString(), {
+    x: 400,
+    y: 750,
+    size: 15,
+  });
+
+  page.drawText(`Hello, ${name}!`, {
+    x: 50,
+    y: 700,
+    size: 30,
+  });
+
+  page.drawText(`Order ID: ${id}`, {
+    x: 50,
+    y: 650,
+    size: 10,
+  });
+
+  page.drawText(`Total: $${total}`, { x: 50, y: 600, size: 15 });
+
+  const orderList = items
+    .map(
+      ({ description, quantity, cost }) =>
+        `${description} x ${quantity} = $${cost}`
+    )
+    .join('\n');
+
+  page.drawText(orderList, { x: 50, y: 550, size: 15 });
+
+  const pdfBytes = await document.save();
+
+  return Buffer.from(pdfBytes.buffer);
+}
