< Back

From Vibes to Vacation: Build a Mood-Based Travel API with AWS SAM & TypeScript

Author

Chania Beké

Date

07/01/2026

Share this article

Hello developers, wanderlusters and people who really need a vacation. Ever stared at your screen thinking “Where should I go next?” Same. So I built an API that picks a travel destination based on your mood and budget, no thinking required. It’s serverless (thanks, AWS SAM), written in TypeScript, and runs like a dream on Lambda.

Feel romantic? Try Slovenia. Offbeat? Uzbekistan. Broke but beachy? Albania’s calling. This API gets your vibe and sends you packing.

What Even Is AWS SAM and Lambda?

AWS Lambda lets you run backend code without touching servers, it runs when needed and scales automatically. AWS SAM (Serverless Application Model) makes setting all that up ridiculously easy. It handles the messy stuff like creating IAM roles, permissions, and API Gateway connections for you. You define everything in one YAML file, and with a single command, SAM builds and deploys your app. If you're new to serverless or just want to move fast without fighting AWS configs, SAM has your back.

Prerequisites: Let’s Set the Stage

Before we build our mood-matching travel genie, let’s get your setup ready. Nothing too complicated, just the essentials (and a few nice-to-haves).

Node.js & npm – Our JavaScript/TypeScript backbone

Install from: nodejs

Check it's working:

node -v
npm -v

AWS CLI (with SSO – because passwords are so last season)

We’re using AWS SSO (aka IAM Identity Center) to log in, no messy access keys, no drama. Install AWS CLI

Set it up with SSO:

aws configure sso

You’ll be prompted to: - Enter your SSO start URL (from your AWS org) - Choose the AWS account & role - Pick a default region (e.g eu-west-1)

Log in when needed:

aws sso login

Easy, secure, and way less painful than juggling keys.

Docker (Optional but recommended) - For local testing

SAM uses Docker to simulate the Lambda runtime on your machine. Install docker desktop

Verify it’s running:

docker --version

IAM Permissions - So AWS lets you actually do stuff

Make sure the IAM role you log into via SSO can: - Create and update Lambda functions - Create IAM roles - Deploy CloudFormation stacks - Access S3 (SAM uses it to upload deployment files)

If you’re using SSO in a team setup, your admin probably has you covered, but it’s always good to double-check.

Code Editor (Optional but highly recommended)

VS Code is your bestie here. Bonus points if you install the AWS Toolkit extension, makes it super easy to browse resources, test Lambdas, and deploy.

Let’s Start with the Basics: Templates, Commands & Setup

Time to spin up our project using SAM’s built-in starter templates. I like starting with the TypeScript Hello World, it gives us a clean slate with just enough boilerplate to not feel lost.

Create the Project

sam init

Then go with these options: - Template source: 1 - AWS Quick Start Templates - Template type: 1 - Hello World Example - Use most popular runtime? No (we want to use Typescript) - Runtime: nodejs22.x (as of now, the latest supported) - Package type: Image - Starter template: Hello World Example TypeScript - Would you like to enable X-Ray/monitoring/testing? No to all (we’re keeping it simple and keeping our AWS bill low) - Project name: Wanderlamb

This will generate the base project folder with a sample Lambda function, Docker setup, and TypeScript support baked in, perfect for what we’re building.

Essential Commands

sam build - Compile & Prepare Your Code

This command compiles your TypeScript code and prepares your project for deployment or local testing.

sam build

It takes your .ts files and converts them into .js, bundles your dependencies, and outputs everything into the .aws-sam/build/ folder so SAM knows what to deploy or run locally.

Heads Up! Anytime you change: - Your Lambda function code - The template.yaml file - Add a new function - Update environment variables or API paths

You must run sam build again to see the changes locally or deploy the latest version. Don’t skip it, or you’ll be wondering why your function still acts like it's 3 commits behind

sam validate - Sanity Check Your Template

Want to make sure your template.yaml is actually valid before deploying? Run:

sam validate

This checks your syntax and resources so you don’t hit errors later on.

Docker Required for Local Testing

!Important: If you're running your Lambda functions locally, you’ll need to have Docker Desktop running, SAM uses it to simulate the Lambda runtime.

sam local invoke – Test One Function with Mock Data

Want to test your function with a sample event? Use:

sam local invoke HelloFunction --event events/event.json

Replace HelloFunction with your actual function name (e.g. WanderLamb) and customize event.json with your test payload.

sam local start-api – Test the Full API Locally

To spin up a local API Gateway (great for using Bruno), Run:

sam local start-api --skip-pull-image -p 4000

This serves your API on http://localhost:4000/ and skips downloading the runtime Docker image again (which speeds things up).

Create an S3 Bucket – Where SAM Stores Stuff

Before deploying, you need an S3 bucket for SAM to upload your Lambda package.

sam deploy --guided – Your First Deployment

This command walks you through setting everything up for your first deploy:

sam deploy --guided

It will ask for: - Stack name (your app name) - Region (e.g. eu-west-1) - S3 bucket (use the one you created) - Permissions confirmation (say "Y" to allow SAM to create roles for you)

samconfig.toml – Save Your Deploy Settings

After your first deploy, SAM saves your answers to samconfig.toml so future deploys are one-liners:

sam deploy

To avoid errors, make sure this section exists in your samconfig.toml:

resolve_s3 = false
s3_bucket = "wanderlamb-bucket"

This tells SAM: “Hey, I already have an S3 bucket, no need to auto-create one for me.”

From Hello World to WanderLamb

Okay, the “Hello World” thing was cute, but we’re building WanderLamb, a vibe-matching travel API that actually does something.

What Changed (and Why)

Resources:
  WanderLambFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: wanderLamb/
      Events:
        WanderLamb:
          Type: Api
          Properties:
            Path: /travel
            Method: get

So now when you hit: /travel?maxBudget=40&mood=wild-life …it serves actual recommendations.

How It Works (No Boring Stuff):

  • Pulls your query params like mood=wild-life and maxBudget=40

  • Filters the destinations list (yep, we’ve got one)

  • If there's a match, it picks one at random

  • If not, it sends a polite “nothing found”

  • Sends a clean JSON response back to you Here’s the the logic:

export const lambdaHandler = async (event: APIGatewayEvent): Promise<APIGatewayProxyResult> => {
    try {
        const query: RequestQuery = parseQueryParams(event.pathParameters || {});

        const filtered = filterByMood(filterByBudget(destinations, query.maxBudget), query.mood);

        if (filtered.length === 0) {
            return buildErrorResponse(404, 'No destinations match your filters.');
        }

        const result = getRandomItem(filtered);
        return buildDestinationResponse(result);
    } catch (error) {
        console.error('Error processing request:', error);
        return buildErrorResponse(500, 'Internal server error.');
    }
};

More code lives on our github space, if you wanna see all the goodies.

That’s a Wrap - Let’s Run It!

You built it, tested it, and deployed it, now it’s time to see WanderLamb in action. Fire up your local API, throw in a mood and a budget, and let the cloud do its thing.

Tudum, your next destination? Chile. Dry desert air, starry skies in the Atacama, and a warm plate of pastel de choclo waiting for you.

No logins. No spreadsheets. Just pure travel vibes, powered by TypeScript and a bit of serverless magic. Happy wandering!