How to Monitor Hallmark Performance: Complete Guide to Static Site Telemetry
Use the browser's native Performance API to capture runtime metrics like First Contentful Paint (FCP), Largest Contentful Paint (LCP), and animation frame durations, while adhering to the GPU-composited animation rules defined in the Hallmark skill.
Hallmark is a design skill in the Nutlope/hallmark repository that generates static HTML and CSS pages governed by 57 "slop-test" performance gates. Because the output is purely client-side markup without server-side processing, monitoring Hallmark performance requires leveraging native browser APIs like performance.now() and PerformanceObserver rather than backend telemetry. This guide covers the exact implementation patterns found in the source code to measure, log, and enforce performance standards.
Why Monitor Hallmark Performance?
Hallmark outputs static pages, which means performance bottlenecks arise from client-side rendering rather than database queries or server response times. The primary concerns involve First Contentful Paint (FCP), Largest Contentful Paint (LCP), and animation frame rates.
According to the source analysis, the repository enforces strict performance boundaries through "slop-test" gates defined in SKILL.md. Monitoring ensures your generated pages stay within these thresholds and maintain the performance-first philosophy documented in skills/hallmark/references/motion.md.
Core Monitoring Techniques
Capturing Runtime Timestamps
The simplest way to monitor Hallmark performance is recording timestamps at key lifecycle moments. In site/js/main.js, the codebase demonstrates this pattern by capturing performance.now() at the start of animation loops to calculate elapsed time.
// Record when the page starts loading
const pageStart = performance.now();
// Measure specific operation duration
const start = performance.now();
// ... animation or layout operation ...
const duration = performance.now() - start;
console.log('Operation took:', duration.toFixed(2), 'ms');
This approach provides microsecond-precision timing for any arbitrary code block without external dependencies.
Observing Paint Metrics (FCP and LCP)
For Web Vitals monitoring, use PerformanceObserver to capture paint metrics as they occur. This pattern detects when critical content becomes visible to users.
// Listen for First Contentful Paint
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'first-contentful-paint') {
console.log('FCP:', entry.startTime.toFixed(2), 'ms');
}
}
}).observe({ type: 'paint', buffered: true });
// Capture overall load time at page exit
window.addEventListener('beforeunload', () => {
const loadTime = performance.now() - pageStart;
console.log('Total page load time:', loadTime.toFixed(2), 'ms');
});
Measuring Animation Frame Rates
Hallmark emphasizes smooth animations, making frame timing critical. Use requestAnimationFrame combined with performance.now() to detect jank or dropped frames.
function logAnimationFrame() {
const start = performance.now();
requestAnimationFrame(() => {
const frameDuration = performance.now() - start;
console.log('Animation frame duration:', frameDuration.toFixed(2), 'ms');
// Target: ~16.67ms for 60fps
if (frameDuration > 16.67) {
console.warn('Frame dropped');
}
});
}
Performance-First Animation Rules
As documented in skills/hallmark/references/motion.md, Hallmark follows a GPU-composited only policy. This means animations must exclusively use transform and opacity properties. Any animation involving width, height, margin, or other layout-triggering properties causes reflows and degrades frame rates.
/* ✅ GPU-accelerated: Uses transform and opacity only */
.optimal-animation {
animation: slide 1s infinite;
}
@keyframes slide {
from { transform: translateX(0); }
to { transform: translateX(100px); }
}
/* ❌ Avoid: Triggers layout and paint */
.poor-performance {
animation: expand 1s infinite;
}
@keyframes expand {
from { width: 100px; }
to { width: 200px; }
}
Adhering to these rules is essential because monitoring reveals problems that these animation constraints are designed to prevent.
Implementing a Monitoring Pipeline
Client-Side Instrumentation
Combine timestamp capture with metric reporting to build a complete monitoring solution. The following implementation mirrors the pattern found at line 990 of site/js/main.js:
// Comprehensive performance monitoring
const perfMetrics = {
pageStart: performance.now(),
fcp: null,
lcp: null
};
// Observe paint metrics
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'first-contentful-paint') {
perfMetrics.fcp = entry.startTime;
}
}
}).observe({ type: 'paint', buffered: true });
// Long task detection (helps identify blocking JavaScript)
new PerformanceObserver((list) => {
list.getEntries().forEach(entry => {
console.warn('Long task detected:', entry.duration.toFixed(2), 'ms');
});
}).observe({ type: 'longtask', buffered: true });
// Report on unload
window.addEventListener('beforeunload', () => {
const totalTime = performance.now() - perfMetrics.pageStart;
// Send to analytics endpoint or logging service
console.log('Performance Report:', {
totalLoadTime: totalTime,
fcp: perfMetrics.fcp,
timestamp: new Date().toISOString()
});
});
Automated CI with Lighthouse
Because Hallmark generates static files under site/_tests/, you can automate performance monitoring using Lighthouse CI. Configure your package.json scripts to run audits against generated pages and enforce the slop-test thresholds.
{
"scripts": {
"perf:audit": "lighthouse-ci --config=lighthouserc.js"
}
}
This ensures that FCP and LCP metrics remain below the gate thresholds defined in the skill rules before deployment.
Key Source Files for Performance Monitoring
site/js/main.js: Contains the reference implementation usingperformance.now()for animation frame timing (around line 990).skills/hallmark/references/motion.md: Documents the strict animation guidelines limiting effects to GPU-composited properties.SKILL.md: Defines the 57 slop-test performance gates and thresholds that your monitoring should validate against.README.md: Provides installation steps and overview of the performance monitoring philosophy.package.json: Houses npm scripts extensible for Lighthouse CI integration.
Summary
- Use
performance.now()to capture microsecond-precision timestamps at page load and animation start points, following the pattern insite/js/main.js. - Monitor Web Vitals (FCP, LCP) using
PerformanceObserverto track when critical content renders. - Restrict animations to
transformandopacityonly, as required byskills/hallmark/references/motion.md, to prevent layout thrashing. - Implement Long Task observation to detect blocking JavaScript that degrades frame rates.
- Automate validation with Lighthouse CI against the slop-test thresholds defined in
SKILL.md.
Frequently Asked Questions
How do I measure First Contentful Paint in Hallmark projects?
Use the PerformanceObserver API to listen for paint events. Because Hallmark outputs static HTML, FCP occurs as soon as the browser renders the first text or image element. The observer pattern with { type: 'paint', buffered: true } captures this metric even if your script loads after the initial paint.
What is the "slop-test" performance gate mentioned in the Hallmark skill?
The slop-test refers to 57 specific performance thresholds defined in SKILL.md that govern acceptable latency, bundle size, and rendering metrics. Monitoring tools should validate that FCP, LCP, and animation frame rates stay within these boundaries to ensure the generated site meets the skill's quality standards.
Why can't I animate properties like width or height in Hallmark?
As documented in skills/hallmark/references/motion.md, animating layout properties triggers browser reflow and repaint cycles, which degrade frame rates on static sites. Hallmark enforces a GPU-composited-only policy (transform and opacity) to maintain 60fps performance. Monitoring will reveal these bottlenecks if you accidentally use non-compliant CSS.
Can I use third-party libraries like web-vitals with Hallmark?
Yes. While the core examples use native browser APIs, you can import libraries like web-vitals to simplify metric collection. Since Hallmark generates standard static HTML, any client-side performance library works, though the native PerformanceObserver and performance.now() methods provide sufficient granularity for most use cases without adding bundle weight.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →