diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml
new file mode 100644
index 0000000..e0d6abd
--- /dev/null
+++ b/.github/workflows/on-pull-request.yml
@@ -0,0 +1,21 @@
+name: on-pull-request
+
+on:
+ pull_request:
+ branches: [main]
+
+jobs:
+ test:
+ runs-on: ubuntu-24.04
+ steps:
+ - name: Setup repo
+ uses: actions/checkout@v3
+
+ - name: Verify README generation
+ uses: momentohq/standards-and-practices/github-actions/oss-readme-template@gh-actions-v2
+ with:
+ project_status: official
+ project_stability: stable
+ project_type: other
+ template_file: ./README.template.md
+ output_file: .README.md
diff --git a/.github/workflows/on-push-to-main.yml b/.github/workflows/on-push-to-main.yml
new file mode 100644
index 0000000..1e7c858
--- /dev/null
+++ b/.github/workflows/on-push-to-main.yml
@@ -0,0 +1,23 @@
+name: on-push-to-main
+
+on:
+ push:
+ branches: [main]
+
+jobs:
+ test:
+ runs-on: ubuntu-24.04
+ steps:
+ - name: Setup repo
+ uses: actions/checkout@v3
+ with:
+ token: ${{ secrets.MOMENTO_MACHINE_USER_GITHUB_TOKEN }}
+
+ - name: Generate README
+ uses: momentohq/standards-and-practices/github-actions/generate-and-commit-oss-readme@gh-actions-v2
+ with:
+ project_status: official
+ project_stability: stable
+ project_type: other
+ template_file: ./README.template.md
+ output_file: .README.md
diff --git a/README.template.md b/README.template.md
new file mode 100644
index 0000000..42bf361
--- /dev/null
+++ b/README.template.md
@@ -0,0 +1,22 @@
+{{ ossHeader }}
+
+## Multi-language Moderated Chat Demo
+
+This application uses Momento Webhooks to build a moderated, multi-language chat application. Users across a variety of client applications can chat with each other in multiple languages at the same time with profanity filtered out in real time.
+
+You can try the chat app using our deployed [web app here](https://moderated-chat.vercel.app/).
+
+You can find the web app implementation, as well as additional client applications, of the moderated chat app in the following locations:
+
+- [Web (React + Vite)](./frontend/)
+- [iOS](./ios/)
+- [Android](./android/)
+- [Flutter](./flutter/)
+- [React Native](./react-native/)
+- [Unity](https://github.com/momentohq/momento-unity-demo)
+
+## Developing
+
+If you are interested in deploying your own version of a moderated chat app, you will need to deploy your own version of the backend infrastructure which uses Momento and AWS services. Please see the [infrastructure directory](./infrastructure/) for the overview and setup instructions.
+
+{{ ossFooter }}
diff --git a/android/ModeratedChat/app/src/main/java/software/momento/kotlin/moderatedchat/MainActivity.kt b/android/ModeratedChat/app/src/main/java/software/momento/kotlin/moderatedchat/MainActivity.kt
index 4c3ca90..45c04c6 100644
--- a/android/ModeratedChat/app/src/main/java/software/momento/kotlin/moderatedchat/MainActivity.kt
+++ b/android/ModeratedChat/app/src/main/java/software/momento/kotlin/moderatedchat/MainActivity.kt
@@ -97,7 +97,7 @@ import kotlin.collections.HashMap
import kotlin.system.exitProcess
import kotlin.time.Duration.Companion.seconds
-const val baseApiUrl = "https://57zovcekn0.execute-api.us-west-2.amazonaws.com/prod"
+const val baseApiUrl = "https://your-api-endpoint.com"
var momentoApiToken: String = ""
var tokenExpiresAt: Long = 0
var topicClient: TopicClient? = null
diff --git a/android/README.md b/android/README.md
index a391cd9..febcd8f 100644
--- a/android/README.md
+++ b/android/README.md
@@ -1,7 +1,19 @@
# Moderated Chat Using Android Client
+This directory contains an Android app version of the Moderated Chat demo.
+
+## Prerequisites
+
+- [Android Studio](https://developer.android.com/studio/install)
+
## Running the example using Android Studio
1. Open the `android/ModeratedChat` directory in [Android Studio](https://developer.android.com/studio)
-2. Click the run button in the top bar or choose `Run 'app'` in the `Run` menu
+2. Edit the `baseApiUrl` variable to set your API endpoint.
+
+ ```kotlin
+ const val baseApiUrl = "https://your-api-endpoint.com"
+ ```
+
+3. Click the run button in the top bar or choose `Run 'app'` in the `Run` menu
diff --git a/flutter/moderated_chat/README.md b/flutter/moderated_chat/README.md
index 5b49d71..d5c20fa 100644
--- a/flutter/moderated_chat/README.md
+++ b/flutter/moderated_chat/README.md
@@ -3,16 +3,31 @@
A Flutter version of the Momento Moderated Chat demo. It currently only has a macOS implementation, but more are coming soon.
## Prerequisites
-Flutter. It can be installed by following the instructions [here](https://docs.flutter.dev/get-started/install).
-### macOS
-For mac specifically, you will need the Flutter SDK, [Xcode](https://developer.apple.com/xcode/), and [CocoaPods](https://guides.cocoapods.org/using/getting-started.html#installation).
+- [Flutter is installed](https://docs.flutter.dev/get-started/install).
+
+### macOS prerequisites
+
+- [Xcode](https://developer.apple.com/xcode/)
+- [CocoaPods](https://guides.cocoapods.org/using/getting-started.html#installation).
## Running the Demo
-From the flutter moderated_chat directory, call `flutter run` to start the app:
-```bash
-cd flutter/moderated_chat
-flutter run -d macos
-```
-Alternatively, you can open the project in VSCode or IntelliJ with the Flutter plugin and run the app from there.
+1. In the [lib/config.dart file](./lib/config.dart), specify the base URL for your API endpoints.
+
+ ```dart
+ class Config {
+ static const baseUrl = "https://your-api-endpoint.com";
+ }
+ ```
+
+2. From the flutter moderated_chat directory, call `flutter run` to start the app:
+
+ ```bash
+ cd flutter/moderated_chat
+ flutter run -d macos
+ ```
+
+ Alternatively, you can open the project in VSCode or IntelliJ with the Flutter plugin and run the app from there.
+
+Note: see [here](https://github.com/jonataslaw/get_cli/issues/263) if you are using Dart 3.5.0 and get an error about UnmodifiableUint8ListView.
diff --git a/flutter/moderated_chat/lib/config.dart b/flutter/moderated_chat/lib/config.dart
index 33178e6..812fb98 100644
--- a/flutter/moderated_chat/lib/config.dart
+++ b/flutter/moderated_chat/lib/config.dart
@@ -1,3 +1,3 @@
class Config {
- static const baseUrl = "https://57zovcekn0.execute-api.us-west-2.amazonaws.com/prod";
+ static const baseUrl = "https://your-api-endpoint.com";
}
diff --git a/frontend/README.md b/frontend/README.md
index 1ebe379..c6347bb 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -1,27 +1,26 @@
-# React + TypeScript + Vite
+# Web Moderated Chat App
-This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+This directory contains a React + TypeScript + Vite web app version of the Moderated Chat demo.
-Currently, two official plugins are available:
+## Prerequisites
-- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
-- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+- Node version 16 or higher is required
-## Expanding the ESLint configuration
+## Running the demo
-If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+Create a `.env` file to specify the base URL for your API endpoints.
-- Configure the top-level `parserOptions` property like this:
+```bash
+VITE_API_BASE_URL="https://your-api-endpoint.com"
+```
+
+Then run the web app:
-```js
- parserOptions: {
- ecmaVersion: 'latest',
- sourceType: 'module',
- project: ['./tsconfig.json', './tsconfig.node.json'],
- tsconfigRootDir: __dirname,
- },
+```bash
+npm install
+npm run dev
```
-- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
-- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
-- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
+## Deploying to Vercel
+
+For [Vercel](https://vercel.com) deployments of the moderated chat app, you must also ensure the `VITE_API_BASE_URL` environment variable exists. You can create this using the Vercel console on the project's Settings > Environment Variables page.
diff --git a/frontend/env.d.ts b/frontend/env.d.ts
deleted file mode 100644
index f89ff94..0000000
--- a/frontend/env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-declare namespace NodeJS {
- interface ProcessEnv {
- MOMENTO_AUTH_TOKEN: string;
- }
-}
diff --git a/frontend/src/api/translation.ts b/frontend/src/api/translation.ts
index 41bf763..18b12fc 100644
--- a/frontend/src/api/translation.ts
+++ b/frontend/src/api/translation.ts
@@ -2,9 +2,8 @@ import { type LanguageOption } from "../ChatApp";
import { type ChatMessageEvent, type User } from "../shared/models";
class TranslationApi {
- // TODO: update API DOMAIN when moving to prod
- private readonly baseUrl =
- "https://chat-api.developer-mst-dev.preprod.a.momentohq.com";
+ private readonly baseUrl = import.meta.env.VITE_API_BASE_URL;
+
async createToken(
user: User,
): Promise<{ token: string; expiresAtEpoch: number }> {
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
index 11f02fe..170e8dc 100644
--- a/frontend/src/vite-env.d.ts
+++ b/frontend/src/vite-env.d.ts
@@ -1 +1,10 @@
///
+
+interface ImportMetaEnv {
+ readonly VITE_API_BASE_URL: string;
+ // more env variables may be added here
+}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 5a33944..2ab4ddc 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,7 +1,11 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
-})
+ define: {
+ "process.env": process.env,
+ VITE_API_BASE_URL: process.env.VITE_API_BASE_URL,
+ },
+});
diff --git a/infrastructure/README.md b/infrastructure/README.md
index 320efc0..6e5acaf 100644
--- a/infrastructure/README.md
+++ b/infrastructure/README.md
@@ -1,14 +1,74 @@
-# Welcome to your CDK TypeScript project
+# Moderated Chat App Backend Infrastructure
-This is a blank project for CDK development with TypeScript.
+The [backend](../backend/) directory contains the Lambda functions used for initializing a Momento [cache](https://docs.momentohq.com/cache) and [webhook](https://docs.momentohq.com/topics/webhooks/overview), creating a [token vending machine](https://github.com/momentohq/client-sdk-javascript/tree/main/examples/nodejs/token-vending-machine), and serving API requests for the moderated chat application.
-The `cdk.json` file tells the CDK Toolkit how to execute your app.
+This directory contains the [AWS CDK](https://github.com/aws/aws-cdk) stack to deploy AWS resources.
-## Useful commands
+The main APIs used in this application are:
-* `npm run build` compile typescript to js
-* `npm run watch` watch for changes and compile
-* `npm run test` perform the jest unit tests
-* `cdk deploy` deploy this stack to your default AWS account/region
-* `cdk diff` compare deployed stack with current state
-* `cdk synth` emits the synthesized CloudFormation template
+- `POST /v1/translate` - webhook listener for momento topic events
+- `GET /v1/translate/latestMessages/` - returns the last 100 messages from the chat in the requested language
+- `GET /v1/translate/supportedLanguages` - returns the languages that the application currently supports
+- `GET /v1/translate/token/` - returns a short lived token that allows to publish to the `chat-publish` topic
+
+In order to run these apis, you will first need to create a secret stored in AWS Secrets Manager with the path `moderated-chat/demo/secrets`. You can use the [setup-secrets.sh script](./setup-secrets.sh) to deploy this secret to your AWS account.
+
+In the AWS console, you should verify that the secret contains key-value pairs in the format:
+
+```text
+{
+ momentoApiKey: "",
+ webhookSigningSecret: "",
+}
+```
+
+- `momentoApiKey` - your Momento API key with superuser permissions. This can be created via the [Momento Console](https://console.gomomento.com/api-keys). This api key will be used to vend short lived publish/subscribe api keys to the frontend.
+- `webhookSigningSecret` - the signing secret associated with the Momento Webhook. It is used to validate that requests are coming from Momento. This secret is updated by the custom resource lambda function when you deploy the backend infrastructure CDK stack.
+
+To deploy the CDK stack, you can edit and run the [build-and-deploy script](./build-and-deploy.sh).
+Or you can manually run each of these steps:
+
+1. Build the Lambda function code.
+
+ ```bash
+ cd backend/lambdas
+ npm install
+ npm run build
+ ```
+
+2. Build the CDK code.
+
+ ```bash
+ cd infrastructure
+ npm install
+ npm run build
+ ```
+
+3. Specify the API_DOMAIN environment variable.
+
+ ```bash
+ # The default is to use the API gateway URL that is provided when you deploy the backend stack.
+ export API_DOMAIN="default"
+
+ # Specifying your own domain name will direct your CDK stack to find an existing AWS Route53
+ # hosted zone in your account and create a 'chat-api' subdomain for it.
+ export API_DOMAIN=${API_DOMAIN:-your-chosen-domain-name.com}
+ ```
+
+4. Deploy your backend stack.
+
+ ```bash
+ AWS_PROFILE= AWS_REGION= npx cdk deploy
+ ```
+
+Once deployed, you can test your application using any of the client applications.
+
+If you used the `API_DOMAIN="default"` option, you'll want to save the API gateway URL that was printed out.
+This will be the base API URL you'll provide to the client applications.
+
+```bash
+Outputs:
+moderated-chat-translation-api-stack.moderatedchatrestapiEndpoint23439914 = https://something.something.something.amazonaws.com/prod/
+```
+
+If you used your own API domain name, you'll provide something like `https://chat-api.your-domain-name.com` to the client applications.
diff --git a/infrastructure/build-and-deploy.sh b/infrastructure/build-and-deploy.sh
index d5a0070..56f9e04 100755
--- a/infrastructure/build-and-deploy.sh
+++ b/infrastructure/build-and-deploy.sh
@@ -12,7 +12,12 @@ rm -f cdk.context.json
npm i
npm run build
-# TODO: update API DOMAIN when moving to prod
-export API_DOMAIN=${API_DOMAIN:-developer-mst-dev.preprod.a.momentohq.com}
+# For Momento developers, to deploy to your dev account, you will need to have gone through the cell bootstrap
+# process at least once. Alternately, you can use a teammate's endpoint or use the preprod endpoint
+# (search for Route53 hosted zones in the appropriate AWS accounts).
+# export API_DOMAIN=${API_DOMAIN:-your-chosen-domain-name.com}
+
+# The default is to use the API gateway URL that is provided when you deploy the backend stack.
+export API_DOMAIN="default"
AWS_PROFILE=dev AWS_REGION=us-west-2 npx cdk deploy --require-approval never
diff --git a/infrastructure/lib/translation-api.ts b/infrastructure/lib/translation-api.ts
index cd3a7ce..831d715 100644
--- a/infrastructure/lib/translation-api.ts
+++ b/infrastructure/lib/translation-api.ts
@@ -40,18 +40,6 @@ export class TranslationApiStack extends cdk.Stack {
: RemovalPolicy.RETAIN,
});
- // Register the subdomain and create a certificate for it
- const hostedZone = route53.HostedZone.fromLookup(
- this,
- 'moderated-chat-api-hosted-zone',
- {
- domainName: props.apiDomain,
- }
- );
- const certificate = new certmgr.Certificate(this, 'moderated-chat-api-cert', {
- domainName: `${props.apiSubdomain}.${props.apiDomain}`,
- validation: certmgr.CertificateValidation.fromDns(hostedZone),
- });
const defaultRestApiProps: apigw.RestApiProps = {
restApiName,
endpointTypes: [apigw.EndpointType.REGIONAL],
@@ -72,26 +60,49 @@ export class TranslationApiStack extends cdk.Stack {
allowHeaders: apigw.Cors.DEFAULT_HEADERS,
allowMethods: apigw.Cors.ALL_METHODS,
},
- domainName: {
- domainName: `${props.apiSubdomain}.${props.apiDomain}`,
- endpointType: apigw.EndpointType.REGIONAL,
- certificate,
- },
cloudWatchRole: true, // allows api gateway to write logs to cloudwatch
};
- this.restApi = new apigw.RestApi(this, 'moderated-chat-rest-api', {
- ...defaultRestApiProps,
- });
+ // Register the subdomain and create a certificate for it if using a custom domain
+ if (props.apiDomain !== "default") {
+ const hostedZone = route53.HostedZone.fromLookup(
+ this,
+ 'moderated-chat-api-hosted-zone',
+ {
+ domainName: props.apiDomain,
+ }
+ );
+ const certificate = new certmgr.Certificate(this, 'moderated-chat-api-cert', {
+ domainName: `${props.apiSubdomain}.${props.apiDomain}`,
+ validation: certmgr.CertificateValidation.fromDns(hostedZone),
+ });
- new route53.ARecord(this, "moderated-chat-rest-api-dns", {
- zone: hostedZone,
- recordName: props.apiSubdomain,
- comment: "This is the A Record used for the moderated chat api backend",
- target: route53.RecordTarget.fromAlias(
- new route53Targets.ApiGateway(this.restApi)
- ),
- });
+ const updatedRestApiProps: apigw.RestApiProps = {
+ ...defaultRestApiProps,
+ domainName: {
+ domainName: `${props.apiSubdomain}.${props.apiDomain}`,
+ endpointType: apigw.EndpointType.REGIONAL,
+ certificate,
+ },
+ };
+
+ this.restApi = new apigw.RestApi(this, 'moderated-chat-rest-api', {
+ ...updatedRestApiProps,
+ });
+
+ new route53.ARecord(this, "moderated-chat-rest-api-dns", {
+ zone: hostedZone,
+ recordName: props.apiSubdomain,
+ comment: "This is the A Record used for the moderated chat api backend",
+ target: route53.RecordTarget.fromAlias(
+ new route53Targets.ApiGateway(this.restApi)
+ ),
+ });
+ } else {
+ this.restApi = new apigw.RestApi(this, 'moderated-chat-rest-api', {
+ ...defaultRestApiProps,
+ });
+ }
const secretsPath = 'moderated-chat/demo/secrets';
const v1TranslationApi = new lambda.Function(this, 'moderated-chat-translation-lambda-function', {
diff --git a/ios/ModeratedChat/ModeratedChat/TranslationApi.swift b/ios/ModeratedChat/ModeratedChat/TranslationApi.swift
index 29dd67c..6e253e9 100644
--- a/ios/ModeratedChat/ModeratedChat/TranslationApi.swift
+++ b/ios/ModeratedChat/ModeratedChat/TranslationApi.swift
@@ -5,7 +5,7 @@ import Alamofire
@MainActor
class TranslationApi: ObservableObject {
static let shared = TranslationApi()
- private let baseUrl = "https://57zovcekn0.execute-api.us-west-2.amazonaws.com/prod";
+ private let baseUrl: String = ProcessInfo.processInfo.environment["API_BASE_URL"]!
@Published var selectedLanguageCode: String = "en"
@Published var supportedLanguages: [Language] = []
@Published var currentUsername: String = ""
@@ -17,6 +17,7 @@ class TranslationApi: ObservableObject {
}
func createToken() async -> MomentoToken {
+
do {
let user = getUser()
currentUsername = user.username
diff --git a/ios/README.md b/ios/README.md
index 625ba39..a59fed6 100644
--- a/ios/README.md
+++ b/ios/README.md
@@ -1,6 +1,26 @@
-# Moderated Chat using iOS Client
+# iOS Moderated Chat App
-## Running the example using the Xcode simulator
+This directory contains an iOS client of the Moderated Chat demo.
-1. Open the `ios/moderated_chat` directory as an Xcode project.
-3. Click Run (in the Product menu).
\ No newline at end of file
+## Prerequisites
+
+- [Xcode](https://developer.apple.com/xcode/)
+
+## Running the demo
+
+1. Create an environment variable to specify the base URL for your API endpoints.
+
+ To create an environment variable in Xcode, navigate to "Product" > "Scheme" > "Edit Scheme".
+ Select "Run" from the menu on the left, then "Arguments" along the top of that page.
+
+ ```bash
+ API_BASE_URL="https://your-api-endpoint.com"
+ ```
+
+2. To run the app using a simulator, simply open the `ios/moderated_chat` directory as an Xcode project and click "Run".
+
+Note: You may also need to specify a variable to enable logging output in order to avoid a `LoggingError` in the output console.
+
+```bash
+IDEPreferLogStreaming=YES
+```
\ No newline at end of file
diff --git a/react-native/ModeratedChat/api/translation.ts b/react-native/ModeratedChat/api/translation.ts
index d698a85..eb78e17 100644
--- a/react-native/ModeratedChat/api/translation.ts
+++ b/react-native/ModeratedChat/api/translation.ts
@@ -2,8 +2,7 @@ import { type LanguageOption } from "../ChatApp";
import { type ChatMessageEvent, type User } from "../shared/models";
class TranslationApi {
- private readonly baseUrl =
- "https://chat-api.developer-mst-dev.preprod.a.momentohq.com";
+ private readonly baseUrl = process.env.API_BASE_URL;
async createToken(
user: User,
): Promise<{ token: string; expiresAtEpoch: number }> {
diff --git a/react-native/ModeratedChat/babel.config.js b/react-native/ModeratedChat/babel.config.js
index 2900afe..7fb6e67 100644
--- a/react-native/ModeratedChat/babel.config.js
+++ b/react-native/ModeratedChat/babel.config.js
@@ -2,5 +2,8 @@ module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
+ plugins: [
+ ['module:react-native-dotenv']
+ ]
};
};
diff --git a/react-native/ModeratedChat/env.d.ts b/react-native/ModeratedChat/env.d.ts
new file mode 100644
index 0000000..873c134
--- /dev/null
+++ b/react-native/ModeratedChat/env.d.ts
@@ -0,0 +1,3 @@
+declare module '@env' {
+ export const API_BASE_URL: string;
+}
diff --git a/react-native/ModeratedChat/package-lock.json b/react-native/ModeratedChat/package-lock.json
index 6de8494..add8f32 100644
--- a/react-native/ModeratedChat/package-lock.json
+++ b/react-native/ModeratedChat/package-lock.json
@@ -32,7 +32,8 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
- "@types/uuid": "^9.0.8"
+ "@types/uuid": "^9.0.8",
+ "react-native-dotenv": "^3.4.11"
}
},
"node_modules/@ampproject/remapping": {
@@ -13269,6 +13270,30 @@
"react": "18.2.0"
}
},
+ "node_modules/react-native-dotenv": {
+ "version": "3.4.11",
+ "resolved": "https://registry.npmjs.org/react-native-dotenv/-/react-native-dotenv-3.4.11.tgz",
+ "integrity": "sha512-6vnIE+WHABSeHCaYP6l3O1BOEhWxKH6nHAdV7n/wKn/sciZ64zPPp2NUdEUf1m7g4uuzlLbjgr+6uDt89q2DOg==",
+ "dev": true,
+ "dependencies": {
+ "dotenv": "^16.4.5"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "^7.20.6"
+ }
+ },
+ "node_modules/react-native-dotenv/node_modules/dotenv": {
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
"node_modules/react-native-dropdown-select-list": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/react-native-dropdown-select-list/-/react-native-dropdown-select-list-2.0.5.tgz",
diff --git a/react-native/ModeratedChat/package.json b/react-native/ModeratedChat/package.json
index b547d07..c69e59a 100644
--- a/react-native/ModeratedChat/package.json
+++ b/react-native/ModeratedChat/package.json
@@ -15,6 +15,9 @@
"@types/react": "~18.2.14",
"base-64": "^1.0.0",
"expo": "~49.0.15",
+ "expo-file-system": "~15.4.5",
+ "expo-image-manipulator": "~11.3.0",
+ "expo-image-picker": "~14.3.2",
"expo-splash-screen": "~0.20.5",
"expo-status-bar": "~1.6.0",
"expo-storage": "^48.1.0",
@@ -27,14 +30,12 @@
"react-native-svg": "13.9.0",
"text-encoding": "^0.7.0",
"typescript": "^5.1.3",
- "uuid": "^9.0.1",
- "expo-image-picker": "~14.3.2",
- "expo-image-manipulator": "~11.3.0",
- "expo-file-system": "~15.4.5"
+ "uuid": "^9.0.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
- "@types/uuid": "^9.0.8"
+ "@types/uuid": "^9.0.8",
+ "react-native-dotenv": "^3.4.11"
},
"private": true
}
diff --git a/react-native/ModeratedChat/README.md b/react-native/README.md
similarity index 64%
rename from react-native/ModeratedChat/README.md
rename to react-native/README.md
index b74aba9..f4fac52 100644
--- a/react-native/ModeratedChat/README.md
+++ b/react-native/README.md
@@ -1,20 +1,25 @@
-# Moderated Chat Using React Native Client
+# React Native Moderated Chat App
-## Getting Started
-
-This project uses [Expo Go](https://docs.expo.dev/get-started/expo-go/), a free open-source sandbox that makes it quick and easy to experiment with React Native on Android and iOS devices. You will need the [expo application](https://expo.dev/client) installed on your phone, or you can also use device emulators for [Android](https://docs.expo.dev/workflow/android-studio-emulator/) and [iOS](https://docs.expo.dev/workflow/ios-simulator/).
+## Prerequisites
+- [Expo Go](https://docs.expo.dev/get-started/expo-go/), a free open-source sandbox that makes it quick and easy to experiment with React Native on Android and iOS devices. You will need the [expo application](https://expo.dev/client) installed on your phone, or you can also use device emulators for [Android](https://docs.expo.dev/workflow/android-studio-emulator/) and [iOS](https://docs.expo.dev/workflow/ios-simulator/).
## Running the example using Expo Go
-In the `react-native/ModeratedChat` directory:
+1. Create a `.env` file in the the `react-native/ModeratedChat` directory to specify the base URL for your API endpoints.
+
+ ```bash
+ API_BASE_URL="https://your-api-endpoint.com"
+ ```
+
+2. Then in the `react-native/ModeratedChat` directory:
-- run `npm install`
-- run `npx expo start`
-- run the app on your phone:
- - scan QR Code with your phone to open it in the Expo Go app
-- or run the app on an emulator:
- - launch one of the device emulators as described in the instructions displayed after you start the Expo server
+ - run `npm install`
+ - run `npx expo start`
+ - run the app on your phone:
+ - scan QR Code with your phone to open it in the Expo Go app
+ - or run the app on an emulator:
+ - launch one of the device emulators as described in the instructions displayed after you start the Expo server
## Polyfills