Add support for multiple ads

update-sponsors
Kamran Ahmed 2 years ago
parent 4063979c2a
commit 057bbddd9f
  1. 1283
      pnpm-lock.yaml
  2. 4
      src/components/Analytics/analytics.ts
  3. 89
      src/components/PageSponsor.tsx
  4. 16
      src/data/roadmaps/backend/backend.md
  5. 16
      src/data/roadmaps/devops/devops.md
  6. 16
      src/data/roadmaps/frontend/frontend.md
  7. 16
      src/data/roadmaps/graphql/graphql.md
  8. 16
      src/data/roadmaps/nodejs/nodejs.md
  9. 2
      src/icons/close.svg
  10. 13
      src/layouts/BaseLayout.astro
  11. 4
      src/lib/best-pratice.ts
  12. 4
      src/lib/roadmap.ts
  13. 12
      src/pages/[roadmapId]/index.astro
  14. 10
      src/pages/best-practices/[bestPracticeId]/index.astro

File diff suppressed because it is too large Load Diff

@ -1,4 +1,4 @@
export {}; export { };
declare global { declare global {
interface Window { interface Window {
@ -29,7 +29,7 @@ window.fireEvent = (props: GAEventType) => {
return; return;
} }
if (window.__DEBUG__) { if (import.meta.env.DEV) {
console.log('Analytics event fired', props); console.log('Analytics event fired', props);
} }

@ -0,0 +1,89 @@
import { useStore } from '@nanostores/preact';
import { useEffect, useState } from 'preact/hooks';
import CloseIcon from '../icons/close.svg';
import { sponsorHidden } from '../stores/page';
export type PageSponsorType = {
url: string;
title: string;
imageUrl: string;
description: string;
company: string;
page: string;
};
type PageSponsorProps = {
sponsors?: PageSponsorType[];
};
export function PageSponsor(props: PageSponsorProps) {
const { sponsors = [] } = props;
const $isSponsorHidden = useStore(sponsorHidden);
const [sponsor, setSponsor] = useState<PageSponsorType>();
if (sponsors.length === 0) {
return null;
}
function loadSponsor() {
console.log('loadSponsor');
const sponsorIndex = Math.floor(Math.random() * sponsors.length);
setSponsor(sponsors[sponsorIndex]);
}
// We load the sponsor after 1second of the page load
useEffect(() => {
const timer = window.setTimeout(loadSponsor, 500);
return () => window.clearTimeout(timer);
}, []);
if ($isSponsorHidden || !sponsor) {
return null;
}
const { url, title, imageUrl, description, company, page } = sponsor;
return (
<a
href={url}
target="_blank"
rel="noopener sponsored nofollow"
class="fixed bottom-[15px] right-[15px] z-50 flex max-w-[350px] bg-white shadow-lg outline-0 outline-transparent"
onClick={() => {
window.fireEvent({
category: 'SponsorClick',
action: `${company} Redirect`,
label: `${page} / ${company} Link`,
});
}}
>
<span
class="absolute right-1.5 top-1.5 text-gray-300 hover:text-gray-800"
aria-label="Close"
aria-role="button"
close-sponsor
onClick={(e) => {
e.preventDefault();
e.stopImmediatePropagation();
sponsorHidden.set(true);
}}
>
<img alt="Close" class="h-4 w-4" src={CloseIcon} />
</span>
<img
src={imageUrl}
class="block h-[150px] w-[104.89px] object-contain lg:h-[169px] lg:w-[118.18px]"
alt="Sponsor Banner"
/>
<span class="flex flex-1 flex-col justify-between text-sm">
<span class="p-[10px]">
<span class="mb-0.5 block font-semibold">{title}</span>
<span class="block text-gray-500">{description}</span>
</span>
<span class="sponsor-footer">Partner Content</span>
</span>
</a>
);
}

@ -11,15 +11,13 @@ tnsBannerLink: 'https://thenewstack.io?utm_source=roadmap.sh&utm_medium=Referral
dimensions: dimensions:
width: 968 width: 968
height: 2840.4 height: 2840.4
sponsor: sponsors:
url: 'https://www.apollographql.com/tutorials/lift-off-part1?utm_campaign=2023-05-01_odyssey-lift-off-backend&utm_medium=display&utm_source=roadmap' - url: 'https://www.apollographql.com/tutorials/lift-off-part1?utm_campaign=2023-05-01_odyssey-lift-off-backend&utm_medium=display&utm_source=roadmap'
title: 'Free GraphQL Courses' title: 'Free GraphQL Courses'
imageUrl: 'https://i.imgur.com/pZzroyL.png' imageUrl: 'https://i.imgur.com/pZzroyL.png'
description: 'Level up your knowledge with interactive GraphQL trainings and earn a Graph Developer certification.' description: 'Level up your knowledge with interactive GraphQL trainings and earn a Graph Developer certification.'
event: page: 'Backend'
category: 'SponsorClick' company: 'Apollo'
action: 'Apollo Redirect'
label: 'Backend / Apollo Link'
schema: schema:
headline: 'Backend Developer Roadmap' headline: 'Backend Developer Roadmap'
description: 'Learn how to become a Backend Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.' description: 'Learn how to become a Backend Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'

@ -11,15 +11,13 @@ tnsBannerLink: 'https://thenewstack.io?utm_source=roadmap.sh&utm_medium=Referral
dimensions: dimensions:
width: 968 width: 968
height: 2527.46 height: 2527.46
sponsor: sponsors:
url: 'https://info.honeycomb.io/observability-engineering-oreilly-book-2022?utm_medium=paid-sponsorship&utm_source=insight-partners&utm_campaign=plg_insightpartners_paidsponsorship' - url: 'https://info.honeycomb.io/observability-engineering-oreilly-book-2022?utm_medium=paid-sponsorship&utm_source=insight-partners&utm_campaign=plg_insightpartners_paidsponsorship'
title: 'Free eBook' title: 'Free eBook'
imageUrl: 'https://i.imgur.com/zS1FMNo.jpg' imageUrl: 'https://i.imgur.com/zS1FMNo.jpg'
description: 'Learn how to debug more quickly & get more time to innovate by starting your observability journey' description: 'Learn how to debug more quickly & get more time to innovate by starting your observability journey'
event: page: 'DevOps'
category: 'SponsorClick' company: 'Honeycomb'
action: 'Honeycomb Redirect'
label: 'DevOps / Honeycomb Link'
schema: schema:
headline: 'DevOps Roadmap' headline: 'DevOps Roadmap'
description: 'Learn to become a DevOps, SRE or get any other operations role with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.' description: 'Learn to become a DevOps, SRE or get any other operations role with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'

@ -11,15 +11,13 @@ tnsBannerLink: 'https://thenewstack.io?utm_source=roadmap.sh&utm_medium=Referral
dimensions: dimensions:
width: 968 width: 968
height: 2822.1 height: 2822.1
sponsor: sponsors:
url: 'https://info.honeycomb.io/observability-engineering-oreilly-book-2022?utm_medium=paid-sponsorship&utm_source=insight-partners&utm_campaign=plg_insightpartners_paidsponsorship' - url: 'https://info.honeycomb.io/observability-engineering-oreilly-book-2022?utm_medium=paid-sponsorship&utm_source=insight-partners&utm_campaign=plg_insightpartners_paidsponsorship'
title: 'Free eBook' title: 'Free eBook'
imageUrl: 'https://i.imgur.com/zS1FMNo.jpg' imageUrl: 'https://i.imgur.com/zS1FMNo.jpg'
description: 'Learn how to debug more quickly & get more time to innovate by starting your observability journey' description: 'Learn how to debug more quickly & get more time to innovate by starting your observability journey'
event: page: 'Frontend'
category: 'SponsorClick' company: 'Honeycomb'
action: 'Honeycomb Redirect'
label: 'Frontend / Honeycomb Link'
schema: schema:
headline: 'Frontend Developer Roadmap' headline: 'Frontend Developer Roadmap'
description: 'Learn how to become a Frontend Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.' description: 'Learn how to become a Frontend Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'

@ -11,15 +11,13 @@ hasTopics: true
dimensions: dimensions:
width: 968 width: 968
height: 1669.8 height: 1669.8
sponsor: sponsors:
url: 'https://www.apollographql.com/tutorials/lift-off-part1?utm_campaign=2023-05-01_odyssey-lift-off-graphql&utm_medium=display&utm_source=roadmap' - url: 'https://www.apollographql.com/tutorials/lift-off-part1?utm_campaign=2023-05-01_odyssey-lift-off-graphql&utm_medium=display&utm_source=roadmap'
title: 'Free GraphQL Courses' title: 'Free GraphQL Courses'
imageUrl: 'https://i.imgur.com/pZzroyL.png' imageUrl: 'https://i.imgur.com/pZzroyL.png'
description: 'Level up your knowledge with interactive GraphQL trainings and earn a Graph Developer certification.' description: 'Level up your knowledge with interactive GraphQL trainings and earn a Graph Developer certification.'
event: page: 'GraphQL'
category: 'SponsorClick' company: 'Apollo'
action: 'Apollo Redirect'
label: 'GraphQL / Apollo Link'
schema: schema:
headline: 'GraphQL Roadmap' headline: 'GraphQL Roadmap'
description: 'Learn how to use GraphQL with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.' description: 'Learn how to use GraphQL with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'

@ -11,15 +11,13 @@ hasTopics: true
dimensions: dimensions:
width: 968 width: 968
height: 2474.06 height: 2474.06
sponsor: sponsors:
url: 'https://www.apollographql.com/tutorials/lift-off-part1?utm_campaign=2023-05-01_odyssey-lift-off-nodejs&utm_medium=display&utm_source=roadmap' - url: 'https://www.apollographql.com/tutorials/lift-off-part1?utm_campaign=2023-05-01_odyssey-lift-off-nodejs&utm_medium=display&utm_source=roadmap'
title: 'Free GraphQL Courses' title: 'Free GraphQL Courses'
imageUrl: 'https://i.imgur.com/pZzroyL.png' imageUrl: 'https://i.imgur.com/pZzroyL.png'
description: 'Level up your knowledge with interactive GraphQL trainings and earn a Graph Developer certification.' description: 'Level up your knowledge with interactive GraphQL trainings and earn a Graph Developer certification.'
event: page: 'Node.js'
category: 'SponsorClick' company: 'Apollo'
action: 'Apollo Redirect'
label: 'Node.js / Apollo Link'
schema: schema:
headline: 'Node.js Roadmap' headline: 'Node.js Roadmap'
description: 'Learn Node.js with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.' description: 'Learn Node.js with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'

@ -1,4 +1,4 @@
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <svg aria-hidden="true" class="w-5 h-5" fill="#c6c7c7" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" <path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"></path> clip-rule="evenodd"></path>

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 388 B

@ -2,11 +2,10 @@
import Analytics from '../components/Analytics/Analytics.astro'; import Analytics from '../components/Analytics/Analytics.astro';
import Authenticator from '../components/Authenticator/Authenticator.astro'; import Authenticator from '../components/Authenticator/Authenticator.astro';
import Footer from '../components/Footer.astro'; import Footer from '../components/Footer.astro';
import { PageProgress } from '../components/PageProgress';
import Navigation from '../components/Navigation/Navigation.astro'; import Navigation from '../components/Navigation/Navigation.astro';
import OpenSourceBanner from '../components/OpenSourceBanner.astro'; import OpenSourceBanner from '../components/OpenSourceBanner.astro';
import type { SponsorType } from '../components/Sponsor/Sponsor.astro'; import { PageProgress } from '../components/PageProgress';
import Sponsor from '../components/Sponsor/Sponsor.astro'; import { PageSponsor,PageSponsorType } from '../components/PageSponsor';
import { siteConfig } from '../lib/config'; import { siteConfig } from '../lib/config';
import '../styles/global.css'; import '../styles/global.css';
@ -18,7 +17,7 @@ export interface Props {
noIndex?: boolean; noIndex?: boolean;
canonicalUrl?: string; canonicalUrl?: string;
permalink?: string; permalink?: string;
sponsor?: SponsorType; sponsors?: PageSponsorType[];
jsonLd?: Record<string, unknown>[]; jsonLd?: Record<string, unknown>[];
} }
@ -29,7 +28,7 @@ const {
noIndex = false, noIndex = false,
permalink = '', permalink = '',
canonicalUrl: givenCanonical = '', canonicalUrl: givenCanonical = '',
sponsor, sponsors,
jsonLd = [], jsonLd = [],
redirectUrl = '', redirectUrl = '',
} = Astro.props; } = Astro.props;
@ -136,12 +135,12 @@ const commitUrl = `https://github.com/kamranahmedse/developer-roadmap/commit/${
<slot name='page-footer'> <slot name='page-footer'>
<OpenSourceBanner /> <OpenSourceBanner />
<Footer /> <Footer />
{sponsor && <Sponsor sponsor={sponsor} />}
</slot> </slot>
<Analytics /> <Analytics />
<Authenticator /> <Authenticator />
<PageProgress client:load /> <PageProgress client:idle />
<PageSponsor sponsors={sponsors || []} client:idle />
<slot name='after-footer' /> <slot name='after-footer' />
</body> </body>

@ -1,5 +1,5 @@
import type { PageSponsorType } from '../components/PageSponsor';
import type { MarkdownFileType } from './file'; import type { MarkdownFileType } from './file';
import type { SponsorType } from '../components/Sponsor/Sponsor.astro';
export interface BestPracticeFrontmatter { export interface BestPracticeFrontmatter {
jsonUrl: string; jsonUrl: string;
@ -15,7 +15,7 @@ export interface BestPracticeFrontmatter {
width: number; width: number;
height: number; height: number;
}; };
sponsor?: SponsorType; sponsors?: PageSponsorType[];
seo: { seo: {
title: string; title: string;
description: string; description: string;

@ -1,5 +1,5 @@
import type { PageSponsorType } from '../components/PageSponsor';
import type { MarkdownFileType } from './file'; import type { MarkdownFileType } from './file';
import type { SponsorType } from '../components/Sponsor/Sponsor.astro';
export interface RoadmapFrontmatter { export interface RoadmapFrontmatter {
jsonUrl: string; jsonUrl: string;
@ -18,7 +18,7 @@ export interface RoadmapFrontmatter {
width: number; width: number;
height: number; height: number;
}; };
sponsor?: SponsorType; sponsors?: PageSponsorType[];
seo: { seo: {
title: string; title: string;
description: string; description: string;

@ -5,14 +5,14 @@ import MarkdownFile from '../../components/MarkdownFile.astro';
import RelatedRoadmaps from '../../components/RelatedRoadmaps.astro'; import RelatedRoadmaps from '../../components/RelatedRoadmaps.astro';
import RoadmapHeader from '../../components/RoadmapHeader.astro'; import RoadmapHeader from '../../components/RoadmapHeader.astro';
import ShareIcons from '../../components/ShareIcons/ShareIcons.astro'; import ShareIcons from '../../components/ShareIcons/ShareIcons.astro';
import { TopicDetail } from '../../components/TopicDetail/TopicDetail';
import UpcomingForm from '../../components/UpcomingForm.astro'; import UpcomingForm from '../../components/UpcomingForm.astro';
import BaseLayout from '../../layouts/BaseLayout.astro'; import BaseLayout from '../../layouts/BaseLayout.astro';
import { TopicDetail } from '../../components/TopicDetail/TopicDetail';
import { import {
generateArticleSchema, generateArticleSchema,
generateFAQSchema, generateFAQSchema,
} from '../../lib/jsonld-schema'; } from '../../lib/jsonld-schema';
import { getRoadmapIds, RoadmapFrontmatter } from '../../lib/roadmap'; import { RoadmapFrontmatter,getRoadmapIds } from '../../lib/roadmap';
export async function getStaticPaths() { export async function getStaticPaths() {
const roadmapIds = await getRoadmapIds(); const roadmapIds = await getRoadmapIds();
@ -63,7 +63,7 @@ const contentContributionLink = `https://github.com/kamranahmedse/developer-road
title={roadmapData?.seo?.title} title={roadmapData?.seo?.title}
description={roadmapData.seo.description} description={roadmapData.seo.description}
keywords={roadmapData.seo.keywords} keywords={roadmapData.seo.keywords}
sponsor={roadmapData.sponsor} sponsors={roadmapData.sponsors}
noIndex={roadmapData.isUpcoming} noIndex={roadmapData.isUpcoming}
jsonLd={jsonLdSchema} jsonLd={jsonLdSchema}
> >
@ -95,7 +95,7 @@ const contentContributionLink = `https://github.com/kamranahmedse/developer-road
description={roadmapData.briefDescription} description={roadmapData.briefDescription}
pageUrl={`https://roadmap.sh/${roadmapId}`} pageUrl={`https://roadmap.sh/${roadmapId}`}
/> />
<TopicDetail client:load /> <TopicDetail client:idle />
<FrameRenderer <FrameRenderer
resourceType={'roadmap'} resourceType={'roadmap'}

@ -1,14 +1,14 @@
--- ---
import { TopicDetail } from '../../../components/TopicDetail/TopicDetail';
import BestPracticeHeader from '../../../components/BestPracticeHeader.astro'; import BestPracticeHeader from '../../../components/BestPracticeHeader.astro';
import FrameRenderer from '../../../components/FrameRenderer/FrameRenderer.astro'; import FrameRenderer from '../../../components/FrameRenderer/FrameRenderer.astro';
import MarkdownFile from '../../../components/MarkdownFile.astro'; import MarkdownFile from '../../../components/MarkdownFile.astro';
import ShareIcons from '../../../components/ShareIcons/ShareIcons.astro'; import ShareIcons from '../../../components/ShareIcons/ShareIcons.astro';
import { TopicDetail } from '../../../components/TopicDetail/TopicDetail';
import UpcomingForm from '../../../components/UpcomingForm.astro'; import UpcomingForm from '../../../components/UpcomingForm.astro';
import BaseLayout from '../../../layouts/BaseLayout.astro'; import BaseLayout from '../../../layouts/BaseLayout.astro';
import { import {
BestPracticeFrontmatter, BestPracticeFrontmatter,
getBestPracticeIds, getBestPracticeIds,
} from '../../../lib/best-pratice'; } from '../../../lib/best-pratice';
import { generateArticleSchema } from '../../../lib/jsonld-schema'; import { generateArticleSchema } from '../../../lib/jsonld-schema';
@ -55,7 +55,7 @@ const contentContributionLink = `https://github.com/kamranahmedse/developer-road
title={bestPracticeData?.seo?.title} title={bestPracticeData?.seo?.title}
description={bestPracticeData.seo.description} description={bestPracticeData.seo.description}
keywords={bestPracticeData.seo.keywords} keywords={bestPracticeData.seo.keywords}
sponsor={bestPracticeData.sponsor} sponsors={bestPracticeData.sponsors}
noIndex={bestPracticeData.isUpcoming} noIndex={bestPracticeData.isUpcoming}
jsonLd={jsonLdSchema} jsonLd={jsonLdSchema}
> >
@ -85,7 +85,7 @@ const contentContributionLink = `https://github.com/kamranahmedse/developer-road
pageUrl={`https://roadmap.sh/best-practices/${bestPracticeId}`} pageUrl={`https://roadmap.sh/best-practices/${bestPracticeId}`}
/> />
<TopicDetail client:load /> <TopicDetail client:idle />
<FrameRenderer <FrameRenderer
resourceType={'best-practice'} resourceType={'best-practice'}

Loading…
Cancel
Save