

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
12345# Frontend Rules67## Browser compatibility89- Maintain compatibility with10 - Google Chrome11 - Microsoft Edge (Chromium based)12 - Mozilla Firefox13 - Apple Safari14 - Desktop and small screen touch devices1516## Assets17- Some javascript related assets18 - Audio player used in HTML templates19 - assets/audioplayer.js20 - Javascript snippets21 - assets/utils.js2223## Frameworks2425### HTMX26- **Attributes:**27 - `hx-get`28 - `hx-post`29 - `hx-trigger`30- **Patterns:**31 - Use `hx-boost` for progressive enhancement32 - Implement partial updates3334### Alpine.js35- **Patterns:**36 - Use `x-data` for component state37 - Implement reactive updates3839## Libraries40- Leaflet for interactive map4142## Styling4344### Tailwind CSS45- **Required:** Yes46- **Extensions:**47 - `daisyUI`48- **Patterns:**49 - Use utility classes50 - Implement responsive design51 - Follow component patterns5253- Custom CSS54 - assets/custom.css5556## Snippets5758### Feature Detection59```javascript60function isFeatureSupported(feature) {61 const features = {62 intersectionObserver: () => 'IntersectionObserver' in window,63 customElements: () => 'customElements' in window,64 pointer: () => 'PointerEvent' in window,65 touch: () => 'ontouchstart' in window66 };67 return features[feature] ? features[feature]() : false;68}69```7071### Polyfill Loader72```javascript73async function loadPolyfills() {74 const polyfills = [];7576 if (!window.IntersectionObserver) {77 polyfills.push(import('intersection-observer'));78 }7980 if (!window.fetch) {81 polyfills.push(import('whatwg-fetch'));82 }8384 if (polyfills.length > 0) {85 await Promise.all(polyfills);86 }87}88```8990### Cross-Browser Event Handling91```javascript92function addCrossBrowserEvent(element, eventName, handler, options = {}) {93 const eventMap = {94 click: ['click', 'touchend'],95 mouseenter: ['mouseenter', 'touchstart'],96 mouseleave: ['mouseleave', 'touchend']97 };9899 const events = eventMap[eventName] || [eventName];100 const { passive = true, ...otherOptions } = options;101102 events.forEach(event => {103 element.addEventListener(event, handler, { passive, ...otherOptions });104 });105106 return () => {107 events.forEach(event => {108 element.removeEventListener(event, handler);109 });110 };111}112```113114### Safe Animation115```javascript116function animate(element, properties, duration) {117 if ('animate' in element) {118 return element.animate(properties, duration).finished;119 } else {120 return new Promise(resolve => {121 Object.assign(element.style, {122 transition: `all ${duration}ms`,123 ...properties124 });125 setTimeout(resolve, duration);126 });127 }128}129```130131### Safe Fetch132```javascript133async function safeFetch(url, options = {}) {134 const controller = new AbortController();135 const timeout = options.timeout || 5000;136137 const timeoutId = setTimeout(() => controller.abort(), timeout);138139 try {140 const response = await fetch(url, {141 ...options,142 signal: controller.signal,143 headers: {144 'Accept': 'application/json',145 ...options.headers146 }147 });148149 if (!response.ok) {150 throw new Error(`HTTP error! status: ${response.status}`);151 }152153 return await response.json();154 } catch (error) {155 if (error.name === 'AbortError') {156 throw new Error('Request timed out');157 }158 throw error;159 } finally {160 clearTimeout(timeoutId);161 }162}163```164165### Safe Storage166```javascript167const safeStorage = {168 get(key) {169 try {170 const item = localStorage.getItem(key);171 return item ? JSON.parse(item) : null;172 } catch (e) {173 console.warn(`Error reading ${key} from storage:`, e);174 return null;175 }176 },177 set(key, value) {178 try {179 localStorage.setItem(key, JSON.stringify(value));180 return true;181 } catch (e) {182 console.warn(`Error writing ${key} to storage:`, e);183 return false;184 }185 },186 remove(key) {187 try {188 localStorage.removeItem(key);189 return true;190 } catch (e) {191 console.warn(`Error removing ${key} from storage:`, e);192 return false;193 }194 }195};196```197198
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| tphakala/birdnet-go.cursor/rules/database.mdc · 1.6k | Cursor rules | databasedo-not | 45/100 | today | |
| tphakala/birdnet-go.cursor/rules/go.mdc · 1.6k | Cursor rules | buildteststylearch+5 | 69/100 | today | |
| tphakala/birdnet-go.cursor/rules/go_test.mdc · 1.6k | Cursor rules | setupteststyletesting-strategy+1 | 56/100 | today | |
| tphakala/birdnet-goAGENTS.md · 1.6k | AGENTS.md | teststylegitdo-not+1 | 78/100 | today | |
| tphakala/birdnet-goCLAUDE.md · 1.6k | CLAUDE.md | buildtestlint-formatstyle+8 | 100/100 | today | |
| tphakala/birdnet-gofrontend/CLAUDE.md · 1.6k | CLAUDE.md | setuptestlint-formatstyle+7 | 84/100 | today | |
| tphakala/birdnet-gofrontend/src/lib/desktop/components/CLAUDE.md · 1.6k | CLAUDE.md | teststylearchui | 70/100 | today | |
| tphakala/birdnet-gofrontend/src/lib/desktop/components/ui/CLAUDE.md · 1.6k | CLAUDE.md | styleuidocs | 54/100 | today | |
| tphakala/birdnet-gofrontend/src/lib/desktop/features/settings/CLAUDE.md · 1.6k | CLAUDE.md | buildstylearchtypes+2 | 66/100 | today | |
| tphakala/birdnet-gofrontend/static/messages/CLAUDE.md · 1.6k | CLAUDE.md | archuido-notagent-behaviour | 67/100 | today | |
| tphakala/birdnet-gofrontend/tools/CLAUDE.md · 1.6k | CLAUDE.md | no sections | 65/100 | today | |
| tphakala/birdnet-gointernal/CLAUDE.md · 1.6k | CLAUDE.md | buildteststylearch+5 | 88/100 | today | |
| tphakala/birdnet-gointernal/api/v2/CLAUDE.md · 1.6k | CLAUDE.md | teststylesecurityapi+1 | 84/100 | today | |
| tphakala/birdnet-gointernal/errors/CLAUDE.md · 1.6k | CLAUDE.md | styleuiperformancedo-not+1 | 61/100 | today |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| bybren-llc/safe-agentic-workflow.cursor/rules/10-backend-python.mdc · 399 | Cursor rules | testlint-formatstylegit+4 | 97/100 | today |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/tphakala-birdnet-go-cursor-rules-frontend)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.