Remove trailing slashes from the website URLs

pull/3333/head
Kamran Ahmed 2 years ago
parent 8b32a3a831
commit 5b93bc42db
  1. 5
      astro.config.mjs
  2. 22
      sitemap.mjs
  3. 35
      src/components/Breadcrumbs.astro
  4. 4
      src/components/FeaturedGuides.astro
  5. 4
      src/components/FeaturedVideos.astro
  6. 26
      src/components/Footer.astro
  7. 2
      src/components/GridRoadmapItem.astro
  8. 2
      src/components/GuideListItem.astro
  9. 45
      src/components/Navigation.astro
  10. 21
      src/components/ResourcesAlert.astro
  11. 16
      src/components/RoadmapBanner.astro
  12. 4
      src/components/RoadmapHeader.astro
  13. 20
      src/components/TopicSearch/TopicSearch.astro
  14. 20
      src/components/VideoListItem.astro
  15. 17
      src/components/YouTubeBanner.astro
  16. 4
      src/pages/404.astro
  17. 2
      src/pages/[...topicId].astro
  18. 2
      src/pages/[roadmapId]/index.astro
  19. 4
      src/pages/[roadmapId]/topics.astro
  20. 2
      src/pages/about.astro
  21. 2
      src/pages/guides/[guideId].astro
  22. 7
      src/pages/guides/index.astro
  23. 5
      src/pages/index.astro
  24. 2
      src/pages/privacy.md
  25. 2
      src/pages/roadmaps.astro
  26. 2
      src/pages/signup.astro
  27. 2
      src/pages/videos/[videoId].astro
  28. 7
      src/pages/videos/index.astro

@ -10,7 +10,7 @@ export default defineConfig({
site: 'https://roadmap.sh', site: 'https://roadmap.sh',
markdown: { markdown: {
shikiConfig: { shikiConfig: {
theme: 'dracula' theme: 'dracula',
}, },
rehypePlugins: [ rehypePlugins: [
[ [
@ -21,6 +21,9 @@ export default defineConfig({
], ],
], ],
}, },
build: {
format: 'file',
},
integrations: [ integrations: [
tailwind({ tailwind({
config: { config: {

@ -7,21 +7,21 @@ async function getRoadmapIds() {
export function shouldIndexPage(page) { export function shouldIndexPage(page) {
return ![ return ![
'https://roadmap.sh/404/', 'https://roadmap.sh/404',
'https://roadmap.sh/terms/', 'https://roadmap.sh/terms',
'https://roadmap.sh/privacy/', 'https://roadmap.sh/privacy',
'https://roadmap.sh/pdfs/', 'https://roadmap.sh/pdfs',
].includes(page); ].includes(page);
} }
export async function serializeSitemap(item) { export async function serializeSitemap(item) {
const highPriorityPages = [ const highPriorityPages = [
'https://roadmap.sh/', 'https://roadmap.sh',
'https://roadmap.sh/about/', 'https://roadmap.sh/about',
'https://roadmap.sh/roadmaps/', 'https://roadmap.sh/roadmaps',
'https://roadmap.sh/guides/', 'https://roadmap.sh/guides',
'https://roadmap.sh/videos/', 'https://roadmap.sh/videos',
...(await getRoadmapIds()).map((id) => `https://roadmap.sh/${id}/`), ...(await getRoadmapIds()).flatMap((id) => [`https://roadmap.sh/${id}`, `https://roadmap.sh/${id}/topics`]),
]; ];
// Roadmaps and other high priority pages // Roadmaps and other high priority pages
@ -37,7 +37,7 @@ export async function serializeSitemap(item) {
} }
// Guide and video pages // Guide and video pages
if (item.url.startsWith('https://roadmap.sh/guides/') || item.url.startsWith('https://roadmap.sh/videos/')) { if (item.url.startsWith('https://roadmap.sh/guides') || item.url.startsWith('https://roadmap.sh/videos')) {
return { return {
...item, ...item,
// @ts-ignore // @ts-ignore

@ -10,28 +10,35 @@ const { breadcrumbs, roadmapId } = Astro.props;
--- ---
<div class='py-7 pb-6'> <div class='py-7 pb-6'>
<!-- Desktop breadcrums --> <!-- Desktop breadcrums -->
<p class='text-gray-500 container hidden sm:block'> <p class='text-gray-500 container hidden sm:block'>
{ breadcrumbs.map((breadcrumb, counter) => { {
breadcrumbs.map((breadcrumb, counter) => {
const isLast = counter === breadcrumbs.length - 1; const isLast = counter === breadcrumbs.length - 1;
if (!isLast) { if (!isLast) {
return ( return (
<> <>
<a class='hover:text-gray-800' href={`${breadcrumb.url}/`}>{ breadcrumb.title }</a> <a class='hover:text-gray-800' href={`${breadcrumb.url}`}>
{breadcrumb.title}
</a>
<span>&nbsp;&middot;&nbsp;</span> <span>&nbsp;&middot;&nbsp;</span>
</> </>
); );
} }
return <span class='text-gray-400'>{ breadcrumb.title }</span> return <span class='text-gray-400'>{breadcrumb.title}</span>;
})} })
</p> }
</p>
<!-- Mobile breadcrums --> <!-- Mobile breadcrums -->
<p class='container block sm:hidden'> <p class='container block sm:hidden'>
<a class='bg-gray-500 py-1.5 px-3 rounded-md text-white text-xs sm:text-sm font-medium hover:bg-gray-600' href={`/${roadmapId}/`}> <a
&larr; Back to Topics List class='bg-gray-500 py-1.5 px-3 rounded-md text-white text-xs sm:text-sm font-medium hover:bg-gray-600'
</a> href={`/${roadmapId}`}
</p> >
</div> &larr; Back to Topics List
</a>
</p>
</div>

@ -18,7 +18,7 @@ const { heading, guides } = Astro.props;
</div> </div>
<a <a
href='/guides/' href='/guides'
class='hidden sm:inline transition-colors py-2 px-3 text-xs font-medium rounded-full bg-gradient-to-r from-slate-600 to-black hover:from-blue-600 hover:to-blue-800 text-white' class='hidden sm:inline transition-colors py-2 px-3 text-xs font-medium rounded-full bg-gradient-to-r from-slate-600 to-black hover:from-blue-600 hover:to-blue-800 text-white'
> >
View All Guides &rarr; View All Guides &rarr;
@ -26,7 +26,7 @@ const { heading, guides } = Astro.props;
<div class='block sm:hidden mt-3'> <div class='block sm:hidden mt-3'>
<a <a
href='/guides/' href='/guides'
class='text-sm font-regular block p-2 border border-black text-black rounded-md text-center hover:bg-black hover:text-gray-50' class='text-sm font-regular block p-2 border border-black text-black rounded-md text-center hover:bg-black hover:text-gray-50'
> >
View All Guides &nbsp;&rarr; View All Guides &nbsp;&rarr;

@ -18,7 +18,7 @@ const { heading, videos } = Astro.props;
</div> </div>
<a <a
href='/videos/' href='/videos'
class='hidden sm:inline transition-colors py-2 px-3 text-xs font-medium rounded-full bg-gradient-to-r from-slate-600 to-black hover:from-blue-600 hover:to-blue-800 text-white' class='hidden sm:inline transition-colors py-2 px-3 text-xs font-medium rounded-full bg-gradient-to-r from-slate-600 to-black hover:from-blue-600 hover:to-blue-800 text-white'
> >
View All Videos &rarr; View All Videos &rarr;
@ -26,7 +26,7 @@ const { heading, videos } = Astro.props;
<div class='block sm:hidden mt-3'> <div class='block sm:hidden mt-3'>
<a <a
href='/videos/' href='/videos'
class='text-sm font-regular block p-2 border border-black text-black rounded-md text-center hover:bg-black hover:text-gray-50' class='text-sm font-regular block p-2 border border-black text-black rounded-md text-center hover:bg-black hover:text-gray-50'
> >
View All Videos &nbsp;&rarr; View All Videos &nbsp;&rarr;

@ -4,24 +4,22 @@ import Icon from './Icon.astro';
<div class='py-6 sm:py-16 pb-10 bg-slate-900 text-white'> <div class='py-6 sm:py-16 pb-10 bg-slate-900 text-white'>
<div class='container'> <div class='container'>
<p <p class='text-gray-400 font-medium flex flex-col sm:flex-row gap-0 sm:gap-4 mb-8 sm:mb-16 justify-center'>
class='text-gray-400 font-medium flex flex-col sm:flex-row gap-0 sm:gap-4 mb-8 sm:mb-16 justify-center'
>
<a <a
class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white' class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white'
href='/roadmaps/'>Roadmaps</a href='/roadmaps'>Roadmaps</a
> >
<a <a
class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white' class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white'
href='/guides/'>Guides</a href='/guides'>Guides</a
> >
<a <a
class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white' class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white'
href='/videos/'>Videos</a href='/videos'>Videos</a
> >
<a <a
class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white' class='transition-colors px-2 py-1.5 border-b border-b-gray-700 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white'
href='/about/'>About</a href='/about'>About</a
> >
<a <a
class='transition-colors px-2 py-1.5 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white' class='transition-colors px-2 py-1.5 sm:border-b-0 sm:py-0 sm:px-0 hover:text-white'
@ -51,18 +49,18 @@ import Icon from './Icon.astro';
</a> </a>
</p> </p>
<p class='text-slate-300/60 my-4'> <p class='text-slate-300/60 my-4'>
Community created roadmaps, articles, resources and journeys to help Community created roadmaps, articles, resources and journeys to help you choose your path and grow in your
you choose your path and grow in your career. career.
</p> </p>
<div class='text-gray-400 text-sm'> <div class='text-gray-400 text-sm'>
<p> <p>
&copy; roadmap.sh &copy; roadmap.sh
<span class='mx-1.5'>&middot;</span> <span class='mx-1.5'>&middot;</span>
<a href='/about/' class='hover:text-white'>FAQs</a> <a href='/about' class='hover:text-white'>FAQs</a>
<span class='mx-1.5'>&middot;</span> <span class='mx-1.5'>&middot;</span>
<a href='/terms/' class='hover:text-white'>Terms</a> <a href='/terms' class='hover:text-white'>Terms</a>
<span class='mx-1.5'>&middot;</span> <span class='mx-1.5'>&middot;</span>
<a href='/privacy/' class='hover:text-white'>Privacy</a> <a href='/privacy' class='hover:text-white'>Privacy</a>
</p> </p>
</div> </div>
</div> </div>
@ -78,8 +76,8 @@ import Icon from './Icon.astro';
/> />
</a> </a>
<p class='text-slate-300/60 my-4'> <p class='text-slate-300/60 my-4'>
The leading DevOps resource for Kubernetes, cloud-native computing, The leading DevOps resource for Kubernetes, cloud-native computing, and the latest in at-scale development,
and the latest in at-scale development, deployment, and management. deployment, and management.
</p> </p>
<div class='text-gray-400 text-sm'> <div class='text-gray-400 text-sm'>
<p> <p>

@ -10,7 +10,7 @@ const frontmatter = roadmap.frontmatter;
--- ---
<a <a
href={`/${roadmap.id}/`} href={`/${roadmap.id}`}
class="bg-gradient-to-r from-slate-900 to-amber-900 hover:from-stone-900 hover:to-stone-900 hover:bg-gray-100 flex flex-col p-2.5 sm:p-5 rounded-md sm:rounded-lg border border-gray-200 relative h-full" class="bg-gradient-to-r from-slate-900 to-amber-900 hover:from-stone-900 hover:to-stone-900 hover:bg-gray-100 flex flex-col p-2.5 sm:p-5 rounded-md sm:rounded-lg border border-gray-200 relative h-full"
> >
<span <span

@ -13,7 +13,7 @@ const { frontmatter, id } = guide;
class:list={[ class:list={[
"block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b", "block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b",
]} ]}
href={`/guides/${id}/`} href={`/guides/${id}`}
> >
<span class="group-hover:translate-x-2 transition-transform"> <span class="group-hover:translate-x-2 transition-transform">
{frontmatter.title} {frontmatter.title}

@ -12,18 +12,18 @@ import Icon from './Icon.astro';
<!-- Desktop navigation items --> <!-- Desktop navigation items -->
<ul class='hidden sm:flex space-x-5'> <ul class='hidden sm:flex space-x-5'>
<li> <li>
<a href='/roadmaps/' class='text-gray-400 hover:text-white'>Roadmaps</a> <a href='/roadmaps' class='text-gray-400 hover:text-white'>Roadmaps</a>
</li> </li>
<li> <li>
<a href='/guides/' class='text-gray-400 hover:text-white'>Guides</a> <a href='/guides' class='text-gray-400 hover:text-white'>Guides</a>
</li> </li>
<li> <li>
<a href='/videos/' class='text-gray-400 hover:text-white'>Videos</a> <a href='/videos' class='text-gray-400 hover:text-white'>Videos</a>
</li> </li>
<li> <li>
<a <a
class='py-2 px-4 text-sm font-regular rounded-full bg-gradient-to-r from-blue-500 to-blue-700 hover:from-blue-500 hover:to-blue-600 text-white' class='py-2 px-4 text-sm font-regular rounded-full bg-gradient-to-r from-blue-500 to-blue-700 hover:from-blue-500 hover:to-blue-600 text-white'
href='/signup/' href='/signup'
> >
Subscribe Subscribe
</a> </a>
@ -31,19 +31,12 @@ import Icon from './Icon.astro';
</ul> </ul>
<!-- Mobile Navigation Button --> <!-- Mobile Navigation Button -->
<button <button class='text-gray-400 hover:text-gray-50 block sm:hidden cursor-pointer' aria-label='Menu' show-mobile-nav>
class='text-gray-400 hover:text-gray-50 block sm:hidden cursor-pointer'
aria-label='Menu'
show-mobile-nav
>
<Icon icon='hamburger' /> <Icon icon='hamburger' />
</button> </button>
<!-- Mobile Navigation Items --> <!-- Mobile Navigation Items -->
<div <div class='fixed top-0 bottom-0 left-0 right-0 z-40 bg-slate-900 items-center flex hidden' mobile-nav>
class='fixed top-0 bottom-0 left-0 right-0 z-40 bg-slate-900 items-center flex hidden'
mobile-nav
>
<button <button
close-mobile-nav close-mobile-nav
class='text-gray-400 hover:text-gray-50 block cursor-pointer absolute top-6 right-6' class='text-gray-400 hover:text-gray-50 block cursor-pointer absolute top-6 right-6'
@ -53,26 +46,16 @@ import Icon from './Icon.astro';
</button> </button>
<ul class='flex flex-col gap-2 md:gap-3 items-center w-full'> <ul class='flex flex-col gap-2 md:gap-3 items-center w-full'>
<li> <li>
<a href='/roadmaps/' class='text-xl md:text-lg hover:text-blue-300' <a href='/roadmaps' class='text-xl md:text-lg hover:text-blue-300'>Roadmaps</a>
>Roadmaps</a
>
</li> </li>
<li> <li>
<a href='/guides/' class='text-xl md:text-lg hover:text-blue-300' <a href='/guides' class='text-xl md:text-lg hover:text-blue-300'>Guides</a>
>Guides</a
>
</li> </li>
<li> <li>
<a href='/videos/' class='text-xl md:text-lg hover:text-blue-300' <a href='/videos' class='text-xl md:text-lg hover:text-blue-300'>Videos</a>
>Videos</a
>
</li> </li>
<li> <li>
<a <a href='/signup' class='text-xl md:text-lg text-red-300 hover:text-red-400'>Subscribe</a>
href='/signup/'
class='text-xl md:text-lg text-red-300 hover:text-red-400'
>Subscribe</a
>
</li> </li>
</ul> </ul>
</div> </div>
@ -84,9 +67,7 @@ import Icon from './Icon.astro';
document.querySelector('[mobile-nav]')?.classList.remove('hidden'); document.querySelector('[mobile-nav]')?.classList.remove('hidden');
}); });
document document.querySelector('[close-mobile-nav]')?.addEventListener('click', () => {
.querySelector('[close-mobile-nav]') document.querySelector('[mobile-nav]')?.classList.add('hidden');
?.addEventListener('click', () => { });
document.querySelector('[mobile-nav]')?.classList.add('hidden');
});
</script> </script>

@ -8,10 +8,7 @@ export interface Props {
const { roadmapId } = Astro.props; const { roadmapId } = Astro.props;
const hasTNSBanner = ['frontend', 'backend', 'devops'].includes(roadmapId); const hasTNSBanner = ['frontend', 'backend', 'devops'].includes(roadmapId);
const roadmapTitle = const roadmapTitle = roadmapId === 'devops' ? 'DevOps' : `${roadmapId.charAt(0).toUpperCase()}${roadmapId.slice(1)}`;
roadmapId === 'devops'
? 'DevOps'
: `${roadmapId.charAt(0).toUpperCase()}${roadmapId.slice(1)}`;
--- ---
<div <div
@ -54,15 +51,12 @@ const roadmapTitle =
]} ]}
> >
<p class='text-sm'> <p class='text-sm'>
<span <span class='text-yellow-900 bg-yellow-200 py-0.5 px-1 text-xs rounded-sm font-medium uppercase mr-0.5'>New</span>
class='text-yellow-900 bg-yellow-200 py-0.5 px-1 text-xs rounded-sm font-medium uppercase mr-0.5'
>New</span
>
Resources are here, try clicking nodes Resources are here, try clicking nodes
</p> </p>
<a <a
href={`/${roadmapId}/topics/`} href={`/${roadmapId}/topics`}
class='inline-flex items-center justify-center py-1.5 text-sm font-medium rounded-md hover:text-black text-gray-500 px-1' class='inline-flex items-center justify-center py-1.5 text-sm font-medium rounded-md hover:text-black text-gray-500 px-1'
> >
<Icon icon='search' /> <Icon icon='search' />
@ -71,13 +65,8 @@ const roadmapTitle =
</div> </div>
<!-- Mobile - Roadmap resources alert --> <!-- Mobile - Roadmap resources alert -->
<p <p class='block sm:hidden text-sm border border-yellow-500 text-yellow-700 rounded-md py-1.5 px-2 bg-white relative'>
class='block sm:hidden text-sm border border-yellow-500 text-yellow-700 rounded-md py-1.5 px-2 bg-white relative'
>
Click roadmap items for resources or visit{' '} Click roadmap items for resources or visit{' '}
<a href={`/${roadmapId}/topics/`} class='text-blue-700 underline'> <a href={`/${roadmapId}/topics`} class='text-blue-700 underline'> resources list</a>.
resources list
</a>
.
</p> </p>
</div> </div>

@ -10,17 +10,13 @@ const { roadmap, roadmapId } = Astro.props;
--- ---
<a <a
href={`/${roadmapId}/`} href={`/${roadmapId}`}
class="flex items-center justify-center bg-yellow-100 text-yellow-900 border-b py-2 sm:py-3 text-sm sm:text-md hover:bg-yellow-200" class='flex items-center justify-center bg-yellow-100 text-yellow-900 border-b py-2 sm:py-3 text-sm sm:text-md hover:bg-yellow-200'
> >
<span class="container"> <span class='container'>
<span class="hidden sm:inline" <span class='hidden sm:inline'>Click to visit the interactive version of</span>
>Click to visit the interactive version of</span <span class='inline sm:hidden'>Visit complete</span>
>
<span class="inline sm:hidden">Visit complete</span>
<span class="sm:lowercase ml-0.5 font-medium underline underline-offset-1" <span class='sm:lowercase ml-0.5 font-medium underline underline-offset-1'>{roadmap.featuredTitle} roadmap</span>
>{roadmap.featuredTitle} roadmap</span
>
</span> </span>
</a> </a>

@ -37,7 +37,7 @@ const isRoadmapReady = !isUpcoming;
!hasSearch && ( !hasSearch && (
<> <>
<a <a
href='/roadmaps/' href='/roadmaps'
class='bg-gray-500 py-1.5 px-3 rounded-md text-white text-xs sm:text-sm font-medium hover:bg-gray-600' class='bg-gray-500 py-1.5 px-3 rounded-md text-white text-xs sm:text-sm font-medium hover:bg-gray-600'
aria-label='Back to All Roadmaps' aria-label='Back to All Roadmaps'
> >
@ -76,7 +76,7 @@ const isRoadmapReady = !isUpcoming;
{ {
hasSearch && ( hasSearch && (
<a <a
href={`/${roadmapId}/`} href={`/${roadmapId}`}
class='bg-gray-500 py-1.5 px-3 rounded-md text-white text-xs sm:text-sm font-medium hover:bg-gray-600' class='bg-gray-500 py-1.5 px-3 rounded-md text-white text-xs sm:text-sm font-medium hover:bg-gray-600'
aria-label='Back to Visual Roadmap' aria-label='Back to Visual Roadmap'
> >

@ -1,21 +1,19 @@
--- ---
import Icon from "../Icon.astro"; import Icon from '../Icon.astro';
--- ---
<script src="./topics.js" /> <script src='./topics.js'></script>
<div class="sm:-mb-[68px] mt-5 sm:mt-6 relative"> <div class='sm:-mb-[68px] mt-5 sm:mt-6 relative'>
<input <input
autofocus autofocus
type="text" type='text'
id="search-topic-input" id='search-topic-input'
class="border border-gray-300 text-gray-900 text-sm sm:text-md rounded-md focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 sm:px-3 py-2" class='border border-gray-300 text-gray-900 text-sm sm:text-md rounded-md focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 sm:px-3 py-2'
placeholder="Search for a topic" placeholder='Search for a topic'
/> />
<span <span class='absolute top-1/2 -translate-y-1/2 right-4 flex items-center text-sm text-gray-500'>
class="absolute top-1/2 -translate-y-1/2 right-4 flex items-center text-sm text-gray-500" <Icon icon='search' />
>
<Icon icon="search" />
</span> </span>
</div> </div>

@ -1,5 +1,5 @@
--- ---
import type { VideoFileType } from "../lib/video"; import type { VideoFileType } from '../lib/video';
export interface Props { export interface Props {
video: VideoFileType; video: VideoFileType;
@ -11,30 +11,30 @@ const { frontmatter, id } = video;
<a <a
class:list={[ class:list={[
"block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b", 'block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b',
]} ]}
href={`/videos/${id}/`} href={`/videos/${id}`}
> >
<span class="group-hover:translate-x-2 transition-transform"> <span class='group-hover:translate-x-2 transition-transform'>
{frontmatter.title} {frontmatter.title}
{ {
frontmatter.isNew && ( frontmatter.isNew && (
<span class="bg-green-300 text-green-900 text-xs font-medium px-1.5 py-0.5 rounded-sm uppercase ml-1.5"> <span class='bg-green-300 text-green-900 text-xs font-medium px-1.5 py-0.5 rounded-sm uppercase ml-1.5'>
New New
<span class="hidden sm:inline"> <span class='hidden sm:inline'>
&middot; &middot;
{new Date(frontmatter.date).toLocaleString("default", { {new Date(frontmatter.date).toLocaleString('default', {
month: "long", month: 'long',
})} })}
</span> </span>
</span> </span>
) )
} }
</span> </span>
<span class="capitalize text-gray-500 text-xs hidden sm:block"> <span class='capitalize text-gray-500 text-xs hidden sm:block'>
{frontmatter.duration} {frontmatter.duration}
</span> </span>
<span class="text-gray-400 text-xs block sm:hidden"> &raquo;</span> <span class='text-gray-400 text-xs block sm:hidden'> &raquo;</span>
</a> </a>

@ -2,17 +2,14 @@
import Icon from './Icon.astro'; import Icon from './Icon.astro';
--- ---
<div <div class='sticky top-0 border-b border-b-yellow-300 z-20 flex h-[37px]' youtube-banner>
class='sticky top-0 border-b border-b-yellow-300 z-20 flex h-[37px]'
youtube-banner
>
<a <a
href='https://youtube.com/theroadmap?sub_confirmation=1' href='https://youtube.com/theroadmap?sub_confirmation=1'
target='_blank' target='_blank'
class='flex bg-yellow-200 text-center flex-1 items-center justify-center text-sm hover:bg-yellow-300 outline-0' class='flex bg-yellow-200 text-center flex-1 items-center justify-center text-sm hover:bg-yellow-300 outline-0'
> >
<Icon icon='youtube' class='mr-2' /> We now have a YouTube Channel.&nbsp;<span <Icon icon='youtube' class='mr-2' /> We now have a YouTube Channel.&nbsp;<span class='hidden sm:inline'
class='hidden sm:inline'>Subscribe for the video content.</span >Subscribe for the video content.</span
> >
</a> </a>
<button <button
@ -25,9 +22,7 @@ import Icon from './Icon.astro';
</div> </div>
<script> <script>
document document.querySelector('[close-youtube-banner]')?.addEventListener('click', () => {
.querySelector('[close-youtube-banner]') document.querySelector('[youtube-banner]')?.remove();
?.addEventListener('click', () => { });
document.querySelector('[youtube-banner]').remove();
});
</script> </script>

@ -3,7 +3,7 @@ import Icon from '../components/Icon.astro';
import BaseLayout from '../layouts/BaseLayout.astro'; import BaseLayout from '../layouts/BaseLayout.astro';
--- ---
<BaseLayout title='Page not found' permalink={'/404/'}> <BaseLayout title='Page not found' permalink={'/404'}>
<div class='bg-gray-100'> <div class='bg-gray-100'>
<div <div
class='py-10 md:py-32 container flex flex-col md:flex-row items-center justify-center gap-7 ' class='py-10 md:py-32 container flex flex-col md:flex-row items-center justify-center gap-7 '
@ -19,7 +19,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
Sorry, we couldn't find the page you are looking for. Sorry, we couldn't find the page you are looking for.
</p> </p>
<p> <p>
<a class="underline text-blue-700" href='/'>Homepage</a> &middot; <a href='/roadmaps/' class="underline text-blue-700">Roadmaps</a> &middot; <a href='/videos/' class="underline text-blue-700">Videos</a> <a class="underline text-blue-700" href='/'>Homepage</a> &middot; <a href='/roadmaps' class="underline text-blue-700">Roadmaps</a> &middot; <a href='/videos' class="underline text-blue-700">Videos</a>
</p> </p>
</div> </div>
</div> </div>

@ -21,7 +21,7 @@ const { file, breadcrumbs, roadmapId, roadmap, heading } = Astro.props as TopicF
title={`${heading} - roadmap.sh`} title={`${heading} - roadmap.sh`}
description={`Free resources to learn ${heading} in ${roadmap.featuredTitle}. Everything you need to know about ${heading} and how it realtes to ${roadmap.featuredTitle}.`} description={`Free resources to learn ${heading} in ${roadmap.featuredTitle}. Everything you need to know about ${heading} and how it realtes to ${roadmap.featuredTitle}.`}
noIndex={true} noIndex={true}
permalink={`/${topicId}/`} permalink={`/${topicId}`}
> >
<RoadmapBanner roadmapId={roadmapId} roadmap={roadmap} /> <RoadmapBanner roadmapId={roadmapId} roadmap={roadmap} />
<div class='bg-gray-50'> <div class='bg-gray-50'>

@ -48,7 +48,7 @@ if (roadmapFAQs.length) {
--- ---
<BaseLayout <BaseLayout
permalink={`/${roadmapId}/`} permalink={`/${roadmapId}`}
title={roadmapData?.seo?.title} title={roadmapData?.seo?.title}
description={roadmapData.seo.description} description={roadmapData.seo.description}
keywords={roadmapData.seo.keywords} keywords={roadmapData.seo.keywords}

@ -26,7 +26,7 @@ const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
title={`${roadmapData.title} Topics`} title={`${roadmapData.title} Topics`}
description={roadmapData.seo.description} description={roadmapData.seo.description}
keywords={roadmapData.seo.keywords} keywords={roadmapData.seo.keywords}
permalink={`/${roadmapId}/topics/`} permalink={`/${roadmapId}/topics`}
> >
<RoadmapHeader <RoadmapHeader
description={roadmapData.description} description={roadmapData.description}
@ -59,7 +59,7 @@ const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
'bg-gray-100 hover:bg-gray-300': totalParentCount === 3, 'bg-gray-100 hover:bg-gray-300': totalParentCount === 3,
}, },
]} ]}
href={`${topic.url}/`} href={`${topic.url}`}
> >
{topic.heading} {topic.heading}
</a> </a>

@ -2,7 +2,7 @@
import BaseLayout from '../layouts/BaseLayout.astro'; import BaseLayout from '../layouts/BaseLayout.astro';
--- ---
<BaseLayout title='About roadmap.sh' permalink={'/about/'}> <BaseLayout title='About roadmap.sh' permalink={'/about'}>
<div class='bg-white border-b pt-7 pb-7 sm:pt-12 sm:pb-10'> <div class='bg-white border-b pt-7 pb-7 sm:pt-12 sm:pb-10'>
<div class='container'> <div class='container'>
<div class='flex items-center'> <div class='flex items-center'>

@ -24,7 +24,7 @@ const { frontmatter: guideData } = guide;
<BaseLayout <BaseLayout
title={guideData.seo.title} title={guideData.seo.title}
description={guideData.seo.description} description={guideData.seo.description}
permalink={`/guides/${guideId}/`} permalink={`/guides/${guideId}`}
canonicalUrl={guideData.canonicalUrl} canonicalUrl={guideData.canonicalUrl}
> >
<GuideHeader guide={guide} /> <GuideHeader guide={guide} />

@ -10,12 +10,9 @@ const guides = await getAllGuides();
<BaseLayout <BaseLayout
title='Guides - roadmap.sh' title='Guides - roadmap.sh'
description={'Detailed guides on Software Engineering Topics'} description={'Detailed guides on Software Engineering Topics'}
permalink={`/guides/`} permalink={`/guides`}
> >
<SimplePageHeader <SimplePageHeader title='Guides' description='Succinct graphical explanations to engineering topics.' />
title='Guides'
description='Succinct graphical explanations to engineering topics.'
/>
<div class='pb-20 pt-2 bg-gray-50'> <div class='pb-20 pt-2 bg-gray-50'>
<div class='container'> <div class='container'>

@ -9,6 +9,7 @@ import { getAllVideos } from '../lib/video';
const roleRoadmaps = await getRoadmapsByTag('role-roadmap'); const roleRoadmaps = await getRoadmapsByTag('role-roadmap');
const skillRoadmaps = await getRoadmapsByTag('skill-roadmap'); const skillRoadmaps = await getRoadmapsByTag('skill-roadmap');
const guides = await getAllGuides(); const guides = await getAllGuides();
const videos = await getAllVideos(); const videos = await getAllVideos();
--- ---
@ -42,7 +43,7 @@ const videos = await getAllVideos();
heading='Role based Roadmaps' heading='Role based Roadmaps'
featuredItems={roleRoadmaps.map((roadmapItem) => ({ featuredItems={roleRoadmaps.map((roadmapItem) => ({
text: roadmapItem.frontmatter.featuredTitle, text: roadmapItem.frontmatter.featuredTitle,
url: `/${roadmapItem.id}/`, url: `/${roadmapItem.id}`,
isNew: roadmapItem.frontmatter.isNew, isNew: roadmapItem.frontmatter.isNew,
isUpcoming: roadmapItem.frontmatter.isUpcoming, isUpcoming: roadmapItem.frontmatter.isUpcoming,
}))} }))}
@ -52,7 +53,7 @@ const videos = await getAllVideos();
heading='Skill based Roadmaps' heading='Skill based Roadmaps'
featuredItems={skillRoadmaps.map((roadmapItem) => ({ featuredItems={skillRoadmaps.map((roadmapItem) => ({
text: roadmapItem.frontmatter.featuredTitle === 'Go' ? 'Go Roadmap' : roadmapItem.frontmatter.featuredTitle, text: roadmapItem.frontmatter.featuredTitle === 'Go' ? 'Go Roadmap' : roadmapItem.frontmatter.featuredTitle,
url: `/${roadmapItem.id}/`, url: `/${roadmapItem.id}`,
isNew: roadmapItem.frontmatter.isNew, isNew: roadmapItem.frontmatter.isNew,
isUpcoming: roadmapItem.frontmatter.isUpcoming, isUpcoming: roadmapItem.frontmatter.isUpcoming,
}))} }))}

@ -6,7 +6,7 @@ noIndex: true
# Privacy Policy # Privacy Policy
By using or accessing the Services in any manner, you acknowledge that you accept the practices and policies outlined in this Privacy Policy, and you hereby consent that we will collect, use, and share your information in the following ways. Remember that your use of roadmap.sh’s Services is at all times subject to the [Terms of Use](/terms/), which incorporates this Privacy Policy. Any terms we use in this Policy without defining them have the definitions given to them in the Terms of Use. By using or accessing the Services in any manner, you acknowledge that you accept the practices and policies outlined in this Privacy Policy, and you hereby consent that we will collect, use, and share your information in the following ways. Remember that your use of roadmap.sh’s Services is at all times subject to the [Terms of Use](/terms), which incorporates this Privacy Policy. Any terms we use in this Policy without defining them have the definitions given to them in the Terms of Use.
## What does this Privacy Policy cover? ## What does this Privacy Policy cover?

@ -11,7 +11,7 @@ const skillRoadmaps = await getRoadmapsByTag('skill-roadmap');
<BaseLayout <BaseLayout
title='Developer Roadmaps' title='Developer Roadmaps'
description={'Step by step guides and paths to learn different tools or technologies'} description={'Step by step guides and paths to learn different tools or technologies'}
permalink={'/roadmaps/'} permalink={'/roadmaps'}
> >
<SimplePageHeader <SimplePageHeader
title='Developer Roadmaps' title='Developer Roadmaps'

@ -7,7 +7,7 @@ import BaseLayout from '../layouts/BaseLayout.astro';
<BaseLayout <BaseLayout
title='Signup - roadmap.sh' title='Signup - roadmap.sh'
description='Register yourself to receive occasional emails about new roadmaps, updates, guides and videos' description='Register yourself to receive occasional emails about new roadmaps, updates, guides and videos'
permalink={'/signup/'} permalink={'/signup'}
noIndex={true} noIndex={true}
> >
<div class='container'> <div class='container'>

@ -23,7 +23,7 @@ const { video } = Astro.props;
<BaseLayout <BaseLayout
title={video.frontmatter.title} title={video.frontmatter.title}
description={video.frontmatter.description} description={video.frontmatter.description}
permalink={`/videos/${videoId}/`} permalink={`/videos/${videoId}`}
> >
<VideoHeader video={video} /> <VideoHeader video={video} />

@ -10,12 +10,9 @@ const videos = await getAllVideos();
<BaseLayout <BaseLayout
title='Illustrated Videos - roadmap.sh' title='Illustrated Videos - roadmap.sh'
description={'Graphical video demonstrations on software engineering topics.'} description={'Graphical video demonstrations on software engineering topics.'}
permalink={`/videos/`} permalink={`/videos`}
> >
<SimplePageHeader <SimplePageHeader title='Videos' description='Graphical video demonstrations on software engineering topics.' />
title='Videos'
description='Graphical video demonstrations on software engineering topics.'
/>
<div class='pb-20 pt-2 bg-gray-50'> <div class='pb-20 pt-2 bg-gray-50'>
<div class='container'> <div class='container'>

Loading…
Cancel
Save