Skip to content

Commit fe98e2f

Browse files
feat: add multiple new tools including Base64 encoder, JSON formatter, and UUID generator; update BASE_URL handling in layouts
1 parent cba1529 commit fe98e2f

12 files changed

Lines changed: 36 additions & 100 deletions

src/layouts/BaseLayout.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export interface Props {
1111
1212
const { title, description, jsonLd } = Astro.props;
1313
14-
const base = import.meta.env.BASE_URL;
14+
const rawBase = import.meta.env.BASE_URL;
15+
const base = rawBase.endsWith('/') ? rawBase : `${rawBase}/`;
1516
1617
// AdSense slot ID for the site-wide footer placement.
1718
// Set PUBLIC_ADSENSE_CLIENT (and replace this slot) to enable. Hidden otherwise.
@@ -30,7 +31,7 @@ const FOOTER_AD_SLOT = import.meta.env.PUBLIC_ADSENSE_FOOTER_SLOT ?? '';
3031
DevTools
3132
</a>
3233
<div class="flex gap-6">
33-
<a href={`${base}tools`} class="text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400">
34+
<a href={base} class="text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400">
3435
Tools
3536
</a>
3637
<a href={`${base}blog`} class="text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400">

src/layouts/ToolLayout.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export interface Props {
1313
1414
const { title, description, category, tags = [], relatedTools = [], jsonLd } = Astro.props;
1515
16-
const base = import.meta.env.BASE_URL;
16+
const rawBase = import.meta.env.BASE_URL;
17+
const base = rawBase.endsWith('/') ? rawBase : `${rawBase}/`;
1718
1819
const adInArticleSlot = import.meta.env.PUBLIC_ADSENSE_SLOT_TOOL_INARTICLE;
1920
const adFooterSlot = import.meta.env.PUBLIC_ADSENSE_SLOT_TOOL_FOOTER;
@@ -61,7 +62,7 @@ const adFooterSlot = import.meta.env.PUBLIC_ADSENSE_SLOT_TOOL_FOOTER;
6162
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
6263
{relatedTools.map((tool) => (
6364
<a
64-
href={`${base}tools/${tool}`}
65+
href={`${base}${tool}`}
6566
class="block p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 transition-colors"
6667
>
6768
<span class="text-blue-600 dark:text-blue-400 font-medium">{tool}</span>
File renamed without changes.

src/pages/index.astro

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ import BaseLayout from '@layouts/BaseLayout.astro';
44
import { generateWebsiteJsonLd } from '@lib/json-ld';
55
66
const tools = await getCollection('tools');
7+
const sortedTools = tools.sort((a, b) => b.data.publishedAt.getTime() - a.data.publishedAt.getTime());
78
const featuredTools = tools.filter(t => t.data.featured).slice(0, 6);
89
9-
const base = import.meta.env.BASE_URL;
10+
// Normalize Astro's BASE_URL (which may or may not include a trailing slash)
11+
// so concatenating `${base}/<slug>` always produces a valid path.
12+
const rawBase = import.meta.env.BASE_URL;
13+
const base = rawBase.endsWith('/') ? rawBase : `${rawBase}/`;
14+
const toolHref = (slug: string) => `${base}${slug}`;
1015
const siteUrl = Astro.site?.toString().replace(/\/$/, '') || 'https://devtools.example.com';
1116
1217
const jsonLd = generateWebsiteJsonLd({
@@ -32,7 +37,7 @@ const jsonLd = generateWebsiteJsonLd({
3237
</p>
3338
<div class="flex flex-wrap gap-4 justify-center">
3439
<a
35-
href={`${base}tools`}
40+
href="#all-tools"
3641
class="px-8 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors"
3742
>
3843
Browse All Tools
@@ -78,7 +83,7 @@ const jsonLd = generateWebsiteJsonLd({
7883
Featured Tools
7984
</h2>
8085
<a
81-
href={`${base}tools`}
86+
href="#all-tools"
8287
class="text-blue-600 dark:text-blue-400 hover:underline font-medium"
8388
>
8489
View All →
@@ -88,7 +93,7 @@ const jsonLd = generateWebsiteJsonLd({
8893
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
8994
{featuredTools.map((tool) => (
9095
<a
91-
href={`${base}tools/${tool.id}`}
96+
href={toolHref(tool.id)}
9297
class="group block p-6 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:shadow-lg transition-all"
9398
>
9499
<div class="flex items-start gap-4">
@@ -112,18 +117,29 @@ const jsonLd = generateWebsiteJsonLd({
112117
</div>
113118
</section>
114119

115-
<!-- Categories -->
116-
<section class="space-y-6">
117-
<h2 class="text-3xl font-bold text-gray-900 dark:text-white">
118-
Tool Categories
119-
</h2>
120-
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
121-
{['Encoding', 'Formatting', 'Conversion', 'Generation', 'Security'].map((category) => (
120+
<!-- All Tools -->
121+
<section id="all-tools" class="space-y-6">
122+
<h2 class="text-3xl font-bold text-gray-900 dark:text-white">All Tools</h2>
123+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
124+
{sortedTools.map((tool) => (
122125
<a
123-
href={`${base}tools?category=${category.toLowerCase()}`}
124-
class="p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 transition-colors text-center"
126+
href={toolHref(tool.id)}
127+
class="group block p-6 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-400 hover:shadow-lg transition-all"
125128
>
126-
<span class="font-medium text-gray-900 dark:text-white">{category}</span>
129+
<div class="flex items-start gap-4">
130+
{tool.data.icon && <span class="text-3xl">{tool.data.icon}</span>}
131+
<div class="flex-1 min-w-0">
132+
<h3 class="text-lg font-semibold text-gray-900 dark:text-white group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">
133+
{tool.data.title}
134+
</h3>
135+
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400 line-clamp-2">
136+
{tool.data.description}
137+
</p>
138+
<span class="mt-3 inline-block px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 rounded capitalize">
139+
{tool.data.category}
140+
</span>
141+
</div>
142+
</div>
127143
</a>
128144
))}
129145
</div>
File renamed without changes.

src/pages/tools/index.astro

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)