diff --git a/masked-number/.env b/masked-number/.env
deleted file mode 100644
index fb964af7..00000000
--- a/masked-number/.env
+++ /dev/null
@@ -1,9 +0,0 @@
-# description: Messages sent to your Twilio number will get forwarded to this E.164-formatted phone number
-# format: phone_number
-# required: true
-# link: https://www.twilio.com/docs/glossary/what-e164
-MY_PHONE_NUMBER=+12223334444
-
-# description: The path to the webhook
-# configurable: false
-TWILIO_SMS_WEBHOOK_URL=/relay-sms
diff --git a/masked-number/masked-number-demo/.gitignore b/masked-number/masked-number-demo/.gitignore
new file mode 100644
index 00000000..ca7e037f
--- /dev/null
+++ b/masked-number/masked-number-demo/.gitignore
@@ -0,0 +1,133 @@
+# Twilio Serverless
+.twiliodeployinfo
+
+# 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.*
diff --git a/masked-number/masked-number-demo/.nvmrc b/masked-number/masked-number-demo/.nvmrc
new file mode 100644
index 00000000..25bf17fc
--- /dev/null
+++ b/masked-number/masked-number-demo/.nvmrc
@@ -0,0 +1 @@
+18
\ No newline at end of file
diff --git a/masked-number/masked-number-demo/.twilioserverlessrc b/masked-number/masked-number-demo/.twilioserverlessrc
new file mode 100644
index 00000000..a7f5a1cb
--- /dev/null
+++ b/masked-number/masked-number-demo/.twilioserverlessrc
@@ -0,0 +1,42 @@
+{
+ "commands": {},
+ "environments": {},
+ "projects": {},
+ // "assets": true /* Upload assets. Can be turned off with --no-assets */,
+ // "assetsFolder": null /* Specific folder name to be used for static assets */,
+ // "buildSid": null /* An existing Build SID to deploy to the new environment */,
+ // "createEnvironment": false /* Creates environment if it couldn't find it. */,
+ // "cwd": null /* Sets the directory of your existing Serverless project. Defaults to current directory */,
+ // "detailedLogs": false /* Toggles detailed request logging by showing request body and query params */,
+ // "edge": null /* Twilio API Region */,
+ // "env": null /* Path to .env file for environment variables that should be installed */,
+ // "environment": "dev" /* The environment name (domain suffix) you want to use for your deployment. Alternatively you can specify an environment SID starting with ZE. */,
+ // "extendedOutput": false /* Show an extended set of properties on the output */,
+ // "force": false /* Will run deployment in force mode. Can be dangerous. */,
+ // "forkProcess": true /* Disable forking function processes to emulate production environment */,
+ // "functionSid": null /* Specific Function SID to retrieve logs for */,
+ // "functions": true /* Upload functions. Can be turned off with --no-functions */,
+ // "functionsFolder": null /* Specific folder name to be used for static functions */,
+ // "inspect": null /* Enables Node.js debugging protocol */,
+ // "inspectBrk": null /* Enables Node.js debugging protocol, stops execution until debugger is attached */,
+ // "legacyMode": false /* Enables legacy mode, it will prefix your asset paths with /assets */,
+ // "live": true /* Always serve from the current functions (no caching) */,
+ // "loadLocalEnv": false /* Includes the local environment variables */,
+ // "loadSystemEnv": false /* Uses system environment variables as fallback for variables specified in your .env file. Needs to be used with --env explicitly specified. */,
+ // "logCacheSize": null /* Tailing the log endpoint will cache previously seen entries to avoid duplicates. The cache is topped at a maximum of 1000 by default. This option can change that. */,
+ // "logLevel": "info" /* Level of logging messages. */,
+ // "logs": true /* Toggles request logging */,
+ // "ngrok": null /* Uses ngrok to create a public url. Pass a string to set the subdomain (requires a paid-for ngrok account). */,
+ // "outputFormat": "" /* Output the results in a different format */,
+ // "overrideExistingProject": false /* Deploys Serverless project to existing service if a naming conflict has been found. */,
+ // "port": "3000" /* Override default port of 3000 */,
+ // "production": false /* Promote build to the production environment (no domain suffix). Overrides environment flag */,
+ // "properties": null /* Specify the output properties you want to see. Works best on single types */,
+ // "region": null /* Twilio API Region */,
+ "runtime": "node18" /* The version of Node.js to deploy the build to. (node18) */,
+ // "serviceName": null /* Overrides the name of the Serverless project. Default: the name field in your package.json */,
+ // "serviceSid": null /* SID of the Twilio Serverless Service to deploy to */,
+ // "sourceEnvironment": null /* SID or suffix of an existing environment you want to deploy from. */,
+ // "tail": false /* Continuously stream the logs */,
+ // "template": null /* undefined */,
+}
\ No newline at end of file
diff --git a/masked-number/masked-number-demo/assets/index.html b/masked-number/masked-number-demo/assets/index.html
new file mode 100644
index 00000000..1e172050
--- /dev/null
+++ b/masked-number/masked-number-demo/assets/index.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+ Get started with your Twilio Functions!
+
+
+
+
+
+
+
+
+
Your live application with Twilio is ready to use!
+
+
+
+
Get started with your application
+
+ Follow these steps to try out your new app:
+
+
+ This app masks your phone number for SMS messages by relaying them through a
+ Twilio phone number.
+
+
+
+ Text your Twilio phone number with a recipient phone number, a
+ :, and a message. For example, to send the message "hello" to
+ the number "+12223334444", text your Twilio phone number with:
+ +12223334444: hello.
+
+
Your recipient should receive your message from your Twilio phone number.
+
+ When that recipient sends a reply to your Twilio phone number, it will be
+ relayed to your personal phone number.
+
+
+
+
+
+
+
+
+
Troubleshooting
+
+
+ Check the
+
+ phone number configuration
+
+ and make sure the Twilio phone number you want for your app has a SMS webhook
+ configured to point at the following URL
+
+
+
+ Ensure that MY_PHONE_NUMBER is set to the phone number you want
+ to relay messages to, in
+
+ E.164 format
+ .
+
+
+
+
+
+
+
+
diff --git a/masked-number/masked-number-demo/functions/relay-sms.protected.js b/masked-number/masked-number-demo/functions/relay-sms.protected.js
new file mode 100644
index 00000000..38658c8b
--- /dev/null
+++ b/masked-number/masked-number-demo/functions/relay-sms.protected.js
@@ -0,0 +1,95 @@
+/*
+ * Masking your phone number for SMS Forwarding and Responding
+ *
+ * Description:
+ * This function acts as a message-forwarding service
+ * If the message comes from the user, it forwards the message to another number.
+ * If it comes from someone else, it forwards it to the user.
+ *
+ * Contents:
+ * 1. Initialize Client and Response
+ * 2. Sender Check
+ * 3. Extracting Recipient and Message
+ * 4. Sending the Message
+ * 5. Handling Messages from Other Senders
+ */
+
+/*
+ * 1. Initialize client and response
+ *
+ * Here you can initialize a Twilio client (client) to interact with Twilio's API.
+ *
+ * A twiml object is created to generate TwiML (Twilio Markup Language) responses,
+ * which are instructions that tell Twilio how to respond to an incoming message.
+ */
+
+// Defines the main function handler for the Twilio Function.
+exports.handler = async function (context, event, callback) {
+ const client = context.getTwilioClient();
+ const twiml = new Twilio.twiml.MessagingResponse();
+
+/*
+ * 2. Checking the Sender
+ *
+ * Here you can checks if the message came from a specific number.
+ * This condition ensures that only the user with this phone number can send outgoing messages.
+ */
+ if (event.From === context.MY_PHONE_NUMBER) {
+ // Looks for a : in the message body to separate the recipient's phone number from the message text.
+ const separatorPosition = event.Body.indexOf(':');
+
+ // If there is no :, a response is sent to the sender with a message explaining the required format: recipientPhoneNumber: message.
+ if (separatorPosition < 1) {
+ twiml.message(
+ 'You need to specify a recipient number and a ":" before the message. For example, "+12223334444: message".'
+ );
+
+ /*
+ * 3. Extracting Recipient and Message
+ *
+ * Here you can processes the incoming message body
+ * to extract the recipient's phone number and the actual message content
+ */
+
+ } else {
+ // Extracts the recipient's phone number from the part of the message before the : and removes any extra whitespace.
+ const recipientNumber = event.Body.substr(0, separatorPosition).trim();
+ // Extracts the actual message from the part of the message after the ':'
+ const messageBody = event.Body.substr(separatorPosition + 1).trim();
+
+ /*
+ * 4. Sending the Message
+ *
+ * Here a try-catch block attempts to send an SMS message using the Twilio API
+ */
+ try {
+ // Sends the SMS to recipientNumber with the message messageBody.
+ await client.messages.create({
+ to: recipientNumber,
+ from: event.To,
+ body: messageBody,
+ });
+ // If successful, callback(null) is called to signal that the function executed successfully without returning any TwiML.
+ return callback(null);
+ // If there is an error (e.g., an invalid phone number), a failure message is sent to the sender explaining that the phone number might be incorrect.
+ } catch (err) {
+ twiml.message(
+ 'There was an issue with the phone number you entered; please verify it is correct and try again.'
+ );
+ }
+ }
+ /*
+ * 5. Handling Messages from Other Senders
+ *
+ * If the message is not from context.MY_PHONE_NUMBER,
+ * the function forwards it to the number stored in context.MY_PHONE_NUMBER,
+ */
+ } else {
+ twiml.message(
+ { to: context.MY_PHONE_NUMBER },
+ `${event.From}: ${event.Body}`
+ );
+ }
+
+ return callback(null, twiml);
+};
diff --git a/masked-number/masked-number-demo/package.json b/masked-number/masked-number-demo/package.json
new file mode 100644
index 00000000..f511c8a2
--- /dev/null
+++ b/masked-number/masked-number-demo/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "masked-number-demo",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "twilio-run",
+ "deploy": "twilio-run deploy"
+ },
+ "dependencies": {
+ "twilio": "5.0.3",
+ "@twilio/runtime-handler": "2.0.3"
+ },
+ "devDependencies": {
+ "twilio-run": "^4.0.3"
+ },
+ "engines": {
+ "node": "18"
+ }
+}
\ No newline at end of file
diff --git a/masked-number/masked-number-demo/readmes/masked-number.md b/masked-number/masked-number-demo/readmes/masked-number.md
new file mode 100644
index 00000000..4f855268
--- /dev/null
+++ b/masked-number/masked-number-demo/readmes/masked-number.md
@@ -0,0 +1,50 @@
+# Masked Number
+
+Uses a Twilio phone number to relay SMS messages to and from your phone; since the other party only sees your Twilio number, this effectively allows you to mask your phone number for privacy purposes.
+
+## Pre-requisites
+
+### Environment variables
+
+This project requires some environment variables to be set. To keep your tokens and secrets secure, make sure to not commit the `.env` file in git. When setting up the project with `twilio serverless:init ...` the Twilio CLI will create a `.gitignore` file that excludes `.env` from the version history.
+
+In your `.env` file, set the following values:
+
+| Variable | Description | Required |
+| :-------------- | :------------------------------------------------- | :------- |
+| MY_PHONE_NUMBER | The phone number which SMS messages get relayed to | Yes |
+
+## Create a new project with the template
+
+1. Install the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart#install-twilio-cli)
+2. Install the [serverless toolkit](https://www.twilio.com/docs/labs/serverless-toolkit/getting-started)
+
+```shell
+twilio plugins:install @twilio-labs/plugin-serverless
+```
+
+3. Initiate a new project
+
+```
+twilio serverless:init example --template=masked-number && cd example
+```
+
+4. Start the server with the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart):
+
+```
+twilio serverless:start
+```
+
+5. Open the web page at https://localhost:3000/index.html and enter your phone number to test
+
+ℹ️ Check the developer console and terminal for any errors, make sure you've set your environment variables.
+
+## Deploying
+
+Deploy your functions and assets with either of the following commands. Note: you must run these commands from inside your project folder. [More details in the docs.](https://www.twilio.com/docs/labs/serverless-toolkit)
+
+With the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart):
+
+```
+twilio serverless:deploy
+```
diff --git a/masked-number/package.json b/masked-number/package.json
index 249bce8d..4366bcb2 100644
--- a/masked-number/package.json
+++ b/masked-number/package.json
@@ -1,6 +1,14 @@
{
"name": "masked-number",
"version": "1.0.0",
- "private": true,
- "dependencies": {}
+ "description": "Uses a Twilio phone number to relay SMS messages to and from your phone; since the other party only sees your Twilio number, this effectively allows you to mask your phone number for privacy purposes.",
+ "main": "index.js",
+ "directories": {
+ "test": "tests"
+ },
+ "scripts": {
+ "test": "jest"
+ },
+ "author": "",
+ "license": "ISC"
}
diff --git a/masked-number/package.json.backup b/masked-number/package.json.backup
new file mode 100644
index 00000000..691b6e73
--- /dev/null
+++ b/masked-number/package.json.backup
@@ -0,0 +1,8 @@
+{
+ "name": "masked-number",
+ "version": "1.0.0",
+ "private": true,
+ "devDependencies": {
+ "jest": "^29.7.0"
+ }
+}