Note: the visuals in this demo recording have since been refreshed with sharper brand assets. The conversation flow is identical to what you'll get from a fresh clone.
What's inside
- Browse and book available rooms with rich card carousels
- Order room service from a paginated menu
- RSVP to on-property events and activities
- Browse amenities — spa, gym, pool, restaurants
- Per-guest cart and reservation state
A hotel concierge chatbot that runs entirely over RCS. Guests can check in, browse and book rooms, order room service, RSVP to on-property activities, view the hotel map, and explore amenities — all from inside the messages app.
This guide walks you from a fresh clone to a working hotel demo in under 10 minutes.
What you'll build
- A Pinnacle RCS agent that handles check-in, bookings, dining, activities, and amenities
- Per-guest cart and reservation state in memory (swap for Postgres in prod)
- Multi-step booking flow with date pickers and confirmation
- Activity RSVP with capacity tracking
- Hotel map and parking info pulled from a single brand file
Prerequisites
- Node.js 18+
- A Pinnacle account — sign up. Add an RCS test agent for development
- An API key and a webhook signing secret
1. Clone and install
git clone https://github.com/pinnacle-samples/Alpenglow-Resorts
cd Alpenglow-Resorts
npm install2. Configure environment
cp .env.example .envPINNACLE_API_KEY=your_pinnacle_api_key_here
PINNACLE_AGENT_ID=your_agent_id_here
PINNACLE_SIGNING_SECRET=your_signing_secret_here
TEST_MODE=false
PORT=30003. Expose your webhook
ngrok http 30004. Connect the webhook
In the Webhooks dashboard:
- Add
https://<your-tunnel-domain>/webhook - Attach it to your RCS agent
- Copy the signing secret into
PINNACLE_SIGNING_SECRET
5. Run it
npm run devSend MENU or START to your agent. You'll see the Alpenglow Resorts landing card with Book a Room, Room Service, Events & Activities, Hotel Info, Amenities, and Check In entry points.
How the pieces fit together
Alpenglow-Resorts/
├── server.ts # Express bootstrap
├── router.ts # /webhook POST — verifies + dispatches
├── lib/
│ ├── rcsClient.ts # PinnacleClient instance
│ ├── baseAgent.ts # Shared send + typing helpers
│ ├── typing.ts # Fire-and-forget typing indicator
│ ├── agent.ts # AlpenglowAgent — every action handler
│ └── data.ts # Rooms, room service menu, activities, amenities, guests
Action handlers
| Action | What it does |
|---|---|
showMainMenu | Landing card with all entry points |
checkIn | Existing-reservation check-in flow |
bookRoom / selectDates / selectCheckOutDate / confirmBooking | Multi-step booking |
roomService / addToOrder / placeOrder / clearCart | Room service ordering |
eventsActivities / bookActivity / confirmActivity | Activity RSVP |
showAmenities | Amenities carousel |
hotelInfo / hotelMap / parkingInfo | Property info cards |
Customize the property
lib/data.ts exports availableRooms, roomServiceMenu, eventsActivities, and amenities — all plain arrays of objects. Swap them for your own property and the rich card carousels rebuild on the next message.
For example, add a new room:
{
id: 'penthouse-suite',
name: 'Penthouse Suite',
price: 899,
description: '2 King Beds • 1200 sq ft • Panoramic Views',
amenities: ['Private Terrace', 'Soaking Tub', 'Personal Concierge'],
media: 'https://yourcdn.com/penthouse.jpg',
}bookRoom iterates over availableRooms directly, so your new room appears immediately.
Per-guest state
guests is a Map<phoneNumber, Guest> that holds the active reservation and room service cart. Replace it with a real DB for production — every handler flows through a getOrCreateGuest(from) helper so the swap is mechanical.
Going to production
- Set
TEST_MODE=falseand submit your agent for carrier approval - Wire reservations to your PMS (Opera, Mews, Cloudbeds)
- Replace the in-memory
guestsMap with Postgres - Use proactive RCS messages for check-in reminders, loyalty offers, and post-stay surveys
Resources
- Repo: github.com/pinnacle-samples/Alpenglow-Resorts
- Docs: docs.pinnacle.sh
- Dashboard: app.pinnacle.sh/dashboard
- Support: founders@trypinnacle.app

