Recipes
Common patterns for reports, automation, monitoring, and multi-guild setups.
Practical examples for common use cases beyond basic sync operations.
Generate a monthly report
Use date range helpers to build activity reports:
import { getCardsFromLastMonth, getProvider, isProviderReady } from '@robojs/roadmap'
export default async function monthlyReport(interaction) {
if (!isProviderReady()) {
return 'Provider not configured.'
}
const provider = getProvider()
const cards = await getCardsFromLastMonth(provider)
const created = cards.filter(c => c.column === 'Backlog')
const completed = cards.filter(c => c.column === 'Done')
const inProgress = cards.filter(c => c.column === 'In Progress')
return [
`**Monthly Report**`,
`Cards updated: ${cards.length}`,
`New: ${created.length} | Active: ${inProgress.length} | Completed: ${completed.length}`
].join('\n')
}import { getCardsFromLastMonth, getProvider, isProviderReady } from '@robojs/roadmap'
export default async function monthlyReport(interaction) {
if (!isProviderReady()) {
return 'Provider not configured.'
}
const provider = getProvider()
const cards = await getCardsFromLastMonth(provider)
const created = cards.filter(c => c.column === 'Backlog')
const completed = cards.filter(c => c.column === 'Done')
const inProgress = cards.filter(c => c.column === 'In Progress')
return [
`**Monthly Report**`,
`Cards updated: ${cards.length}`,
`New: ${created.length} | Active: ${inProgress.length} | Completed: ${completed.length}`
].join('\n')
}Trigger sync from a webhook
Use the REST API to trigger syncs from CI/CD pipelines or external services:
# Trigger sync after a Jira webhook fires
curl -X POST http://localhost:3000/api/roadmap/sync/YOUR_GUILD_IDOr trigger from a custom event handler:
import { syncRoadmap, getProvider } from '@robojs/roadmap'
export default async function onWebhook(guild) {
const provider = getProvider()
if (!provider) return
const result = await syncRoadmap({ guild, provider })
console.log(`Synced ${result.stats.total} cards`)
}import { syncRoadmap, getProvider } from '@robojs/roadmap'
export default async function onWebhook(guild) {
const provider = getProvider()
if (!provider) return
const result = await syncRoadmap({ guild, provider })
console.log(`Synced ${result.stats.total} cards`)
}Monitor provider health
Build a health check dashboard using the REST API:
# Check provider status
curl http://localhost:3000/api/roadmap/provider/status
# Get last sync time
curl http://localhost:3000/api/roadmap/sync/YOUR_GUILD_ID/statusTrack activity over time
Use date range helpers for trend analysis:
import { getCardsFromLastDays, getProvider } from '@robojs/roadmap'
async function weeklyTrend() {
const provider = getProvider()
const thisWeek = await getCardsFromLastDays(provider, 7)
const lastWeek = await getCardsFromLastDays(provider, 14)
// Compare activity between periods
const delta = thisWeek.length - lastWeek.length
return `This week: ${thisWeek.length} cards (${delta >= 0 ? '+' : ''}${delta} vs last week)`
}import { getCardsFromLastDays, getProvider } from '@robojs/roadmap'
async function weeklyTrend() {
const provider = getProvider()
const thisWeek = await getCardsFromLastDays(provider, 7)
const lastWeek = await getCardsFromLastDays(provider, 14)
// Compare activity between periods
const delta = thisWeek.length - lastWeek.length
return `This week: ${thisWeek.length} cards (${delta >= 0 ? '+' : ''}${delta} vs last week)`
}Sync a single card
Sync one card after creation or update without running a full sync:
import { syncSingleCard, getProvider } from '@robojs/roadmap'
const provider = getProvider()
const card = await provider.getCard('PROJ-123')
if (card) {
const result = await syncSingleCard(card, guild, provider)
if (result) {
console.log(`Thread: ${result.threadUrl}`)
}
}import { syncSingleCard, getProvider } from '@robojs/roadmap'
const provider = getProvider()
const card = await provider.getCard('PROJ-123')
if (card) {
const result = await syncSingleCard(card, guild, provider)
if (result) {
console.log(`Thread: ${result.threadUrl}`)
}
}Cancelable sync with progress
Run a sync with progress tracking and cancellation support:
import { syncRoadmap, SyncCanceledError, getProvider } from '@robojs/roadmap'
const controller = new AbortController()
const provider = getProvider()
try {
const result = await syncRoadmap({
guild,
provider,
signal: controller.signal,
onProgress: (update) => {
console.log(`[${update.currentIndex + 1}/${update.totalCards}] ${update.currentCard.title}`)
if (update.stats.errors > 5) {
controller.abort() // Cancel if too many errors
}
}
})
console.log('Sync complete:', result.stats)
} catch (error) {
if (error instanceof SyncCanceledError) {
console.log('Sync canceled')
}
}import { syncRoadmap, SyncCanceledError, getProvider } from '@robojs/roadmap'
const controller = new AbortController()
const provider = getProvider()
try {
const result = await syncRoadmap({
guild,
provider,
signal: controller.signal,
onProgress: (update) => {
console.log(`[${update.currentIndex + 1}/${update.totalCards}] ${update.currentCard.title}`)
if (update.stats.errors > 5) {
controller.abort() // Cancel if too many errors
}
}
})
console.log('Sync complete:', result.stats)
} catch (error) {
if (error instanceof SyncCanceledError) {
console.log('Sync canceled')
}
}Multi-guild management
Each guild has independent settings. Manage multiple guilds programmatically:
import { getSettings, updateSettings } from '@robojs/roadmap'
const guildIds = ['guild-1', 'guild-2', 'guild-3']
for (const guildId of guildIds) {
const settings = getSettings(guildId)
console.log(`${guildId}: last sync ${new Date(settings.lastSyncTimestamp ?? 0)}`)
// Apply consistent settings across guilds
updateSettings(guildId, {
threadTitleTemplate: '[{id}] {title}',
isPublic: true
})
}import { getSettings, updateSettings } from '@robojs/roadmap'
const guildIds = ['guild-1', 'guild-2', 'guild-3']
for (const guildId of guildIds) {
const settings = getSettings(guildId)
console.log(`${guildId}: last sync ${new Date(settings.lastSyncTimestamp ?? 0)}`)
// Apply consistent settings across guilds
updateSettings(guildId, {
threadTitleTemplate: '[{id}] {title}',
isPublic: true
})
}