This is a prototype to fill in the gap that Planning Poker has left. Copilot was used for 100% of this prototype.
One of the biggest benefits for using Planning Poker was the anonymity of the estimates which generated conversations. Otherwise I observed others would defer to the leads or to whomever spoke first. This prototype is to give the same experience:
- All necessary information displayed from Jira
- Anonymous voting
Additionally I wanted this to be as simple as possible for my developers without having to learn a new system.
- Anonymous voting
- Import Jira cards from a Jira filter
- Import Jira cards from CSV (formatting is important)
- Add Jira cards on the fly
- See previous vote when re-voting
- Extenisble to T-Shirt sizing and other estimating values
- Running tally of cards estimated in session
- Teams bot (still need access to create one)
- Fix UI width
- Edit participants
- If Jira issue fields contain Figma links, up to 3 embeds are shown in the Jira details panel.
- Users can connect their own Figma account via in-app OAuth before viewing embeds.
- Auth tokens are stored server-side in
.figma-auth-store.json(encrypted withFIGMA_TOKEN_ENCRYPTION_KEY).
Planning Poker app with:
- A Teams bot for chat-driven estimation rounds
- A Teams tab/web UI for interactive voting
- Local simulation and smoke-test scripts for rapid validation
bot.js- Core bot logic and command handlingindex.js- Bot server entry point (/api/messages,/health)chat.js- Interactive local terminal chat with the botmulti-user-sim.js- Multi-user local simulationsmoke-test.js- Basic end-to-end bot smoke testmanifest.json- Microsoft Teams app manifestplanning-poker-ui/- React + Vite frontend
- Node.js 18+ (recommended)
- npm
- Azure Bot registration (for Teams integration)
- Optional: Jira cloud credentials for
/poker jiraand filter imports
Install dependencies from the repository root:
npm install botbuilder express body-parser dotenvCreate a .env file in the root:
MicrosoftAppId=your_bot_app_id
MicrosoftAppPassword=your_bot_app_password
PORT=3978
# Optional Jira integration
JIRA_BASE_URL=https://yourorg.atlassian.net
JIRA_BEARER_TOKEN=your_token
# OR
# [email protected]
# JIRA_API_TOKEN=your_api_token
# JIRA_ACCEPTANCE_CRITERIA_FIELD=customfield_10039
# Optional Figma OAuth (required for in-app Figma embeds)
# Create an OAuth app in Figma and set callback to:
# http://localhost:3978/api/figma/auth/callback
FIGMA_CLIENT_ID=your_figma_client_id
FIGMA_CLIENT_SECRET=your_figma_client_secret
FIGMA_REDIRECT_URI=http://localhost:3978/api/figma/auth/callback
FIGMA_SCOPE=file_content:read
FIGMA_TOKEN_ENCRYPTION_KEY=use_a_long_random_secret_hereStart the bot server:
node index.jsHealth check:
curl http://localhost:3978/healthcd planning-poker-ui
npm install
npm run devOptional frontend env (planning-poker-ui/.env):
VITE_API_BASE_URL=http://localhost:3978Build for production:
npm run build
npm run previewInteractive single-user REPL:
node chat.jsMulti-user simulation:
node multi-user-sim.js
node multi-user-sim.js --story "PROJ-123" --users 6 --revealSmoke test:
node smoke-test.js/poker help/poker start [story title]/poker vote <value>/poker reveal/poker next [story title]/poker load/poker status/poker deck/poker add <value>/poker jira <ISSUE-123>/poker end
- Update placeholder values in
manifest.json:YOUR-DOMAINYOUR-BOT-APP-ID-HERE- developer URLs and metadata
- Host tab content and bot endpoint on HTTPS for Teams usage.
- Ensure
contentUrl/websiteUrlin the manifest point to your deployed tab route.
- Session state is currently in-memory (
Mapinbot.js), so state resets on restart. - For production, replace in-memory storage with a persistent store (Redis/Cosmos DB/etc.).
- There is a certificate that you will need in order to hit the corporate version of Jira. If you see "failed fetch" and a 404 in the console when getting tickets via filters, this cert needs to be made
- If you can't make the cert, you can run the following command
$env:NODE_TLS_REJECT_UNAUTHORIZED = "0"in the root directory of the project and it will ignore the lack of certs. This is very insecure, so should ONLY be used for local development, never deployment
- If you can't make the cert, you can run the following command
Internal project.