Skip to content

Commit 62eeb16

Browse files
author
mcarbonell
committed
feat: Añadir 8 herramientas SEO + categoría SEO Specialists (41 herramientas totales)
1 parent d899057 commit 62eeb16

File tree

98 files changed

+3330
-420
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+3330
-420
lines changed

generate-site.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const dataDir = path.join(projectRoot, 'data');
8888
const i18nDir = path.join(projectRoot, 'i18n');
8989
const baseTemplatePath = path.join(templatesDir, 'base.html');
9090
const indexTemplatePath = path.join(templatesDir, 'index-base.html');
91-
const toolsIndexPath = path.join(dataDir, 'tools-index-es.json'); // Using Spanish as base for iteration
91+
const toolsIndexPath = path.join(dataDir, 'tools-index-unified.json');
9292

9393
// Load translations
9494
async function loadTranslations(lang) {
@@ -315,8 +315,8 @@ async function generateTools(toolsIndex, lang) {
315315
];
316316

317317
for (const tool of toolsIndex) {
318-
const toolSlug = tool.slug;
319-
const toolFileName = path.basename(toolSlug, '.html');
318+
const toolSlug = tool.slug.replace('tools/', '');
319+
const toolFileName = tool.id;
320320

321321
const headPath = path.join(toolsContentDir, `${toolFileName}-head.html`);
322322
const contentPath = path.join(toolsContentDir, `${toolFileName}-content.html`);
@@ -338,17 +338,19 @@ async function generateTools(toolsIndex, lang) {
338338
const seoContent = renderSeoContent(toolTranslations.seo);
339339
toolContent += seoContent;
340340

341-
// Get translated tool info from tools-index
342-
const translatedToolsIndexPath = path.join(dataDir, `tools-index-${lang}.json`);
343-
const translatedToolsIndex = JSON.parse(await fs.readFile(translatedToolsIndexPath, 'utf8'));
344-
const translatedTool = translatedToolsIndex.find(t => t.slug === tool.slug) || tool;
341+
// Get translated tool info from unified index
342+
const translatedTool = {
343+
title: tool.title[lang] || tool.title.en,
344+
description: tool.description[lang] || tool.description.en,
345+
slug: toolSlug
346+
};
345347

346348
let generatedHtml = baseTemplate;
347349
generatedHtml = generatedHtml.replace(/{{title}}/g, translatedTool.title || '');
348350
generatedHtml = generatedHtml.replace(/{{description}}/g, translatedTool.description || '');
349351
generatedHtml = generatedHtml.replace(/{{keywords}}/g, tool.tags ? `<meta name="keywords" content="${tool.tags.join(', ')}">` : '');
350-
generatedHtml = generatedHtml.replace(/{{og_title}}/g, tool.title || '');
351-
generatedHtml = generatedHtml.replace(/{{og_description}}/g, tool.description || '');
352+
generatedHtml = generatedHtml.replace(/{{og_title}}/g, translatedTool.title || '');
353+
generatedHtml = generatedHtml.replace(/{{og_description}}/g, translatedTool.description || '');
352354
generatedHtml = generatedHtml.replace(/{{og_url}}/g, `https://${siteConfig.domain}/${lang === siteConfig.defaultLanguage ? '' : lang + '/'}${toolSlug}`);
353355
generatedHtml = generatedHtml.replace(/{{head_extra}}/g, headExtra);
354356
generatedHtml = generatedHtml.replace(/{{tool_title}}/g, translatedTool.title || '');
@@ -470,7 +472,8 @@ async function generateSitemap(toolsIndex) {
470472
{ slug: { es: 'analistas-datos', en: 'data-analysts' } },
471473
{ slug: { es: 'marketing', en: 'marketers' } },
472474
{ slug: { es: 'productividad', en: 'productivity' } },
473-
{ slug: { es: 'ia', en: 'ai' } }
475+
{ slug: { es: 'ia', en: 'ai' } },
476+
{ slug: { es: 'seo', en: 'seo' } }
474477
];
475478

476479
categories.forEach(cat => {
@@ -536,7 +539,8 @@ async function main() {
536539
console.log(`Idiomas: ${siteConfig.languages.join(', ')}`);
537540
console.log(`Idioma por defecto: ${siteConfig.defaultLanguage}\n`);
538541

539-
const toolsIndex = JSON.parse(await fs.readFile(toolsIndexPath, 'utf8'));
542+
const toolsData = JSON.parse(await fs.readFile(toolsIndexPath, 'utf8'));
543+
const toolsIndex = toolsData.tools;
540544
console.log(`Total de herramientas: ${toolsIndex.length}\n`);
541545

542546
// Generate for each language

scripts/generate-category-pages.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const categories = [
1414
{ id: 'data-analysts', slug: { es: 'analistas-datos', en: 'data-analysts' }, icon: '📊' },
1515
{ id: 'marketers', slug: { es: 'marketing', en: 'marketers' }, icon: '📱' },
1616
{ id: 'productivity', slug: { es: 'productividad', en: 'productivity' }, icon: '⚡' },
17-
{ id: 'ai-tools', slug: { es: 'ia', en: 'ai' }, icon: '🤖' }
17+
{ id: 'ai-tools', slug: { es: 'ia', en: 'ai' }, icon: '🤖' },
18+
{ id: 'seo-specialists', slug: { es: 'seo', en: 'seo' }, icon: '🔍' }
1819
];
1920

2021
const categoryNames = {
@@ -24,7 +25,8 @@ const categoryNames = {
2425
'data-analysts': { es: 'Analistas de Datos', en: 'Data Analysts' },
2526
marketers: { es: 'Marketing', en: 'Marketers' },
2627
productivity: { es: 'Productividad', en: 'Productivity' },
27-
'ai-tools': { es: 'IA', en: 'AI' }
28+
'ai-tools': { es: 'IA', en: 'AI' },
29+
'seo-specialists': { es: 'Especialistas SEO', en: 'SEO Specialists' }
2830
};
2931

3032
const categoryDescriptions = {
@@ -55,6 +57,10 @@ const categoryDescriptions = {
5557
'ai-tools': {
5658
es: 'Herramientas con IA: chat, resumir textos, mejorar redacción, editar imágenes. Potenciadas por Google Gemini.',
5759
en: 'AI-powered tools: chat, summarize texts, improve writing, edit images. Powered by Google Gemini.'
60+
},
61+
'seo-specialists': {
62+
es: 'Herramientas SEO profesionales: analizar meta tags, validar robots.txt, detectar enlaces rotos, optimizar para buscadores. Todo gratis.',
63+
en: 'Professional SEO tools: analyze meta tags, validate robots.txt, detect broken links, optimize for search engines. All free.'
5864
}
5965
};
6066

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<meta name="keywords" content="text, base64, encode">
1010
<!-- Open Graph -->
1111
<meta property="og:type" content="website">
12-
<meta property="og:title" content="Codificar/Decodificar Base64 — FastTools">
13-
<meta property="og:description" content="Codifica y decodifica texto en Base64.">
14-
<meta property="og:url" content="https://fasttools.tools/tools/base64.html">
12+
<meta property="og:title" content="Encode/Decode Base64 — FastTools">
13+
<meta property="og:description" content="Encode and decode text in Base64.">
14+
<meta property="og:url" content="https://fasttools.tools/base64.html">
1515
<!-- PWA Manifest -->
1616
<link rel="manifest" href="/manifest.json">
1717
<meta name="theme-color" content="#0d6efd">
@@ -20,9 +20,9 @@
2020
<meta name="apple-mobile-web-app-title" content="FastTools">
2121
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
2222
<!-- Hreflang tags for i18n -->
23-
<link rel="alternate" hreflang="en" href="https://fasttools.tools/tools/base64.html">
24-
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/tools/base64.html">
25-
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/tools/base64.html">
23+
<link rel="alternate" hreflang="en" href="https://fasttools.tools/base64.html">
24+
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/base64.html">
25+
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/base64.html">
2626

2727
<!-- Schema.org markup -->
2828
<script type="application/ld+json">
@@ -39,6 +39,12 @@
3939
{
4040
"@type": "ListItem",
4141
"position": 2,
42+
"name": "Developers",
43+
"item": "https://fasttools.tools/developers.html"
44+
},
45+
{
46+
"@type": "ListItem",
47+
"position": 3,
4248
"name": "Encode/Decode Base64"
4349
}
4450
]
@@ -70,7 +76,7 @@
7076
<div class="tool-header">
7177
<h1>Encode/Decode Base64</h1>
7278
<p class="text-muted">Encode and decode text in Base64.</p>
73-
79+
<div class="alert alert-info mt-3"><small>🎯 Useful for: <a href="/developers.html" class="badge bg-primary text-decoration-none">💻 Developers</a></small></div>
7480
</div>
7581

7682
<div class="mb-3">

web/broken-links-checker.html

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!doctype html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<title>Broken Links Checker - FastTools</title>
8+
<meta name="description" content="Detect broken links in your HTML or web page.">
9+
<meta name="keywords" content="seo, links, checker">
10+
<!-- Open Graph -->
11+
<meta property="og:type" content="website">
12+
<meta property="og:title" content="Broken Links Checker — FastTools">
13+
<meta property="og:description" content="Detect broken links in your HTML or web page.">
14+
<meta property="og:url" content="https://fasttools.tools/broken-links-checker.html">
15+
<!-- PWA Manifest -->
16+
<link rel="manifest" href="/manifest.json">
17+
<meta name="theme-color" content="#0d6efd">
18+
<meta name="apple-mobile-web-app-capable" content="yes">
19+
<meta name="apple-mobile-web-app-status-bar-style" content="default">
20+
<meta name="apple-mobile-web-app-title" content="FastTools">
21+
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
22+
<!-- Hreflang tags for i18n -->
23+
<link rel="alternate" hreflang="en" href="https://fasttools.tools/broken-links-checker.html">
24+
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/broken-links-checker.html">
25+
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/broken-links-checker.html">
26+
27+
<!-- Schema.org markup -->
28+
<script type="application/ld+json">
29+
{
30+
"@context": "https://schema.org",
31+
"@type": "BreadcrumbList",
32+
"itemListElement": [
33+
{
34+
"@type": "ListItem",
35+
"position": 1,
36+
"name": "FastTools",
37+
"item": "https://fasttools.tools"
38+
},
39+
{
40+
"@type": "ListItem",
41+
"position": 2,
42+
"name": "Broken Links Checker"
43+
}
44+
]
45+
}
46+
</script>
47+
<!-- Fonts -->
48+
<link rel="preconnect" href="https://fonts.googleapis.com">
49+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
50+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap" rel="stylesheet">
51+
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet">
52+
53+
<!-- Styles -->
54+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
55+
<link rel="stylesheet" href="/css/style.css">
56+
<link rel="stylesheet" href="/css/style-v2.css">
57+
<link rel="stylesheet" href="/css/cookie-banner.css">
58+
59+
</head>
60+
61+
<body>
62+
<div class="container py-4">
63+
<div class="d-flex justify-content-between align-items-center mb-4">
64+
<a href="/index.html" class="btn btn-secondary btn-sm" id="backLink">
65+
<span class="material-symbols-outlined" style="font-size: 18px;">arrow_back</span>
66+
Back
67+
</a>
68+
<div id="languageSelector"></div>
69+
</div>
70+
<div class="tool-header">
71+
<h1>Broken Links Checker</h1>
72+
<p class="text-muted">Detect broken links in your HTML or web page.</p>
73+
<div class="alert alert-info mt-3"><small>🎯 Useful for: </small></div>
74+
</div>
75+
76+
77+
</div>
78+
79+
80+
<script>
81+
window.toolTranslations = {};
82+
</script>
83+
84+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
85+
<script src="/js/toast.js"></script>
86+
<script src="/i18n/language-selector.js"></script>
87+
<script src="/js/cookie-consent.js"></script>
88+
<script src="/js/analytics.js"></script>
89+
90+
<!-- Service Worker Registration -->
91+
<script>
92+
// Auto-registrar Service Worker
93+
if ('serviceWorker' in navigator && (location.protocol === 'https:' || location.hostname === 'localhost')) {
94+
window.addEventListener('load', function () {
95+
navigator.serviceWorker.register('/sw.js', {
96+
scope: '/'
97+
}).then(function (registration) {
98+
console.log('SW registered: ', registration);
99+
}).catch(function (registrationError) {
100+
console.log('SW registration failed: ', registrationError);
101+
});
102+
});
103+
}
104+
</script>
105+
106+
107+
</body>
108+
109+
</html>
Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<meta name="keywords" content="ai, chat, gemini">
1010
<!-- Open Graph -->
1111
<meta property="og:type" content="website">
12-
<meta property="og:title" content="Chat con IA — FastTools">
13-
<meta property="og:description" content="Chatea con inteligencia artificial usando Google Gemini.">
14-
<meta property="og:url" content="https://fasttools.tools/tools/chat-ai.html">
12+
<meta property="og:title" content="AI Chat — FastTools">
13+
<meta property="og:description" content="Chat with AI using Google Gemini.">
14+
<meta property="og:url" content="https://fasttools.tools/chat-ai.html">
1515
<!-- PWA Manifest -->
1616
<link rel="manifest" href="/manifest.json">
1717
<meta name="theme-color" content="#0d6efd">
@@ -20,9 +20,9 @@
2020
<meta name="apple-mobile-web-app-title" content="FastTools">
2121
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
2222
<!-- Hreflang tags for i18n -->
23-
<link rel="alternate" hreflang="en" href="https://fasttools.tools/tools/chat-ai.html">
24-
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/tools/chat-ai.html">
25-
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/tools/chat-ai.html">
23+
<link rel="alternate" hreflang="en" href="https://fasttools.tools/chat-ai.html">
24+
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/chat-ai.html">
25+
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/chat-ai.html">
2626

2727
<!-- Schema.org markup -->
2828
<script type="application/ld+json">
@@ -39,6 +39,24 @@
3939
{
4040
"@type": "ListItem",
4141
"position": 2,
42+
"name": "Writers",
43+
"item": "https://fasttools.tools/writers.html"
44+
},
45+
{
46+
"@type": "ListItem",
47+
"position": 3,
48+
"name": "Marketers",
49+
"item": "https://fasttools.tools/marketers.html"
50+
},
51+
{
52+
"@type": "ListItem",
53+
"position": 4,
54+
"name": "AI",
55+
"item": "https://fasttools.tools/ai.html"
56+
},
57+
{
58+
"@type": "ListItem",
59+
"position": 5,
4260
"name": "AI Chat"
4361
}
4462
]
@@ -82,7 +100,7 @@
82100
<div class="tool-header">
83101
<h1>AI Chat</h1>
84102
<p class="text-muted">Chat with AI using Google Gemini.</p>
85-
103+
<div class="alert alert-info mt-3"><small>🎯 Useful for: <a href="/writers.html" class="badge bg-primary text-decoration-none">✍️ Writers</a> <a href="/marketers.html" class="badge bg-primary text-decoration-none">📱 Marketers</a> <a href="/ai.html" class="badge bg-primary text-decoration-none">🤖 AI</a></small></div>
86104
</div>
87105

88106
<div id="apiKeySetup" class="api-key-setup">
Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<meta name="keywords" content="ai, pdf, chat">
1010
<!-- Open Graph -->
1111
<meta property="og:type" content="website">
12-
<meta property="og:title" content="Chat con PDF — FastTools">
13-
<meta property="og:description" content="Chatea con tus documentos PDF usando IA.">
14-
<meta property="og:url" content="https://fasttools.tools/tools/chat-pdf.html">
12+
<meta property="og:title" content="Chat with PDF — FastTools">
13+
<meta property="og:description" content="Chat with your PDF documents using AI.">
14+
<meta property="og:url" content="https://fasttools.tools/chat-pdf.html">
1515
<!-- PWA Manifest -->
1616
<link rel="manifest" href="/manifest.json">
1717
<meta name="theme-color" content="#0d6efd">
@@ -20,9 +20,9 @@
2020
<meta name="apple-mobile-web-app-title" content="FastTools">
2121
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
2222
<!-- Hreflang tags for i18n -->
23-
<link rel="alternate" hreflang="en" href="https://fasttools.tools/tools/chat-pdf.html">
24-
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/tools/chat-pdf.html">
25-
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/tools/chat-pdf.html">
23+
<link rel="alternate" hreflang="en" href="https://fasttools.tools/chat-pdf.html">
24+
<link rel="alternate" hreflang="es" href="https://fasttools.tools/es/chat-pdf.html">
25+
<link rel="alternate" hreflang="x-default" href="https://fasttools.tools/chat-pdf.html">
2626

2727
<!-- Schema.org markup -->
2828
<script type="application/ld+json">
@@ -39,6 +39,12 @@
3939
{
4040
"@type": "ListItem",
4141
"position": 2,
42+
"name": "AI",
43+
"item": "https://fasttools.tools/ai.html"
44+
},
45+
{
46+
"@type": "ListItem",
47+
"position": 3,
4248
"name": "Chat with PDF"
4349
}
4450
]
@@ -77,7 +83,7 @@
7783
<div class="tool-header">
7884
<h1>Chat with PDF</h1>
7985
<p class="text-muted">Chat with your PDF documents using AI.</p>
80-
86+
<div class="alert alert-info mt-3"><small>🎯 Useful for: <a href="/ai.html" class="badge bg-primary text-decoration-none">🤖 AI</a></small></div>
8187
</div>
8288

8389
<div id="apiKeySetup" class="alert alert-warning">

0 commit comments

Comments
 (0)