Skip to content

Instantly share code, notes, and snippets.

@josephfusco
Last active June 5, 2025 14:56
Show Gist options
  • Save josephfusco/9b6547cf1138e7db7bdfcf01b70f2253 to your computer and use it in GitHub Desktop.
Save josephfusco/9b6547cf1138e7db7bdfcf01b70f2253 to your computer and use it in GitHub Desktop.
// Word lists
const nounsOpenSource = [
'Fork', 'Commit', 'Patch', 'Module', 'Branch', 'Merge', 'Token', 'Kernel', 'Repo', 'Hook'
];
const nounsWordPress = [
'Plugin', 'Theme', 'Block', 'Template', 'Dashboard', 'Widget', 'Post', 'Page', 'Core', 'Loop'
];
const nounsHeadless = [
'GraphQL', 'API', 'Endpoint', 'Resolver', 'Payload', 'Schema', 'Client', 'Cache', 'TokenAuth', 'Webhook'
];
const adjectivesPopCulture = [
'Matrix', 'Mandalorian', 'Skywalker', 'Stark', 'Gandalf', 'Spock', 'Kenobi',
'X-Men', 'Hobbit', 'Neo', 'Vulcan', 'Lannister', 'Sith', 'Potter'
];
const nounsDnDGame = [
'Dungeon', 'Quest', 'Boss', 'Mana', 'Crit', 'XP', 'Potion', 'Loot', 'Spell', 'Dragon',
'Blade', 'Warlock', 'Rogue', 'Knight', 'Tavern'
];
const modifiersFantasy = ['Ancient', 'Cursed', 'Lost', 'Arcane', 'Forgotten', 'Infernal'];
const templates = [
'{adj} and the {game} of the {wp}',
'The {game} of {adj}\'s {wp}',
'{open} in the {game} of {adj}',
'Chronicles of {adj}: The {mod} {game}',
'{mod} {wp} of the {headless} {game}',
'The {mod} {game} of {adj} the {open}'
];
const emojiMap = {
'Warlock': 'πŸ§™β€β™‚οΈ',
'Spell': 'πŸͺ„',
'Blade': 'πŸ—‘οΈ',
'Rogue': 'πŸ—‘οΈ',
'Knight': 'πŸ›‘οΈ',
'Boss': 'πŸ‰',
'Dragon': '🐲',
'Dungeon': '🏰',
'Tavern': '🍺',
'Mana': 'πŸ’«',
'XP': 'πŸ“ˆ',
'Potion': 'πŸ§ͺ',
'Loot': 'πŸ’°'
};
function pickRandom(arr, seen = new Set()) {
const options = arr.filter(item => !seen.has(item));
const choice = options.length > 0 ? options[Math.floor(Math.random() * options.length)] : arr[Math.floor(Math.random() * arr.length)];
seen.add(choice);
return choice;
}
function titleCase(str) {
return str.replace(/\w\S*/g, w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase());
}
function generateSprintName(usedWords) {
const template = pickRandom(templates);
const adj = titleCase(pickRandom(adjectivesPopCulture, usedWords));
const open = titleCase(pickRandom(nounsOpenSource, usedWords));
const wp = titleCase(pickRandom(nounsWordPress, usedWords));
const headless = titleCase(pickRandom(nounsHeadless, usedWords));
const game = titleCase(pickRandom(nounsDnDGame, usedWords));
const mod = titleCase(pickRandom(modifiersFantasy, usedWords));
const raw = template.replace(/\{(\w+)\}/g, (_, key) => ({ adj, open, wp, headless, game, mod }[key]));
const emoji = emojiMap[game] || '';
return `${emoji} ${raw}`.trim();
}
function generateSprintBoard(count = 10) {
const seen = new Set();
const board = [];
while (board.length < count) {
const name = generateSprintName(seen);
if (!board.includes(name)) {
board.push(name);
}
}
return board;
}
// Run it
generateSprintBoard(5).forEach((name, i) => console.log(`${i + 1}. ${name}`));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment