vibes-plug 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  2. package/BLUEPRINT.md +125 -0
  3. package/CHANGELOG.md +195 -0
  4. package/CONTRIBUTING.md +199 -0
  5. package/LICENSE +21 -0
  6. package/README.md +263 -0
  7. package/SECURITY.md +21 -0
  8. package/banner.png +0 -0
  9. package/package.json +25 -0
  10. package/plugin.json +8 -0
  11. package/scripts/update_skills.js +75 -0
  12. package/skills/ai-llm-integration-expert/SKILL.md +162 -0
  13. package/skills/api-design-expert/SKILL.md +310 -0
  14. package/skills/app-analyzer-optimizer/SKILL.md +189 -0
  15. package/skills/asisten_ramah/SKILL.md +41 -0
  16. package/skills/authentication-identity-expert/SKILL.md +45 -0
  17. package/skills/auto-doc-updater/SKILL.md +204 -0
  18. package/skills/bootstrap-to-modern/SKILL.md +87 -0
  19. package/skills/brainstorming/SKILL.md +353 -0
  20. package/skills/bun-runtime-expert/SKILL.md +211 -0
  21. package/skills/ci-cd-devops-architect/SKILL.md +45 -0
  22. package/skills/cloud-hosting-expert/SKILL.md +244 -0
  23. package/skills/coderabbit/SKILL.md +192 -0
  24. package/skills/data-telemetry-expert/SKILL.md +213 -0
  25. package/skills/database-orm-expert/SKILL.md +294 -0
  26. package/skills/design-system-architect/SKILL.md +243 -0
  27. package/skills/e2e-testing-expert/SKILL.md +315 -0
  28. package/skills/event-driven-architect/SKILL.md +81 -0
  29. package/skills/firebase-security-expert/SKILL.md +195 -0
  30. package/skills/fullstack-expert/SKILL.md +202 -0
  31. package/skills/fullstack-expert/references/api_design_guide.md +466 -0
  32. package/skills/fullstack-expert/references/devops_infrastructure.md +477 -0
  33. package/skills/fullstack-expert/references/multi_language_backend.md +528 -0
  34. package/skills/fullstack-expert/references/system_design_patterns.md +358 -0
  35. package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -0
  36. package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -0
  37. package/skills/gemini-agent-booster/SKILL.md +135 -0
  38. package/skills/global-a11y-i18n-expert/SKILL.md +81 -0
  39. package/skills/go-programming-expert/SKILL.md +295 -0
  40. package/skills/hig/SKILL.md +188 -0
  41. package/skills/js-backend-expert/SKILL.md +192 -0
  42. package/skills/mcp-server-architect/SKILL.md +194 -0
  43. package/skills/mobile-expo-expert/SKILL.md +186 -0
  44. package/skills/monday-design-aesthetic/SKILL.md +67 -0
  45. package/skills/monorepo-architect/SKILL.md +227 -0
  46. package/skills/mpa-orchestrator/SKILL.md +101 -0
  47. package/skills/multi-agent-orchestration/SKILL.md +234 -0
  48. package/skills/multiple-entry-points/SKILL.md +55 -0
  49. package/skills/mvc-expert/SKILL.md +231 -0
  50. package/skills/payment-gateway-expert/SKILL.md +45 -0
  51. package/skills/performance-web-vitals/SKILL.md +332 -0
  52. package/skills/prd-architect/SKILL.md +191 -0
  53. package/skills/production-ready-hardener/SKILL.md +469 -0
  54. package/skills/production-ready-hardener/references/performance_optimization.md +441 -0
  55. package/skills/production-ready-hardener/references/production_checklist.md +161 -0
  56. package/skills/production-ready-hardener/references/security_hardening_guide.md +379 -0
  57. package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +875 -0
  58. package/skills/python-programming-expert/SKILL.md +271 -0
  59. package/skills/realtime-collaboration-expert/SKILL.md +45 -0
  60. package/skills/rust-programming-expert/SKILL.md +235 -0
  61. package/skills/saas-billing/SKILL.md +377 -0
  62. package/skills/saas-multi-tenant/SKILL.md +237 -0
  63. package/skills/saas-mvp-launcher/SKILL.md +231 -0
  64. package/skills/saas-transformer/SKILL.md +446 -0
  65. package/skills/saas-transformer/references/billing_integration_guide.md +401 -0
  66. package/skills/saas-transformer/references/feature_gating_patterns.md +137 -0
  67. package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -0
  68. package/skills/saas-transformer/scripts/saas_transformation_scanner.py +254 -0
  69. package/skills/scalability-clean-code/SKILL.md +229 -0
  70. package/skills/secure-fuzz-testing/SKILL.md +201 -0
  71. package/skills/senior-frontend/SKILL.md +161 -0
  72. package/skills/senior-frontend/references/frontend_best_practices.md +806 -0
  73. package/skills/senior-frontend/references/nextjs_optimization_guide.md +724 -0
  74. package/skills/senior-frontend/references/react_patterns.md +746 -0
  75. package/skills/senior-frontend/scripts/bundle_analyzer.py +407 -0
  76. package/skills/senior-frontend/scripts/component_generator.py +329 -0
  77. package/skills/senior-frontend/scripts/frontend_scaffolder.py +1005 -0
  78. package/skills/senior-fullstack/SKILL.md +167 -0
  79. package/skills/senior-fullstack/references/architecture_patterns.md +160 -0
  80. package/skills/senior-fullstack/references/development_workflows.md +222 -0
  81. package/skills/senior-fullstack/references/tech_stack_guide.md +190 -0
  82. package/skills/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
  83. package/skills/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
  84. package/skills/senior-fullstack/scripts/project_scaffolder.py +114 -0
  85. package/skills/seo/SKILL.md +225 -0
  86. package/skills/seo/references/cwv-thresholds.md +108 -0
  87. package/skills/seo/references/eeat-framework.md +214 -0
  88. package/skills/seo/references/quality-gates.md +155 -0
  89. package/skills/seo/references/schema-types.md +118 -0
  90. package/skills/seo-aeo-landing-page-writer/SKILL.md +97 -0
  91. package/skills/seo-geo/SKILL.md +188 -0
  92. package/skills/session-handoff-resume/SKILL.md +158 -0
  93. package/skills/skill_baru/SKILL.md +147 -0
  94. package/skills/spa-orchestrator/SKILL.md +288 -0
  95. package/skills/state-management-expert/SKILL.md +272 -0
  96. package/skills/supabase-migration/SKILL.md +45 -0
  97. package/skills/supabase-security-expert/SKILL.md +243 -0
  98. package/skills/tailwind-expert/SKILL.md +188 -0
  99. package/skills/tanstack-query-expert/SKILL.md +199 -0
  100. package/skills/tauri-expert/SKILL.md +97 -0
  101. package/skills/token-saver/SKILL.md +111 -0
  102. package/skills/typescript-expert/SKILL.md +279 -0
  103. package/skills/ui-components-expert/SKILL.md +63 -0
  104. package/skills/ui-ux-pro-max/SKILL.md +201 -0
  105. package/skills/ui-ux-pro-max/data/charts.csv +26 -0
  106. package/skills/ui-ux-pro-max/data/colors.csv +97 -0
  107. package/skills/ui-ux-pro-max/data/icons.csv +101 -0
  108. package/skills/ui-ux-pro-max/data/landing.csv +31 -0
  109. package/skills/ui-ux-pro-max/data/products.csv +97 -0
  110. package/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  111. package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  112. package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  113. package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  114. package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  115. package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  116. package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  117. package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  118. package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  119. package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  120. package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  121. package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  122. package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  123. package/skills/ui-ux-pro-max/data/styles.csv +59 -0
  124. package/skills/ui-ux-pro-max/data/typography.csv +58 -0
  125. package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  126. package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  127. package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  128. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  129. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc +0 -0
  130. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  131. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-312.pyc +0 -0
  132. package/skills/ui-ux-pro-max/scripts/core.py +257 -0
  133. package/skills/ui-ux-pro-max/scripts/design_system.py +493 -0
  134. package/skills/ui-ux-pro-max/scripts/search.py +81 -0
  135. package/skills/ui_ux_expert/SKILL.md +114 -0
  136. package/skills/vibe-code-gardener/SKILL.md +173 -0
  137. package/skills/web-scraper/SKILL.md +205 -0
  138. package/skills/web-scraper/references/data-transforms.md +397 -0
  139. package/skills/web-scraper/references/extraction-patterns.md +475 -0
  140. package/skills/web-scraper/references/output-templates.md +481 -0
  141. package/skills/zero-to-prod-orchestrator/SKILL.md +180 -0
@@ -0,0 +1,475 @@
1
+ # Extraction Patterns Reference
2
+
3
+ CSS selectors, JavaScript snippets, and domain-specific tips for
4
+ common web scraping scenarios.
5
+
6
+ ---
7
+
8
+ ## CSS Selector Patterns
9
+
10
+ ### Tables
11
+
12
+ ```css
13
+ /* Standard HTML tables */
14
+ table /* All tables */
15
+ table.data-table /* Class-based */
16
+ table[id*="result"] /* ID contains "result" */
17
+ table thead th /* Header cells */
18
+ table tbody tr /* Data rows */
19
+ table tbody tr td /* Data cells */
20
+ table tbody tr td:nth-child(2) /* Specific column (2nd) */
21
+
22
+ /* Grid layouts acting as tables */
23
+ [role="table"] /* ARIA table role */
24
+ [role="row"] /* ARIA row */
25
+ [role="gridcell"] /* ARIA grid cell */
26
+ .table-responsive table /* Bootstrap responsive wrapper */
27
+ ```
28
+
29
+ ### Product Listings
30
+
31
+ ```css
32
+ /* E-commerce product grids */
33
+ .product-card, .product-item, .product-tile
34
+ [data-product-id] /* Data attribute markers */
35
+ .product-name, .product-title, h2.title
36
+ .price, .product-price, [data-price]
37
+ .price--sale, .price--original /* Sale vs original price */
38
+ .rating, .stars, [data-rating]
39
+ .availability, .stock-status
40
+ .product-image img, .product-thumb img
41
+
42
+ /* Common e-commerce patterns */
43
+ .search-results .result-item
44
+ .catalog-grid .catalog-item
45
+ .listing .listing-item
46
+ ```
47
+
48
+ ### Search Results
49
+
50
+ ```css
51
+ /* Generic search result patterns */
52
+ .search-result, .result-item, .search-entry
53
+ .result-title a, .result-link
54
+ .result-snippet, .result-description
55
+ .result-url, .result-source
56
+ .result-date, .result-timestamp
57
+ .pagination a, .page-numbers a, [aria-label="Next"]
58
+ ```
59
+
60
+ ### Contact / Directory
61
+
62
+ ```css
63
+ /* People and contact cards */
64
+ .team-member, .staff-card, .person, .contact-card
65
+ .member-name, .person-name, h3.name
66
+ .member-title, .job-title, .role
67
+ .member-email a[href^="mailto:"]
68
+ .member-phone a[href^="tel:"]
69
+ .member-bio, .person-description
70
+ .vcard /* hCard microformat */
71
+ ```
72
+
73
+ ### FAQ / Accordion
74
+
75
+ ```css
76
+ /* FAQ and accordion patterns */
77
+ .faq-item, .accordion-item, [itemtype*="FAQPage"] [itemprop="mainEntity"]
78
+ .faq-question, .accordion-header, [itemprop="name"], summary
79
+ .faq-answer, .accordion-body, .accordion-content, [itemprop="acceptedAnswer"]
80
+ details, details > summary /* Native HTML accordion */
81
+ [role="tabpanel"] /* Tab-based FAQ */
82
+ ```
83
+
84
+ ### Pricing Tables
85
+
86
+ ```css
87
+ /* SaaS pricing page patterns */
88
+ .pricing-table, .pricing-card, .plan-card, .pricing-tier
89
+ .plan-name, .tier-name, .pricing-title
90
+ .plan-price, .pricing-amount, .price-value
91
+ .plan-period, .billing-cycle /* monthly/annually */
92
+ .plan-features li, .feature-list li
93
+ .plan-cta, .pricing-button
94
+ [class*="popular"], [class*="recommended"], [class*="featured"] /* highlighted plan */
95
+ ```
96
+
97
+ ### Job Listings
98
+
99
+ ```css
100
+ /* Job board patterns */
101
+ .job-listing, .job-card, .job-posting, [itemtype*="JobPosting"]
102
+ .job-title, [itemprop="title"]
103
+ .company-name, [itemprop="hiringOrganization"]
104
+ .job-location, [itemprop="jobLocation"]
105
+ .job-salary, [itemprop="baseSalary"]
106
+ .job-type, .employment-type
107
+ .job-date, [itemprop="datePosted"]
108
+ ```
109
+
110
+ ### Events
111
+
112
+ ```css
113
+ /* Event listing patterns */
114
+ .event-card, .event-item, [itemtype*="Event"]
115
+ .event-title, [itemprop="name"]
116
+ .event-date, [itemprop="startDate"], time[datetime]
117
+ .event-location, [itemprop="location"]
118
+ .event-description, [itemprop="description"]
119
+ .event-speaker, .speaker-name
120
+ ```
121
+
122
+ ### Navigation / Pagination
123
+
124
+ ```css
125
+ /* Pagination controls */
126
+ .pagination, .pager, nav[aria-label*="pagination"]
127
+ .pagination .next, a[rel="next"]
128
+ .pagination .prev, a[rel="prev"]
129
+ .page-numbers, .page-link
130
+ button[data-page], a[data-page]
131
+ .load-more, button.show-more
132
+ ```
133
+
134
+ ### Articles / Blog Posts
135
+
136
+ ```css
137
+ /* Article content */
138
+ article, .post, .entry, .article-content
139
+ article h1, .post-title, .entry-title
140
+ .author, .byline, [rel="author"]
141
+ time, .date, .published, .post-date
142
+ .post-content, .entry-content, .article-body
143
+ .tags a, .categories a, .post-tags a
144
+ ```
145
+
146
+ ---
147
+
148
+ ## JavaScript Extraction Snippets
149
+
150
+ ### Generic Table Extractor
151
+
152
+ ```javascript
153
+ function extractTable(selector) {
154
+ const table = document.querySelector(selector || 'table');
155
+ if (!table) return { error: 'No table found' };
156
+
157
+ const headers = Array.from(
158
+ table.querySelectorAll('thead th, tr:first-child th, tr:first-child td')
159
+ ).map(el => el.textContent.trim());
160
+
161
+ const rows = Array.from(table.querySelectorAll('tbody tr, tr:not(:first-child)'))
162
+ .map(tr => {
163
+ const cells = Array.from(tr.querySelectorAll('td'))
164
+ .map(td => td.textContent.trim());
165
+ return cells.length > 0 ? cells : null;
166
+ })
167
+ .filter(Boolean);
168
+
169
+ return { headers, rows, rowCount: rows.length };
170
+ }
171
+ JSON.stringify(extractTable());
172
+ ```
173
+
174
+ ### Multi-Table Extractor
175
+
176
+ ```javascript
177
+ function extractAllTables() {
178
+ const tables = document.querySelectorAll('table');
179
+ return Array.from(tables).map((table, idx) => {
180
+ const caption = table.querySelector('caption')?.textContent?.trim()
181
+ || table.getAttribute('aria-label') || `Table ${idx + 1}`;
182
+ const headers = Array.from(
183
+ table.querySelectorAll('thead th, tr:first-child th')
184
+ ).map(el => el.textContent.trim());
185
+ const rows = Array.from(table.querySelectorAll('tbody tr'))
186
+ .map(tr => Array.from(tr.querySelectorAll('td')).map(td => td.textContent.trim()))
187
+ .filter(r => r.length > 0);
188
+ return { caption, headers, rows, rowCount: rows.length };
189
+ });
190
+ }
191
+ JSON.stringify(extractAllTables());
192
+ ```
193
+
194
+ ### Generic List Extractor
195
+
196
+ ```javascript
197
+ function extractList(containerSelector, itemSelector, fieldMap) {
198
+ // fieldMap: { fieldName: { selector: 'CSS', attr: 'href'|'src'|null } }
199
+ const container = document.querySelector(containerSelector);
200
+ if (!container) return { error: 'Container not found' };
201
+
202
+ const items = Array.from(container.querySelectorAll(itemSelector));
203
+ const data = items.map(item => {
204
+ const record = {};
205
+ for (const [key, config] of Object.entries(fieldMap)) {
206
+ const sel = typeof config === 'string' ? config : config.selector;
207
+ const attr = typeof config === 'object' ? config.attr : null;
208
+ const el = item.querySelector(sel);
209
+ if (!el) { record[key] = null; continue; }
210
+ record[key] = attr ? el.getAttribute(attr) : el.textContent.trim();
211
+ }
212
+ return record;
213
+ });
214
+ return { data, itemCount: data.length };
215
+ }
216
+
217
+ // Example usage:
218
+ JSON.stringify(extractList('.results', '.result-item', {
219
+ title: '.result-title',
220
+ description: '.result-snippet',
221
+ url: { selector: '.result-title a', attr: 'href' },
222
+ date: '.result-date'
223
+ }));
224
+ ```
225
+
226
+ ### JSON-LD Structured Data Extractor
227
+
228
+ Many pages embed structured data that's easier to parse than DOM:
229
+
230
+ ```javascript
231
+ function extractJsonLd(targetType) {
232
+ const scripts = document.querySelectorAll('script[type="application/ld+json"]');
233
+ const allData = Array.from(scripts).map(s => {
234
+ try { return JSON.parse(s.textContent); } catch { return null; }
235
+ }).filter(Boolean);
236
+
237
+ // Flatten @graph arrays
238
+ const flat = allData.flatMap(d => d['@graph'] || [d]);
239
+
240
+ if (targetType) {
241
+ return flat.filter(d =>
242
+ d['@type'] === targetType ||
243
+ (Array.isArray(d['@type']) && d['@type'].includes(targetType))
244
+ );
245
+ }
246
+ return flat;
247
+ }
248
+ // Extract products: extractJsonLd('Product')
249
+ // Extract articles: extractJsonLd('Article')
250
+ // Extract all: extractJsonLd()
251
+ JSON.stringify(extractJsonLd());
252
+ ```
253
+
254
+ Common JSON-LD types and their useful fields:
255
+ - `Product`: name, offers.price, offers.priceCurrency, aggregateRating, brand.name
256
+ - `Article`: headline, author.name, datePublished, description, wordCount
257
+ - `Organization`: name, address, telephone, email, url
258
+ - `BreadcrumbList`: itemListElement[].name (navigation path)
259
+ - `FAQPage`: mainEntity[].name (question), mainEntity[].acceptedAnswer.text
260
+ - `JobPosting`: title, hiringOrganization.name, jobLocation, baseSalary
261
+ - `Event`: name, startDate, endDate, location, performer
262
+
263
+ ### OpenGraph / Meta Tag Extractor
264
+
265
+ ```javascript
266
+ function extractMeta() {
267
+ const meta = {};
268
+ document.querySelectorAll('meta[property^="og:"], meta[name^="twitter:"]')
269
+ .forEach(el => {
270
+ const key = el.getAttribute('property') || el.getAttribute('name');
271
+ meta[key] = el.getAttribute('content');
272
+ });
273
+ meta.title = document.title;
274
+ meta.description = document.querySelector('meta[name="description"]')
275
+ ?.getAttribute('content');
276
+ meta.canonical = document.querySelector('link[rel="canonical"]')
277
+ ?.getAttribute('href');
278
+ return meta;
279
+ }
280
+ JSON.stringify(extractMeta());
281
+ ```
282
+
283
+ ### Pricing Plan Extractor
284
+
285
+ ```javascript
286
+ function extractPricingPlans() {
287
+ const cards = document.querySelectorAll(
288
+ '.pricing-card, .plan-card, .pricing-tier, [class*="pricing"] [class*="card"]'
289
+ );
290
+ return Array.from(cards).map(card => ({
291
+ name: card.querySelector('[class*="name"], [class*="title"], h2, h3')
292
+ ?.textContent?.trim() || null,
293
+ price: card.querySelector('[class*="price"], [class*="amount"]')
294
+ ?.textContent?.trim() || null,
295
+ period: card.querySelector('[class*="period"], [class*="billing"]')
296
+ ?.textContent?.trim() || null,
297
+ features: Array.from(card.querySelectorAll('[class*="feature"] li, ul li'))
298
+ .map(li => li.textContent.trim()),
299
+ highlighted: card.matches('[class*="popular"], [class*="recommended"], [class*="featured"]'),
300
+ ctaText: card.querySelector('a, button')?.textContent?.trim() || null,
301
+ ctaUrl: card.querySelector('a')?.href || null,
302
+ }));
303
+ }
304
+ JSON.stringify(extractPricingPlans());
305
+ ```
306
+
307
+ ### FAQ Extractor
308
+
309
+ ```javascript
310
+ function extractFAQ() {
311
+ // Try JSON-LD first
312
+ const ldFaq = extractJsonLd('FAQPage');
313
+ if (ldFaq.length > 0 && ldFaq[0].mainEntity) {
314
+ return ldFaq[0].mainEntity.map(q => ({
315
+ question: q.name,
316
+ answer: q.acceptedAnswer?.text || null
317
+ }));
318
+ }
319
+
320
+ // Try <details>/<summary> pattern
321
+ const details = document.querySelectorAll('details');
322
+ if (details.length > 0) {
323
+ return Array.from(details).map(d => ({
324
+ question: d.querySelector('summary')?.textContent?.trim() || null,
325
+ answer: Array.from(d.children).filter(c => c.tagName !== 'SUMMARY')
326
+ .map(c => c.textContent.trim()).join(' ')
327
+ }));
328
+ }
329
+
330
+ // Try accordion pattern
331
+ const items = document.querySelectorAll(
332
+ '.faq-item, .accordion-item, [class*="faq"] [class*="item"]'
333
+ );
334
+ return Array.from(items).map(item => ({
335
+ question: item.querySelector(
336
+ '[class*="question"], [class*="header"], [class*="title"], h3, h4'
337
+ )?.textContent?.trim() || null,
338
+ answer: item.querySelector(
339
+ '[class*="answer"], [class*="body"], [class*="content"], p'
340
+ )?.textContent?.trim() || null
341
+ }));
342
+ }
343
+ JSON.stringify(extractFAQ());
344
+ ```
345
+
346
+ ### Link Extractor
347
+
348
+ ```javascript
349
+ function extractLinks(scope) {
350
+ const container = scope ? document.querySelector(scope) : document;
351
+ const links = Array.from(container.querySelectorAll('a[href]'))
352
+ .map(a => ({
353
+ text: a.textContent.trim(),
354
+ href: a.href,
355
+ title: a.title || null
356
+ }))
357
+ .filter(l => l.text && l.href && !l.href.startsWith('javascript:'));
358
+ return { links, count: links.length };
359
+ }
360
+ JSON.stringify(extractLinks());
361
+ ```
362
+
363
+ ### Image Extractor
364
+
365
+ ```javascript
366
+ function extractImages(scope) {
367
+ const container = scope ? document.querySelector(scope) : document;
368
+ const images = Array.from(container.querySelectorAll('img'))
369
+ .map(img => ({
370
+ src: img.src,
371
+ alt: img.alt || null,
372
+ width: img.naturalWidth,
373
+ height: img.naturalHeight
374
+ }))
375
+ .filter(i => i.src && !i.src.includes('data:image/gif'));
376
+ return { images, count: images.length };
377
+ }
378
+ JSON.stringify(extractImages());
379
+ ```
380
+
381
+ ### Scroll-and-Collect Pattern
382
+
383
+ For pages with lazy-loaded content, use this pattern with Browser automation:
384
+
385
+ ```javascript
386
+ // Count items before scroll
387
+ function countItems(selector) {
388
+ return document.querySelectorAll(selector).length;
389
+ }
390
+ ```
391
+
392
+ Then in the workflow:
393
+ 1. `javascript_tool`: `countItems('.item')` -> get initial count
394
+ 2. `computer(action="scroll", scroll_direction="down")`
395
+ 3. `computer(action="wait", duration=2)`
396
+ 4. `javascript_tool`: `countItems('.item')` -> get new count
397
+ 5. If new count > old count, repeat from step 2
398
+ 6. If count unchanged after 2 scrolls, all items loaded
399
+ 7. Extract all items at once
400
+
401
+ ---
402
+
403
+ ## Domain-Specific Tips
404
+
405
+ ### E-Commerce Sites
406
+ - Check for JSON-LD `Product` schema first - often has cleaner data than DOM
407
+ - Prices may have hidden original/sale price elements
408
+ - Availability often encoded in data attributes (`data-available="true"`)
409
+ - Product variants (size, color) may require click interactions
410
+ - Review data often loaded lazily - scroll to reviews section first
411
+ - Many sites have internal APIs at `/api/products` - check Network tab
412
+
413
+ ### Wikipedia
414
+ - Tables use class `.wikitable` - always prefer this selector
415
+ - Infoboxes use class `.infobox`
416
+ - References in `<sup class="reference">` - exclude from text extraction
417
+ - Table cells may contain complex nested HTML - use `.textContent.trim()`
418
+ - Sortable tables have class `.sortable` with sort buttons in headers
419
+
420
+ ### News Sites
421
+ - Article body often in `<article>` or `[itemprop="articleBody"]`
422
+ - Paywall indicators: `.paywall`, `.subscribe-wall`, truncated with "Read more"
423
+ - Publication date in `<time>` element or `[itemprop="datePublished"]`
424
+ - Author in `[itemprop="author"]` or `.byline`
425
+ - JSON-LD `NewsArticle` often has complete metadata
426
+
427
+ ### Government / Data Portals
428
+ - Often use HTML tables without JavaScript
429
+ - May have download links for CSV/Excel - check for `.csv`, `.xlsx` links
430
+ - Data dictionaries may be on separate pages
431
+ - Look for API endpoints in page source (`/api/`, `.json` links)
432
+ - CORS may block direct API access; use Bash curl instead
433
+
434
+ ### Social Media (Public Profiles)
435
+ - Content is almost always JS-rendered - use Browser automation
436
+ - Rate limiting is aggressive - keep requests minimal
437
+ - Infinite scroll is the norm - set clear item limits
438
+ - Structure changes frequently - prefer text extraction over selectors
439
+
440
+ ### SaaS Pricing Pages
441
+ - Pricing often changes dynamically (monthly vs annual toggle)
442
+ - May need to click "Annual" toggle to see annual prices
443
+ - Feature comparison tables often use checkmarks (Unicode or SVG)
444
+ - Check for hidden elements toggled by billing period selector
445
+
446
+ ### Job Boards
447
+ - Most use JSON-LD `JobPosting` schema
448
+ - Salary ranges often hidden behind "View salary" buttons
449
+ - Location may include remote/hybrid indicators
450
+ - Filters are URL-parameter based - useful for pagination
451
+
452
+ ---
453
+
454
+ ## Anti-Patterns to Avoid
455
+
456
+ | Anti-Pattern | Why It Fails | Better Approach |
457
+ |:-------------|:-------------|:----------------|
458
+ | Selectors with generated hashes (`.css-1a2b3c`) | Change on every deploy | Use semantic selectors, ARIA roles, data attributes |
459
+ | Deeply nested paths (`div > div > div > span`) | Fragile on layout changes | Use closest meaningful class or attribute |
460
+ | Index-based (`:nth-child(3)`) for dynamic lists | Order may change | Use content-based identification |
461
+ | Selecting by inline styles | Presentation, not semantics | Use classes, IDs, or data attributes |
462
+ | Hardcoded wait times for JS content | Too short or too long | Check for content presence in a loop |
463
+ | Single selector for variant pages | Different pages differ | Test selector on multiple pages first |
464
+
465
+ ## Robust Selector Priority
466
+
467
+ Prefer selectors in this order (most stable to least):
468
+
469
+ 1. `[data-testid="..."]`, `[data-id="..."]` - test/data attributes
470
+ 2. `#unique-id` - unique IDs
471
+ 3. `[role="..."]`, `[aria-label="..."]` - ARIA attributes
472
+ 4. `[itemprop="..."]`, `[itemtype="..."]` - microdata / schema.org
473
+ 5. `.semantic-class` - meaningful class names
474
+ 6. `tag.class` - element type + class
475
+ 7. Structural selectors - last resort