Serene is an AI-powered conversational assistant designed to streamline the scheduling of therapy appointments through natural language interactions. This solution leverages serverless architecture on AWS to provide a scalable, secure, and highly available booking experience.
The solution uses a serverless event-driven architecture. The frontend is a Single Page Application (SPA) hosted on Amazon S3 and distributed via Amazon CloudFront, ensuring low latency for users. This frontend interacts with a backend logic layer exposed through Amazon API Gateway. The core business logic is executed by AWS Lambda functions written in Python, which manage data persistence in Amazon DynamoDB and handle authentication via Amazon Cognito.
The conversational capabilities are powered by Amazon Lex, which processes natural language to extract intents and entities (such as dates and times) for booking. The "SereneBot" Lex agent integrates with Lambda functions to validate availability and finalize bookings in the database. The system also includes an administrative flow for managing pending requests, secured by role-based access controls.
- AWS CloudFormation: Infrastructure as Code (IaC) for provisioning all resources.
- Amazon S3: Hosting for the frontend and storage for CloudFormation templates.
- Amazon CloudFront: Content Delivery Network (CDN) for the web application.
- Amazon Cognito: User identity and access management.
- Amazon DynamoDB: NoSQL database for storing meeting records.
- AWS Lambda: Serverless compute for application logic and Lex hooks.
- Amazon API Gateway: RESTful API interface for the frontend.
- Amazon Lex: Conversational AI for the chatbot interface.
This project utilizes a modular Nested Stacks architecture to organize resources, ensuring maintainability and separation of concerns. Instead of a single monolithic template, the infrastructure is broken down into logical units (stacks) that are orchestrated by a parent stack.
- Root Stack (
root-stack.yaml): The orchestrator. It creates the S3 bucket for templates and triggers the creation of all child stacks in the correct dependency order. - Data Stack (
data-stack.yaml): Provisions the DynamoDB tables required for data persistence. - IAM Stack (
iam-stack.yaml): centralized definition of all IAM Roles and Policies to ensure least-privilege access for Lambda, Lex, and other services. - Auth Stack (
auth-stack.yaml): Sets up the Cognito User Pool and App Client for authentication. - AI Stack (
ai-stack.yaml): Defines the Amazon Lex bot resources, including intents, slots, and locales. - Backend Stack (
backend-stack.yaml): Deploys the AWS Lambda functions that contain the business logic. - API Stack (
api-stack.yaml): Configures the API Gateway to expose the Lambda functions as HTTP endpoints. - Frontend Stack (
frontend-stack.yaml): Sets up the S3 bucket for web hosting and the CloudFront distribution.
- An active AWS Account.
- AWS CLI installed and configured.
- Node.js and npm installed (for building the frontend).
Create a primary S3 bucket to store the CloudFormation templates.
aws s3 mb s3://<your-project-bucket-name>Upload the contents of the assets/cloudformation directory to your S3 bucket. Maintain the directory structure.
# Assuming you are in the project root
aws s3 cp assets/cloudformation/ s3://<your-project-bucket-name>/cloudformation/ --recursiveNavigate to the AWS CloudFormation console and create a new stack using the S3 URL of your root-stack.yaml (e.g., https://<your-project-bucket-name>.s3.amazonaws.com/cloudformation/root-stack.yaml).
You will need to provide the following parameters:
- APIName: Name for the API Gateway (default:
serene-api). - S3BucketName: The name of the bucket you created in Step 1.
- S3KeyPrefix: The prefix where templates are stored (default:
cloudformation/stacks). - UserEmail: A valid email address for the initial admin user.
- Username: Username for the admin (disk:
admin). - UserPoolName: Name for the Cognito User Pool.
Important:
- Acknowledge that AWS CloudFormation might create IAM resources with custom names.
- Acknowledge that AWS CloudFormation might require
CAPABILITY_AUTO_EXPAND.
Wait for the stack and all nested stacks to complete (approximately 3-5 minutes).
Once the RootStack deployment is complete, go to the Outputs tab in the CloudFormation console. You will need these values to configure the frontend application.
Update src/configs/aws_exports.ts with your specific values:
export const config = {
aws_project_region: 'us-east-1', // Update if deployed elsewhere
aws_cognito_region: 'us-east-1',
aws_user_pools_id: 'REPLACE_WITH_GlobalCognitoUserPoolId',
aws_user_pools_web_client_id: 'REPLACE_WITH_GlobalCognitoClientId',
};Update src/configs/configs.tsx:
export const API_URL = 'REPLACE_WITH_GlobalApiUrl';Install dependencies and build the project:
npm install
npm run buildThis will create a dist folder. Upload the contents of this folder to the frontend S3 bucket created by the stack (check the FrontendStack resources or outputs for the bucket name, usually formatted as frontend-serene-<suffix>).
aws s3 sync dist/ s3://<frontend-bucket-name>The Amazon Lex bot requires a manual build step to be fully active.
- Go to the Amazon Lex console.
- Select SereneBot.
- Navigate to Deployments -> Aliases.
- Select
TestBotAlias. - Under Languages, click on English (US).
- Ensure the Lambda function
bot-function-sereneis selected as the source. Save. - Go to Bot versions -> Intents.
- Click Build (top right corner).
- Wait for the build to complete.
Open the GlobalFrontendUrl (found in RootStack Outputs) in your browser. You can now chat with Serene to book appointments.
-
Check the inbox of the email provided during deployment for a temporary password.

-
Log in to the frontend using the
adminusername and the temporary password.
-
Once logged in, verify your email if requested.
-
You will have access to the dashboard to approve or reject pending meeting requests.

To remove the application and avoid incurring future charges:
- Empty S3 Buckets: You must manually empty the deployment bucket and the frontend hosting bucket. CloudFormation cannot delete non-empty buckets.
- Delete CloudFormation Stack: Delete the
RootStack. This will automatically delete all nested stacks and associated resources.





