Planning Poker (also known as Scrum poker) is a popular consensus-based technique to estimate efforts of user stories in Scrum. Each team member is given a set of numbered cards, which they use to provide their estimate for a story. The final estimate can be the average of the estimates provided by each team member, or sometimes the process is repeated until a consensus is formed.

Now that many teams are working remotely, the use of physical cards is not practical, and the use of chat windows to share individual estimates is messy and difficult to track. In this blog post, we introduce the Salesforce Planning Poker App and share highlights about the app architecture.

Introducing the Planning Poker app

This free and open-source app allows you to utilize Planning Poker for your planning and is built on Salesforce. You can install the app in any of your orgs (Production, Sandbox, Scratch Orgs, Developer Edition, etc.) by following the instructions from the readme file on the GitHub repo. As it is open-source, you can also fork the repo, and customize the app to match your unique needs.

Check out the app and its source code here.

Once you install the app, you can host a game using the “Host Planning Poker” Lightning app. Each game has a unique Game Pin using which players can use to join and participate.

Players who have a valid Salesforce login to your org can use the “Play Planning Poker” Lightning app to enter a game using the Game Pin.

In cases where you don’t have enough licensed users, or you don’t want to create new Salesforce users for your players, you can install the guest version of the player app on Heroku to allow players without Salesforce Licenses to participate.

You’ll need a free Heroku account to set it up. A free account lets you run the game with a small group of guest players. If you run the game with a larger group, consider upgrading to a Hobby Dyno. Instructions to deploy the guest app to Heroku is also present in the readme file on the GitHub repo.

Planning Poker app features

Here are some salient features of the app:

Choose your own User Story Source

When setting up a new game, the app allows you to select any Salesforce object to be the source of the list of user stories. For example, it can be a custom object that you created, or it can be an object from a managed package like the Agile Accelerator. If you don’t currently have any object for user stories, the Planning Poker app provides a custom object called “Backlog Items” with a few fields that you can use. Finally, you can also choose a field from the object where the Planning Poker app will save the final estimate (consensus). This feature allows you to plug in this app to any kind of workflow you have and saves you a lot of manual effort of keeping track of the estimates and what stories are yet to be estimated.

Use predefined card sets or create your own

This app comes with predefined card sets like Fibonacci and multiples of two. You can also create your own custom card sets using the custom metadata type “Card Sets”.

Host controls

During the game, the host has options to reset the timer, reset cards (clears player responses for the current story), reveal, or hide the player cards. The host can also choose whether or not a timer is shown during the game. All player’s responses are hidden until the timer runs out or until the host chooses to reveal them. The host can also vote in the game if they so choose.

Technical architecture

The Planning Poker app consists of two Lightning apps (Host app and Player app) and an optional Heroku app which you only need to install if you have players that don’t have access to your org. The below diagram summarizes the architecture of both apps.

Lightning Web Components everywhere

The host app and player app on Salesforce are built using Lightning Web Components (LWC), and the Heroku app is built using Lightning Web Components Open Source (LWC OSS). The components have been built keeping reusability in mind. For example, the user interface that shows the poker cards and the votes cast by other players is common across the Host app, Player app, and Heroku app, therefore the components for those have been reused.

The app also uses an Object Agnostic design. Since the source object of the user stories is dynamic, the app uses the getListUI wire adapter to get the story records. The advantage of using this adapter over building a dynamic SOQL query is that when retrieving records, the filter conditions can be configured declaratively using list views instead of custom building the same logic.

The Planning Poker Heroku app is a Single Page Application (SPA) that exposes different URLs for players to join a game. Players can go to <app_name>, enter the game pin and join the game. Games also have dedicated URLs in the form of <app_name><gameId> which can be used to join the game directly. To support this, the app makes use of a routing library LWCE-Router, which has been built for LWC using LWC.

State maintenance

Estimate discussions rarely happen in a single sitting without any interruptions like coffee breaks, network issues, session expirations, and many more which prompt the user to either refresh their page or log back in. To ensure that users pick up exactly where they left off before the interruption, it’s important to preserve the game state. The app uses a combination of Salesforce data and HTML 5 Local Storage to maintain game state.

A few attributes of the game like the current user story being estimated, the timer start time, and so on need to be saved, which the app does using custom fields like Current_Story_Id__c, Timer_Timestamp__c on the Game object. On the Heroku app, HTML5 Local storage is used to store the Id of the player, so that players don’t have to keep entering their name each time they’re interrupted. Check out this file to know more.

In-app and cross-app communication

On Salesforce, the components on the “Host Planning Poker” page use Lightning Message Service to communicate with each other. Each action that the host performs like starting/ending a game, hiding/revealing Cards, and navigating to the next story triggers a Platform Event Game_State_Change__e that the player apps on Salesforce and Heroku subscribe to. Push Topics on the Player__c and Player_Response__c objects are used to automatically update the UI each time a player joins or submits a vote.

On Heroku, LWC is used on the client-side and Node.js is used on the server-side. The Node.js server acts as a proxy between Salesforce and LWC. The node app uses an OAuth JWT Bearer flow to establish a session with Salesforce.
The node server exposes a few endpoints to the LWC client. These endpoints forward client calls to custom Apex REST APIs. This way, sensitive information like the Salesforce session Id, client secrets, and so on, are not exposed to the client.

Node.js also subscribes to PushTopics and Platform Events to receive updates from Salesforce. These updates are sent from node to the LWC app using Server Sent Events (SSE). The SSE connection is kept alive by a ping/heartbeat sent by the server every 30 seconds.


Now that you’ve learned about the Planning Poker app’s features and architecture, how about giving it a try? Check out the app and its source code and let me know what you think. You can report any issues you find, or even submit Pull Requests if you’ve added a new feature or fixed a bug.

Can’t wait for you to try it out.


About the author

Aditya Naag Topalli is a 13x Certified Lead Developer Evangelist at Salesforce. He focuses on Lightning Web Components, Einstein Platform Services, and integrations. He writes technical content and speaks frequently at webinars and conferences around the world. Follow him on Twitter @adityanaag and checkout his contributions on GitHub.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS