claude-agent-framework 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 (111) hide show
  1. package/README.md +128 -0
  2. package/bin/claude-framework +3 -0
  3. package/framework/agents/design-lead.md +240 -0
  4. package/framework/agents/product-owner.md +179 -0
  5. package/framework/agents/tech-lead.md +226 -0
  6. package/framework/commands/ayuda.md +127 -0
  7. package/framework/commands/a/303/261adir.md +98 -0
  8. package/framework/commands/backup.md +397 -0
  9. package/framework/commands/cambiar.md +110 -0
  10. package/framework/commands/cloud.md +457 -0
  11. package/framework/commands/code.md +142 -0
  12. package/framework/commands/debug.md +334 -0
  13. package/framework/commands/deploy.md +383 -0
  14. package/framework/commands/deshacer.md +120 -0
  15. package/framework/commands/estado.md +218 -0
  16. package/framework/commands/explica.md +227 -0
  17. package/framework/commands/feature.md +120 -0
  18. package/framework/commands/git.md +427 -0
  19. package/framework/commands/historial.md +202 -0
  20. package/framework/commands/learn.md +408 -0
  21. package/framework/commands/movil.md +245 -0
  22. package/framework/commands/nuevo.md +118 -0
  23. package/framework/commands/plan.md +134 -0
  24. package/framework/commands/prd.md +113 -0
  25. package/framework/commands/probar.md +148 -0
  26. package/framework/commands/revisar.md +208 -0
  27. package/framework/commands/seeds.md +230 -0
  28. package/framework/commands/seguridad.md +226 -0
  29. package/framework/commands/tasks.md +157 -0
  30. package/framework/skills/architecture/algorithms.md +970 -0
  31. package/framework/skills/architecture/clean-code.md +1080 -0
  32. package/framework/skills/architecture/design-patterns.md +1984 -0
  33. package/framework/skills/architecture/functional-programming.md +972 -0
  34. package/framework/skills/architecture/solid.md +991 -0
  35. package/framework/skills/cloud/cloud-aws.md +848 -0
  36. package/framework/skills/cloud/cloud-azure.md +931 -0
  37. package/framework/skills/cloud/cloud-gcp.md +848 -0
  38. package/framework/skills/cloud/message-queues.md +1229 -0
  39. package/framework/skills/core/accessibility.md +401 -0
  40. package/framework/skills/core/api.md +474 -0
  41. package/framework/skills/core/authentication.md +306 -0
  42. package/framework/skills/core/authorization.md +388 -0
  43. package/framework/skills/core/background-jobs.md +341 -0
  44. package/framework/skills/core/caching.md +473 -0
  45. package/framework/skills/core/code-review.md +341 -0
  46. package/framework/skills/core/controllers.md +290 -0
  47. package/framework/skills/core/cua.md +285 -0
  48. package/framework/skills/core/documentation.md +472 -0
  49. package/framework/skills/core/file-uploads.md +351 -0
  50. package/framework/skills/core/hotwire-native.md +296 -0
  51. package/framework/skills/core/hotwire.md +278 -0
  52. package/framework/skills/core/i18n.md +334 -0
  53. package/framework/skills/core/imports-exports.md +750 -0
  54. package/framework/skills/core/infrastructure.md +337 -0
  55. package/framework/skills/core/models.md +228 -0
  56. package/framework/skills/core/notifications.md +672 -0
  57. package/framework/skills/core/payments.md +581 -0
  58. package/framework/skills/core/performance.md +361 -0
  59. package/framework/skills/core/rails-scaffold.md +131 -0
  60. package/framework/skills/core/search.md +518 -0
  61. package/framework/skills/core/security.md +565 -0
  62. package/framework/skills/core/seeds.md +307 -0
  63. package/framework/skills/core/seo.md +542 -0
  64. package/framework/skills/core/testing.md +393 -0
  65. package/framework/skills/core/views.md +260 -0
  66. package/framework/skills/core/websockets.md +564 -0
  67. package/framework/skills/data/advanced-sql.md +1204 -0
  68. package/framework/skills/data/nosql.md +1141 -0
  69. package/framework/skills/devops/containers-advanced.md +1237 -0
  70. package/framework/skills/devops/debugging.md +834 -0
  71. package/framework/skills/devops/git-workflow.md +752 -0
  72. package/framework/skills/devops/networking.md +932 -0
  73. package/framework/skills/devops/shell-scripting.md +1132 -0
  74. package/framework/sub-agents/architecture-patterns-agent.md +1450 -0
  75. package/framework/sub-agents/cloud-agent.md +677 -0
  76. package/framework/sub-agents/data.md +504 -0
  77. package/framework/sub-agents/debugging-agent.md +554 -0
  78. package/framework/sub-agents/devops.md +483 -0
  79. package/framework/sub-agents/docs.md +176 -0
  80. package/framework/sub-agents/frontend-dev.md +349 -0
  81. package/framework/sub-agents/git-workflow-agent.md +697 -0
  82. package/framework/sub-agents/integrations.md +630 -0
  83. package/framework/sub-agents/native-dev.md +434 -0
  84. package/framework/sub-agents/qa.md +138 -0
  85. package/framework/sub-agents/rails-dev.md +375 -0
  86. package/framework/sub-agents/security.md +526 -0
  87. package/framework/sub-agents/ui.md +437 -0
  88. package/framework/sub-agents/ux.md +284 -0
  89. package/framework/templates/api-spec.md +500 -0
  90. package/framework/templates/component-spec.md +248 -0
  91. package/framework/templates/feature.json +13 -0
  92. package/framework/templates/model-spec.md +318 -0
  93. package/framework/templates/prd-template.md +80 -0
  94. package/framework/templates/task-plan.md +122 -0
  95. package/framework/templates/task-user-story.md +52 -0
  96. package/framework/templates/technical-spec.md +260 -0
  97. package/framework/templates/user-story.md +95 -0
  98. package/package.json +42 -0
  99. package/project-templates/CLAUDE.md +42 -0
  100. package/project-templates/contexts/architecture.md +25 -0
  101. package/project-templates/contexts/conventions.md +46 -0
  102. package/project-templates/contexts/design-system.md +47 -0
  103. package/project-templates/contexts/requirements.md +38 -0
  104. package/project-templates/contexts/stack.md +30 -0
  105. package/project-templates/history/active/models.md +11 -0
  106. package/project-templates/history/changelog.md +15 -0
  107. package/project-templates/workspace/.gitkeep +0 -0
  108. package/src/cli.js +52 -0
  109. package/src/init.js +104 -0
  110. package/src/status.js +75 -0
  111. package/src/update.js +88 -0
@@ -0,0 +1,542 @@
1
+ # Skill: SEO
2
+
3
+ ## Purpose
4
+
5
+ Optimizar aplicaciones Rails para motores de búsqueda, incluyendo meta tags, structured data, sitemaps, y performance.
6
+
7
+ ## Meta Tags
8
+
9
+ ### Helper de meta tags
10
+
11
+ ```ruby
12
+ # app/helpers/meta_tags_helper.rb
13
+ module MetaTagsHelper
14
+ def meta_title(title = nil)
15
+ if title.present?
16
+ content_for(:meta_title) { title }
17
+ else
18
+ content_for?(:meta_title) ? content_for(:meta_title) : t("app.name")
19
+ end
20
+ end
21
+
22
+ def meta_description(description = nil)
23
+ if description.present?
24
+ content_for(:meta_description) { description }
25
+ else
26
+ content_for?(:meta_description) ? content_for(:meta_description) : t("app.description")
27
+ end
28
+ end
29
+
30
+ def meta_image(image_url = nil)
31
+ if image_url.present?
32
+ content_for(:meta_image) { image_url }
33
+ else
34
+ content_for?(:meta_image) ? content_for(:meta_image) : asset_url("og-image.png")
35
+ end
36
+ end
37
+
38
+ def canonical_url(url = nil)
39
+ if url.present?
40
+ content_for(:canonical_url) { url }
41
+ else
42
+ content_for?(:canonical_url) ? content_for(:canonical_url) : request.original_url.split("?").first
43
+ end
44
+ end
45
+
46
+ def full_title
47
+ base_title = t("app.name")
48
+ if content_for?(:meta_title)
49
+ "#{content_for(:meta_title)} | #{base_title}"
50
+ else
51
+ base_title
52
+ end
53
+ end
54
+ end
55
+ ```
56
+
57
+ ### Layout con meta tags
58
+
59
+ ```erb
60
+ <%# app/views/layouts/application.html.erb %>
61
+ <!DOCTYPE html>
62
+ <html lang="<%= I18n.locale %>">
63
+ <head>
64
+ <meta charset="UTF-8">
65
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
+
67
+ <%# Título %>
68
+ <title><%= full_title %></title>
69
+
70
+ <%# Meta básicos %>
71
+ <meta name="description" content="<%= meta_description %>">
72
+ <meta name="robots" content="<%= content_for?(:robots) ? content_for(:robots) : 'index, follow' %>">
73
+
74
+ <%# Canonical %>
75
+ <link rel="canonical" href="<%= canonical_url %>">
76
+
77
+ <%# Open Graph %>
78
+ <meta property="og:type" content="<%= content_for?(:og_type) ? content_for(:og_type) : 'website' %>">
79
+ <meta property="og:title" content="<%= meta_title %>">
80
+ <meta property="og:description" content="<%= meta_description %>">
81
+ <meta property="og:image" content="<%= meta_image %>">
82
+ <meta property="og:url" content="<%= canonical_url %>">
83
+ <meta property="og:site_name" content="<%= t('app.name') %>">
84
+ <meta property="og:locale" content="<%= I18n.locale %>">
85
+
86
+ <%# Twitter Card %>
87
+ <meta name="twitter:card" content="summary_large_image">
88
+ <meta name="twitter:title" content="<%= meta_title %>">
89
+ <meta name="twitter:description" content="<%= meta_description %>">
90
+ <meta name="twitter:image" content="<%= meta_image %>">
91
+ <% if Rails.application.credentials.dig(:twitter, :handle) %>
92
+ <meta name="twitter:site" content="@<%= Rails.application.credentials.dig(:twitter, :handle) %>">
93
+ <% end %>
94
+
95
+ <%# Otros %>
96
+ <%= csrf_meta_tags %>
97
+ <%= csp_meta_tag %>
98
+ <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
99
+ <%= javascript_importmap_tags %>
100
+
101
+ <%# Contenido extra en head %>
102
+ <%= yield :head %>
103
+ </head>
104
+ <body>
105
+ <%= yield %>
106
+ </body>
107
+ </html>
108
+ ```
109
+
110
+ ### Uso en vistas
111
+
112
+ ```erb
113
+ <%# app/views/posts/show.html.erb %>
114
+ <%
115
+ meta_title @post.title
116
+ meta_description @post.excerpt || truncate(strip_tags(@post.body), length: 160)
117
+ meta_image url_for(@post.cover_image) if @post.cover_image.attached?
118
+ canonical_url post_url(@post)
119
+ content_for(:og_type) { "article" }
120
+ %>
121
+
122
+ <article>
123
+ <h1><%= @post.title %></h1>
124
+ <%# ... %>
125
+ </article>
126
+ ```
127
+
128
+ ## Structured Data (Schema.org)
129
+
130
+ ### Helper para JSON-LD
131
+
132
+ ```ruby
133
+ # app/helpers/structured_data_helper.rb
134
+ module StructuredDataHelper
135
+ def json_ld(data)
136
+ content_tag(:script, data.to_json.html_safe, type: "application/ld+json")
137
+ end
138
+
139
+ def organization_schema
140
+ {
141
+ "@context": "https://schema.org",
142
+ "@type": "Organization",
143
+ name: t("app.name"),
144
+ url: root_url,
145
+ logo: asset_url("logo.png"),
146
+ sameAs: [
147
+ "https://twitter.com/myapp",
148
+ "https://www.linkedin.com/company/myapp"
149
+ ]
150
+ }
151
+ end
152
+
153
+ def website_schema
154
+ {
155
+ "@context": "https://schema.org",
156
+ "@type": "WebSite",
157
+ name: t("app.name"),
158
+ url: root_url,
159
+ potentialAction: {
160
+ "@type": "SearchAction",
161
+ target: {
162
+ "@type": "EntryPoint",
163
+ urlTemplate: "#{search_url}?q={search_term_string}"
164
+ },
165
+ "query-input": "required name=search_term_string"
166
+ }
167
+ }
168
+ end
169
+
170
+ def article_schema(post)
171
+ {
172
+ "@context": "https://schema.org",
173
+ "@type": "Article",
174
+ headline: post.title,
175
+ description: post.excerpt,
176
+ image: post.cover_image.attached? ? url_for(post.cover_image) : nil,
177
+ datePublished: post.published_at&.iso8601,
178
+ dateModified: post.updated_at.iso8601,
179
+ author: {
180
+ "@type": "Person",
181
+ name: post.author.name,
182
+ url: user_url(post.author)
183
+ },
184
+ publisher: {
185
+ "@type": "Organization",
186
+ name: t("app.name"),
187
+ logo: {
188
+ "@type": "ImageObject",
189
+ url: asset_url("logo.png")
190
+ }
191
+ },
192
+ mainEntityOfPage: {
193
+ "@type": "WebPage",
194
+ "@id": post_url(post)
195
+ }
196
+ }.compact
197
+ end
198
+
199
+ def breadcrumb_schema(items)
200
+ {
201
+ "@context": "https://schema.org",
202
+ "@type": "BreadcrumbList",
203
+ itemListElement: items.map.with_index(1) do |item, index|
204
+ {
205
+ "@type": "ListItem",
206
+ position: index,
207
+ name: item[:name],
208
+ item: item[:url]
209
+ }
210
+ end
211
+ }
212
+ end
213
+
214
+ def product_schema(product)
215
+ {
216
+ "@context": "https://schema.org",
217
+ "@type": "Product",
218
+ name: product.name,
219
+ description: product.description,
220
+ image: product.images.attached? ? product.images.map { |i| url_for(i) } : nil,
221
+ brand: {
222
+ "@type": "Brand",
223
+ name: product.brand
224
+ },
225
+ offers: {
226
+ "@type": "Offer",
227
+ price: product.price,
228
+ priceCurrency: "EUR",
229
+ availability: product.in_stock? ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
230
+ url: product_url(product)
231
+ }
232
+ }.compact
233
+ end
234
+
235
+ def faq_schema(faqs)
236
+ {
237
+ "@context": "https://schema.org",
238
+ "@type": "FAQPage",
239
+ mainEntity: faqs.map do |faq|
240
+ {
241
+ "@type": "Question",
242
+ name: faq[:question],
243
+ acceptedAnswer: {
244
+ "@type": "Answer",
245
+ text: faq[:answer]
246
+ }
247
+ }
248
+ end
249
+ }
250
+ end
251
+ end
252
+ ```
253
+
254
+ ### Uso en layout
255
+
256
+ ```erb
257
+ <%# app/views/layouts/application.html.erb %>
258
+ <head>
259
+ <%# ... otros meta tags ... %>
260
+
261
+ <%# Schema.org global %>
262
+ <%= json_ld(organization_schema) %>
263
+ <%= json_ld(website_schema) %>
264
+
265
+ <%# Schema.org específico de la página %>
266
+ <%= yield :structured_data %>
267
+ </head>
268
+ ```
269
+
270
+ ### Uso en vistas
271
+
272
+ ```erb
273
+ <%# app/views/posts/show.html.erb %>
274
+ <% content_for :structured_data do %>
275
+ <%= json_ld(article_schema(@post)) %>
276
+ <%= json_ld(breadcrumb_schema([
277
+ { name: "Home", url: root_url },
278
+ { name: "Blog", url: posts_url },
279
+ { name: @post.title, url: post_url(@post) }
280
+ ])) %>
281
+ <% end %>
282
+ ```
283
+
284
+ ## Sitemap
285
+
286
+ ### Gem sitemap_generator
287
+
288
+ ```ruby
289
+ # Gemfile
290
+ gem "sitemap_generator"
291
+ ```
292
+
293
+ ```ruby
294
+ # config/sitemap.rb
295
+ SitemapGenerator::Sitemap.default_host = "https://myapp.com"
296
+ SitemapGenerator::Sitemap.compress = false # Para debug
297
+ SitemapGenerator::Sitemap.create do
298
+ # Páginas estáticas
299
+ add root_path, changefreq: "daily", priority: 1.0
300
+ add about_path, changefreq: "monthly", priority: 0.7
301
+ add contact_path, changefreq: "monthly", priority: 0.7
302
+
303
+ # Posts
304
+ Post.published.find_each do |post|
305
+ add post_path(post),
306
+ lastmod: post.updated_at,
307
+ changefreq: "weekly",
308
+ priority: 0.8,
309
+ images: post.images.map { |img|
310
+ { loc: url_for(img), title: post.title }
311
+ }
312
+ end
313
+
314
+ # Categorías
315
+ Category.find_each do |category|
316
+ add category_path(category),
317
+ lastmod: category.posts.maximum(:updated_at),
318
+ changefreq: "weekly",
319
+ priority: 0.6
320
+ end
321
+
322
+ # Usuarios/perfiles públicos
323
+ User.with_public_profile.find_each do |user|
324
+ add user_path(user),
325
+ lastmod: user.updated_at,
326
+ changefreq: "weekly",
327
+ priority: 0.5
328
+ end
329
+ end
330
+ ```
331
+
332
+ ```bash
333
+ # Generar sitemap
334
+ rails sitemap:refresh
335
+
336
+ # Notificar a motores de búsqueda
337
+ rails sitemap:refresh:no_ping # Sin notificar
338
+ ```
339
+
340
+ ### Tarea programada
341
+
342
+ ```ruby
343
+ # config/schedule.rb (whenever gem) o Solid Queue
344
+ every 1.day, at: "4:00 am" do
345
+ rake "sitemap:refresh"
346
+ end
347
+ ```
348
+
349
+ ## Robots.txt
350
+
351
+ ```ruby
352
+ # config/routes.rb
353
+ get "robots.txt", to: "pages#robots", defaults: { format: :text }
354
+
355
+ # app/controllers/pages_controller.rb
356
+ class PagesController < ApplicationController
357
+ def robots
358
+ render plain: <<~ROBOTS
359
+ User-agent: *
360
+ Disallow: /admin/
361
+ Disallow: /api/
362
+ Disallow: /users/sign_in
363
+ Disallow: /users/sign_up
364
+ Disallow: /search?
365
+
366
+ Sitemap: #{sitemap_url}
367
+ ROBOTS
368
+ end
369
+
370
+ private
371
+
372
+ def sitemap_url
373
+ "#{request.protocol}#{request.host_with_port}/sitemap.xml"
374
+ end
375
+ end
376
+ ```
377
+
378
+ ## URLs amigables
379
+
380
+ ### Slugs con friendly_id
381
+
382
+ ```ruby
383
+ # Gemfile
384
+ gem "friendly_id"
385
+ ```
386
+
387
+ ```ruby
388
+ # db/migrate/xxx_add_slug_to_posts.rb
389
+ class AddSlugToPosts < ActiveRecord::Migration[8.0]
390
+ def change
391
+ add_column :posts, :slug, :string
392
+ add_index :posts, :slug, unique: true
393
+ end
394
+ end
395
+
396
+ # app/models/post.rb
397
+ class Post < ApplicationRecord
398
+ extend FriendlyId
399
+ friendly_id :title, use: [:slugged, :history]
400
+
401
+ # Regenerar slug solo si título cambia significativamente
402
+ def should_generate_new_friendly_id?
403
+ title_changed? || slug.blank?
404
+ end
405
+ end
406
+
407
+ # app/controllers/posts_controller.rb
408
+ class PostsController < ApplicationController
409
+ def show
410
+ @post = Post.friendly.find(params[:id])
411
+
412
+ # Redirect a URL canónica si slug cambió
413
+ if request.path != post_path(@post)
414
+ redirect_to @post, status: :moved_permanently
415
+ end
416
+ end
417
+ end
418
+ ```
419
+
420
+ ### URLs localizadas
421
+
422
+ ```ruby
423
+ # config/routes.rb
424
+ scope "(:locale)", locale: /es|en/ do
425
+ resources :posts, path_names: {
426
+ new: I18n.t("routes.new"),
427
+ edit: I18n.t("routes.edit")
428
+ }
429
+ end
430
+
431
+ # app/controllers/application_controller.rb
432
+ class ApplicationController < ActionController::Base
433
+ around_action :switch_locale
434
+
435
+ def default_url_options
436
+ { locale: I18n.locale }
437
+ end
438
+
439
+ private
440
+
441
+ def switch_locale(&action)
442
+ locale = params[:locale] || I18n.default_locale
443
+ I18n.with_locale(locale, &action)
444
+ end
445
+ end
446
+ ```
447
+
448
+ ## Performance SEO
449
+
450
+ ### Lazy loading de imágenes
451
+
452
+ ```erb
453
+ <%= image_tag post.cover_image,
454
+ loading: "lazy",
455
+ decoding: "async",
456
+ alt: post.title,
457
+ class: "w-full h-auto" %>
458
+ ```
459
+
460
+ ### Preload de recursos críticos
461
+
462
+ ```erb
463
+ <head>
464
+ <%# Preload fuentes %>
465
+ <link rel="preload" href="<%= asset_path('Inter.woff2') %>" as="font" type="font/woff2" crossorigin>
466
+
467
+ <%# Preload imagen LCP %>
468
+ <% if content_for?(:preload_image) %>
469
+ <link rel="preload" href="<%= content_for(:preload_image) %>" as="image">
470
+ <% end %>
471
+
472
+ <%# Preconnect a servicios externos %>
473
+ <link rel="preconnect" href="https://fonts.googleapis.com">
474
+ <link rel="preconnect" href="https://www.google-analytics.com">
475
+ </head>
476
+ ```
477
+
478
+ ### Core Web Vitals
479
+
480
+ ```erb
481
+ <%# Evitar CLS (Cumulative Layout Shift) %>
482
+ <%= image_tag post.image,
483
+ width: 800,
484
+ height: 600,
485
+ class: "aspect-[4/3] object-cover" %>
486
+
487
+ <%# Skeleton para contenido dinámico %>
488
+ <div class="min-h-[200px]"> <!-- Reservar espacio -->
489
+ <%= turbo_frame_tag "comments", src: post_comments_path(@post) do %>
490
+ <div class="animate-pulse bg-gray-200 h-32 rounded"></div>
491
+ <% end %>
492
+ </div>
493
+ ```
494
+
495
+ ## Hreflang para múltiples idiomas
496
+
497
+ ```erb
498
+ <head>
499
+ <% I18n.available_locales.each do |locale| %>
500
+ <link rel="alternate"
501
+ hreflang="<%= locale %>"
502
+ href="<%= url_for(locale: locale) %>">
503
+ <% end %>
504
+ <link rel="alternate" hreflang="x-default" href="<%= url_for(locale: I18n.default_locale) %>">
505
+ </head>
506
+ ```
507
+
508
+ ## Checklist SEO
509
+
510
+ ### Técnico
511
+ - [ ] Meta title único por página (50-60 chars)
512
+ - [ ] Meta description única (150-160 chars)
513
+ - [ ] URLs amigables con slugs
514
+ - [ ] Canonical URLs configuradas
515
+ - [ ] Sitemap.xml generado y actualizado
516
+ - [ ] Robots.txt configurado
517
+ - [ ] HTTPS habilitado
518
+ - [ ] Mobile-friendly (responsive)
519
+
520
+ ### Contenido
521
+ - [ ] H1 único por página
522
+ - [ ] Jerarquía de headings (H1 > H2 > H3)
523
+ - [ ] Alt text en imágenes
524
+ - [ ] Internal linking
525
+
526
+ ### Structured Data
527
+ - [ ] Organization schema
528
+ - [ ] Article schema para posts
529
+ - [ ] BreadcrumbList schema
530
+ - [ ] Product schema (si aplica)
531
+ - [ ] FAQ schema (si aplica)
532
+
533
+ ### Social
534
+ - [ ] Open Graph tags
535
+ - [ ] Twitter Card tags
536
+ - [ ] Imagen OG (1200x630px)
537
+
538
+ ### Performance
539
+ - [ ] Core Web Vitals optimizados
540
+ - [ ] Imágenes optimizadas (WebP, lazy loading)
541
+ - [ ] CSS/JS minificados
542
+ - [ ] Preload de recursos críticos