Skip to content

Commit 1f2c829

Browse files
committed
chore: homepage jsonld + feature/daily-challenge rename
1 parent 92a05a2 commit 1f2c829

File tree

12 files changed

+199
-29
lines changed

12 files changed

+199
-29
lines changed

next.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ const nextConfig = {
2929
destination: '/features/roadmap',
3030
permanent: true,
3131
},
32+
{
33+
source: '/features/daily-challenges',
34+
destination: '/features/daily-coding-challenges',
35+
permanent: true,
36+
},
3237
];
3338
},
3439
async headers() {

src/app/(marketing)/blog/posts/introducing-techblitz.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ For those with a competitive spirit, our global leaderboard system lets you meas
7979
</div>
8080

8181
<div className="mt-4">
82-
Explore our daily challenge system in detail <a href="/features/daily-challenges" aria-label="Navigate to Daily Challenges" className="text-accent">here</a>, or <a href="/signup" aria-label="Navigate to Signup" className="text-accent">begin your journey today</a>.
82+
Explore our daily challenge system in detail <a href="/features/daily-coding-challenges" aria-label="Navigate to Daily Challenges" className="text-accent">here</a>, or <a href="/signup" aria-label="Navigate to Signup" className="text-accent">begin your journey today</a>.
8383
</div>
8484

8585
<br />

src/app/(marketing)/page.tsx

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import { getBaseUrl } from '@/utils';
2626
import { getTodaysQuestion } from '@/utils/data/questions/get-today';
2727
import { fetchGithubStars } from '@/utils/data/misc/get-github-stars';
2828
import { getUserCount } from '@/utils/data/user/get-user-count';
29+
import { WebPageJsonLd } from '@/types/Seo';
30+
import { WebPageJsonLdBreadcrumb } from '@/utils/seo';
2931

3032
const title = 'Learn to code | TechBlitz';
3133
const description = 'Learning to code made simple';
@@ -78,6 +80,38 @@ export const metadata: Metadata = {
7880
};
7981

8082
export default async function Page() {
83+
const jsonLd: WebPageJsonLd = {
84+
'@context': 'https://schema.org',
85+
'@type': 'WebPage',
86+
url: getBaseUrl(),
87+
headline: 'Learn to code | TechBlitz',
88+
description: 'Learning to code made simple',
89+
image:
90+
'https://opengraph.b-cdn.net/production/images/cd5047e6-d495-4666-928e-37d9e52e1806.png?token=hJkK0Ghd13chZ2eBfAOxNQ8ejBMfE_oTwEuHkvxu9aQ&height=667&width=1200&expires=33269844531',
91+
breadcrumb: WebPageJsonLdBreadcrumb,
92+
author: {
93+
'@type': 'Organization',
94+
name: 'TechBlitz',
95+
url: getBaseUrl(),
96+
},
97+
dateModified: new Date().toISOString(),
98+
datePublished: new Date().toISOString(),
99+
mainEntityOfPage: {
100+
'@type': 'WebPage',
101+
'@id': getBaseUrl(),
102+
},
103+
keywords:
104+
'learn to code for free, beginner-friendly coding lessons, interactive coding challenges, daily programming practice, personalized coding roadmap, improve coding skills, best platform to learn coding, AI-assisted coding, learn javascript',
105+
publisher: {
106+
'@type': 'Organization',
107+
name: 'TechBlitz',
108+
logo: {
109+
'@type': 'ImageObject',
110+
url: 'https://opengraph.b-cdn.net/production/images/cd5047e6-d495-4666-928e-37d9e52e1806.png?token=hJkK0Ghd13chZ2eBfAOxNQ8ejBMfE_oTwEuHkvxu9aQ&height=667&width=1200&expires=33269844531',
111+
},
112+
},
113+
};
114+
81115
const [userCount, githubStars, dailyQuestion] = await Promise.all([
82116
getUserCount(),
83117
fetchGithubStars(),
@@ -88,27 +122,33 @@ export default async function Page() {
88122
'https://customer-8s5ov2shcw99ezk2.cloudflarestream.com/e49b63ed5ee42085d838a50928855776/iframe?poster=https%3A%2F%2Fcustomer-8s5ov2shcw99ezk2.cloudflarestream.com%2Fe49b63ed5ee42085d838a50928855776%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600';
89123

90124
return (
91-
<div className="overflow-x-hidden">
92-
<div className="z-30">
93-
<div className="container">
94-
<HomepageHero />
95-
<HomepageHeroImages
96-
imageSrc={DashboardImg}
97-
videoSrc={homepageHeroIframe}
98-
videoPoster="https://customer-8s5ov2shcw99ezk2.cloudflarestream.com/e49b63ed5ee42085d838a50928855776/iframe?poster=https%3A%2F%2Fcustomer-8s5ov2shcw99ezk2.cloudflarestream.com%2Fe49b63ed5ee42085d838a50928855776%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600"
99-
/>
100-
<SocialProof
101-
userCount={userCount}
102-
githubStars={githubStars.stargazers_count}
103-
dailyQuestion={dailyQuestion}
104-
/>
105-
<FeaturesBentoGrid />
106-
<HomepageLargeText />
107-
<ComparisonBlock />
108-
<OpenSourceBlock />
109-
<CallToActionBlock title="The best platform to learn to code" />
125+
<>
126+
<script
127+
type="application/ld+json"
128+
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
129+
/>
130+
<div className="overflow-x-hidden">
131+
<div className="z-30">
132+
<div className="container">
133+
<HomepageHero />
134+
<HomepageHeroImages
135+
imageSrc={DashboardImg}
136+
videoSrc={homepageHeroIframe}
137+
videoPoster="https://customer-8s5ov2shcw99ezk2.cloudflarestream.com/e49b63ed5ee42085d838a50928855776/iframe?poster=https%3A%2F%2Fcustomer-8s5ov2shcw99ezk2.cloudflarestream.com%2Fe49b63ed5ee42085d838a50928855776%2Fthumbnails%2Fthumbnail.jpg%3Ftime%3D%26height%3D600"
138+
/>
139+
<SocialProof
140+
userCount={userCount}
141+
githubStars={githubStars.stargazers_count}
142+
dailyQuestion={dailyQuestion}
143+
/>
144+
<FeaturesBentoGrid />
145+
<HomepageLargeText />
146+
<ComparisonBlock />
147+
<OpenSourceBlock />
148+
<CallToActionBlock title="The best platform to learn to code" />
149+
</div>
110150
</div>
111151
</div>
112-
</div>
152+
</>
113153
);
114154
}

src/app/sitemap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
3939
lastModified: new Date(),
4040
},
4141
{
42-
url: `${baseUrl}/features/daily-challenges`,
42+
url: `${baseUrl}/features/daily-coding-challenges`,
4343
lastModified: new Date(),
4444
},
4545
{

src/components/marketing/global/footer/footer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const footerItems = [
1616
},
1717
{
1818
title: 'Daily Challenges',
19-
href: '/features/daily-challenges',
19+
href: '/features/daily-coding-challenges',
2020
ariaLabel: 'Daily Challenges',
2121
},
2222
{

src/components/marketing/global/navigation/mobile-menu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const menuItems: MenuItem[] = [
2525
label: 'Features',
2626
children: [
2727
{ label: 'Roadmaps', href: '/features/roadmaps' },
28-
{ label: 'Daily Challenges', href: '/features/daily-challenges' },
28+
{ label: 'Daily Challenges', href: '/features/daily-coding-challenges' },
2929
{ label: 'Statistics', href: '/features/statistics' },
3030
],
3131
},

src/components/marketing/global/navigation/navigation-items.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const features = [
5252
},
5353
{
5454
title: 'Daily Challenges',
55-
href: '/features/daily-challenges',
55+
href: '/features/daily-coding-challenges',
5656
description: 'Tackle daily challenges to sharpen your developer skills.',
5757
ariaLabel: 'Navigate to Daily Challenges',
5858
},
@@ -86,7 +86,7 @@ export function NavigationMenuItems() {
8686
AI-powered paths to accelerate your learning journey.
8787
</ListItem>
8888
<ListItem
89-
href="/features/daily-challenges"
89+
href="/features/daily-coding-challenges"
9090
title="Daily Challenges"
9191
aria-label="Navigate to Daily Challenges"
9292
>
@@ -107,7 +107,7 @@ export function NavigationMenuItems() {
107107
Gain insights and track your growth over time.
108108
</ListItem>
109109
<ListItem
110-
href="/features/daily-challenges"
110+
href="/features/daily-coding-challenges"
111111
title="Daily Challenges"
112112
aria-label="Navigate to Daily Challenges"
113113
>

src/components/marketing/global/social-proof.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export default function SocialProof({
6969
<Button
7070
variant="default"
7171
size="lg"
72-
href="/features/daily-challenges"
72+
href="/features/daily-coding-challenges"
7373
aria-label="Navigate to Daily Challenges"
7474
>
7575
Learn more

src/components/marketing/homepage/features/features-bento-grid.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export default async function FeaturesBentoGrid() {
123123
</div>
124124
</Link>
125125
<Link
126-
href="/features/daily-challenges"
126+
href="/features/daily-coding-challenges"
127127
className={cn(
128128
'col-span-full lg:col-span-2 group overflow-hidden',
129129
cardClasses

src/types/Seo.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,56 @@ export type QuizJsonLd = {
3131

3232
teaches: string;
3333
};
34+
35+
export type WebPageJsonLd = {
36+
'@context': 'https://schema.org';
37+
'@type': 'WebPage';
38+
// The URL of the webpage
39+
url: string;
40+
// The headline or title of the webpage
41+
headline: string;
42+
// A brief description of the webpage
43+
description: string;
44+
// The URL of the image representing the webpage
45+
image: string;
46+
author?: {
47+
'@type': 'Person' | 'Organization';
48+
// Name of the author or organization
49+
name: string;
50+
// URL of the author's profile or organization
51+
url?: string;
52+
};
53+
publisher?: {
54+
'@type': 'Organization';
55+
// Name of the publisher
56+
name: string;
57+
logo?: {
58+
'@type': 'ImageObject';
59+
// URL of the publisher's logo
60+
url: string;
61+
};
62+
};
63+
// ISO 8601 date format: e.g., "2023-01-01T12:00:00Z"
64+
datePublished?: string;
65+
// ISO 8601 date format
66+
dateModified?: string;
67+
mainEntityOfPage?: {
68+
'@type': 'WebPage';
69+
// Canonical URL of the main entity of the page
70+
'@id': string;
71+
};
72+
// Comma-separated list of keywords
73+
keywords?: string;
74+
breadcrumb?: {
75+
'@type': 'BreadcrumbList';
76+
itemListElement: {
77+
'@type': 'ListItem';
78+
// Position of the breadcrumb in the list
79+
position: number;
80+
// Name of the breadcrumb item
81+
name: string;
82+
// URL of the breadcrumb item
83+
item: string;
84+
}[];
85+
};
86+
};

src/utils/seo.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Metadata } from 'next';
22
import { getBaseUrl } from '@/utils';
33
import { Question } from '@/types/Questions';
4+
import { WebPageJsonLd } from '@/types/Seo';
45

56
interface OgImageProps {
67
text: string;
@@ -136,3 +137,74 @@ export const getQuestionEducationLevel = (question: Question['difficulty']) => {
136137
return 'intermediate';
137138
}
138139
};
140+
141+
export const WebPageJsonLdBreadcrumb: WebPageJsonLd['breadcrumb'] = {
142+
'@type': 'BreadcrumbList',
143+
itemListElement: [
144+
{
145+
'@type': 'ListItem',
146+
position: 1,
147+
name: 'Home',
148+
item: getBaseUrl(),
149+
},
150+
// dashboard questions
151+
{
152+
'@type': 'ListItem',
153+
position: 2,
154+
name: 'Questions',
155+
item: getBaseUrl() + '/questions',
156+
},
157+
{
158+
'@type': 'ListItem',
159+
position: 3,
160+
name: 'Explore Questions',
161+
item: getBaseUrl() + '/questions/explore',
162+
},
163+
{
164+
'@type': 'ListItem',
165+
position: 4,
166+
name: 'Daily Challenge',
167+
item: getBaseUrl() + '/daily-challenge',
168+
},
169+
// features
170+
{
171+
'@type': 'ListItem',
172+
position: 5,
173+
name: 'Roadmap',
174+
item: getBaseUrl() + '/features/roadmap',
175+
},
176+
{
177+
'@type': 'ListItem',
178+
position: 6,
179+
name: 'Features',
180+
item: getBaseUrl() + '/features/daily-coding-challenges',
181+
},
182+
{
183+
'@type': 'ListItem',
184+
position: 7,
185+
name: 'Statistics',
186+
item: getBaseUrl() + '/features/statistics',
187+
},
188+
// blog
189+
{
190+
'@type': 'ListItem',
191+
position: 8,
192+
name: 'Blog',
193+
item: getBaseUrl() + '/blog',
194+
},
195+
// pricing
196+
{
197+
'@type': 'ListItem',
198+
position: 9,
199+
name: 'Pricing',
200+
item: getBaseUrl() + '/pricing',
201+
},
202+
// faqs
203+
{
204+
'@type': 'ListItem',
205+
position: 10,
206+
name: 'FAQs',
207+
item: getBaseUrl() + '/faqs',
208+
},
209+
],
210+
};

0 commit comments

Comments
 (0)