Errors and logs
Logs
What happened, told to whoever runs the app: audit, security, incident, job and debug intents, recorded with log().
Why
A console.error says nothing about who needs to know. Is it an incident someone should look at, a security signal, a record of who did what, or leftover debugging? Without that, everything is printed at the same volume, alerts are either missing or noisy, and secrets end up in logs. Logs apply everywhere: servers, browser code, background jobs and scripts, so this profile stands on its own.
} catch (error) {
console.error('[ArticlePage] Failed to load related articles:', error);
}} catch (error) {
log('incident.degraded', 'Article rendered without related articles', { slug, cause: error });
}Set it up
npx prongs add logsAdds the logs profile and its starter intents, and copies log() into components/prongs/log.ts. Point its write function at your logger or error tracker; it receives the intent, the level and whether to alert.
The types of log
Pick the type by who needs to know, then the event within it. Each domain has its own page.
audit.createdSomeone created something that matters later: an account, a page, an API key
info levelaudit.changedSomeone changed something that matters: settings, a role, a published page
info levelaudit.deletedSomeone deleted something: a page, an account, content
info levelaudit.signedinSomeone signed in, the ordinary way
info levelaudit.signedoutSomeone signed out
info level
security.signinA sign-in failed, or succeeded from somewhere unusual
warn levelsecurity.tokenA bad or expired token, secret or signature was presented
warn levelsecurity.limitedA caller hit a rate limit
warn level
incident.failedSomething broke and someone should look: a request, a job, a dependency
error level · alertsincident.degradedIt worked, but worse than it should: a fallback, a retry, a slow dependency
warn level
job.startedA background job or script began: a sync, a backup, a migration
info leveljob.finishedA job ended, with what it did: counts, duration
info level
debug.traceDetail for working on the code
debug level · not in production
Using log()
import { log } from '@/components/prongs/log';
log('audit.deleted', 'Page deleted', { pageId, by: user.id });
log('security.token', 'Preview secret did not match', { ip });
log('incident.degraded', 'Search fell back to the cached index', { tookMs });
log('job.finished', 'Redirects synced', { count: entries.length });log(intent, message, data?) writes one structured entry. Levels live in ref-only level.* intents; level.debug is dropped in production. Errors in data become their name, message and stack, and anything under a key that looks like a secret is replaced.