@@ -4,9 +4,14 @@ import BaseLayout from '@layouts/BaseLayout.astro';
44import { generateWebsiteJsonLd } from ' @lib/json-ld' ;
55
66const tools = await getCollection (' tools' );
7+ const sortedTools = tools .sort ((a , b ) => b .data .publishedAt .getTime () - a .data .publishedAt .getTime ());
78const 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 } ` ;
1015const siteUrl = Astro .site ?.toString ().replace (/ \/ $ / , ' ' ) || ' https://devtools.example.com' ;
1116
1217const 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 >
0 commit comments