Skip to content

Commit e8e8683

Browse files
committed
fix: address code review findings - XSS, URLs, schemas, validation
🤖 Committed by claude-swarm
1 parent 0377bab commit e8e8683

File tree

11 files changed

+50
-40
lines changed

11 files changed

+50
-40
lines changed

src/app/about/page.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Metadata } from 'next';
22
import Link from 'next/link';
33
import JsonLd from '@/components/JsonLd';
44
import { generateBreadcrumbSchema } from '@/lib/schemas/breadcrumb';
5+
import { BASE_URL } from '@/lib/constants';
56

67
export const metadata: Metadata = {
78
title: 'About',
@@ -14,13 +15,13 @@ export const metadata: Metadata = {
1415
title: 'About Denver MeshCore',
1516
description:
1617
"Learn about MeshCore technology and the Denver mesh networking community building Colorado's decentralized communication network.",
17-
url: 'https://denvermc.com/about',
18+
url: `${BASE_URL}/about`,
1819
},
1920
};
2021

2122
const breadcrumbData = generateBreadcrumbSchema([
22-
{ name: 'Home', url: 'https://denvermc.com' },
23-
{ name: 'About', url: 'https://denvermc.com/about' },
23+
{ name: 'Home', url: BASE_URL },
24+
{ name: 'About', url: `${BASE_URL}/about` },
2425
]);
2526

2627
export default function AboutPage() {

src/app/blog/[slug]/page.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { MDXRemote } from 'next-mdx-remote/rsc';
99
import { useMDXComponents } from '../../../../mdx-components';
1010
import remarkGfm from 'remark-gfm';
1111
import rehypeSlug from 'rehype-slug';
12+
import { BASE_URL } from '@/lib/constants';
1213

1314
interface BlogPostPageProps {
1415
params: Promise<{
@@ -42,8 +43,7 @@ export async function generateMetadata({ params }: BlogPostPageProps): Promise<M
4243
}
4344

4445
const { frontmatter } = post;
45-
const baseUrl = 'https://denvermc.org';
46-
const postUrl = `${baseUrl}/blog/${slug}`;
46+
const postUrl = `${BASE_URL}/blog/${slug}`;
4747

4848
return {
4949
title: frontmatter.title,
@@ -66,13 +66,13 @@ export async function generateMetadata({ params }: BlogPostPageProps): Promise<M
6666
{
6767
url: frontmatter.image.startsWith('http')
6868
? frontmatter.image
69-
: `${baseUrl}${frontmatter.image}`,
69+
: `${BASE_URL}${frontmatter.image}`,
7070
alt: frontmatter.imageAlt || frontmatter.title,
7171
},
7272
]
7373
: [
7474
{
75-
url: `${baseUrl}/logo-512.png`,
75+
url: `${BASE_URL}/logo-512.png`,
7676
width: 512,
7777
height: 512,
7878
alt: 'Denver MeshCore Logo',
@@ -86,8 +86,8 @@ export async function generateMetadata({ params }: BlogPostPageProps): Promise<M
8686
title: frontmatter.title,
8787
description: frontmatter.description,
8888
images: frontmatter.image
89-
? [frontmatter.image.startsWith('http') ? frontmatter.image : `${baseUrl}${frontmatter.image}`]
90-
: [`${baseUrl}/logo-512.png`],
89+
? [frontmatter.image.startsWith('http') ? frontmatter.image : `${BASE_URL}${frontmatter.image}`]
90+
: [`${BASE_URL}/logo-512.png`],
9191
},
9292
};
9393
}
@@ -116,9 +116,9 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
116116
});
117117

118118
const breadcrumbSchema = generateBreadcrumbSchema([
119-
{ name: 'Home', url: 'https://denvermc.org' },
120-
{ name: 'Blog', url: 'https://denvermc.org/blog' },
121-
{ name: frontmatter.title, url: `https://denvermc.org/blog/${slug}` },
119+
{ name: 'Home', url: BASE_URL },
120+
{ name: 'Blog', url: `${BASE_URL}/blog` },
121+
{ name: frontmatter.title, url: `${BASE_URL}/blog/${slug}` },
122122
]);
123123

124124
// Get related posts based on shared tags

src/app/blog/layout.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Link from 'next/link';
33
import { getAllTags } from '@/lib/blog';
44
import JsonLd from '@/components/JsonLd';
55
import { generateBreadcrumbSchema } from '@/lib/schemas/breadcrumb';
6+
import { BASE_URL } from '@/lib/constants';
67

78
export const metadata: Metadata = {
89
title: {
@@ -18,7 +19,7 @@ export const metadata: Metadata = {
1819
title: 'Denver MeshCore Blog',
1920
description:
2021
'News, tutorials, and updates from the Denver MeshCore community. Learn about mesh networking and off-grid communication.',
21-
url: 'https://denvermc.com/blog',
22+
url: `${BASE_URL}/blog`,
2223
type: 'website',
2324
},
2425
twitter: {
@@ -30,8 +31,8 @@ export const metadata: Metadata = {
3031
};
3132

3233
const breadcrumbData = generateBreadcrumbSchema([
33-
{ name: 'Home', url: 'https://denvermc.com' },
34-
{ name: 'Blog', url: 'https://denvermc.com/blog' },
34+
{ name: 'Home', url: BASE_URL },
35+
{ name: 'Blog', url: `${BASE_URL}/blog` },
3536
]);
3637

3738
interface BlogLayoutProps {

src/app/layout.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import JsonLd, {
88
websiteSchema,
99
communityOrganizationSchema,
1010
} from "@/components/JsonLd";
11+
import { BASE_URL } from "@/lib/constants";
1112

1213
const inter = Inter({
1314
variable: "--font-inter",
@@ -22,7 +23,7 @@ const geistMono = Geist_Mono({
2223
});
2324

2425
export const metadata: Metadata = {
25-
metadataBase: new URL("https://denvermc.com"),
26+
metadataBase: new URL(BASE_URL),
2627
title: {
2728
default: "Denver MeshCore Community Platform",
2829
template: "%s | Denver MeshCore",
@@ -70,7 +71,7 @@ export const metadata: Metadata = {
7071
openGraph: {
7172
type: "website",
7273
locale: "en_US",
73-
url: "https://denvermc.com",
74+
url: BASE_URL,
7475
siteName: "Denver MeshCore",
7576
title: "Denver MeshCore Community Platform",
7677
description:

src/app/locations/[city]/page.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
getCoverageBadgeColor,
1414
getCoverageDescription,
1515
} from '@/lib/utils/coverage';
16+
import { BASE_URL } from '@/lib/constants';
1617

1718
interface CityPageProps {
1819
params: Promise<{ city: string }>;
@@ -55,7 +56,7 @@ export async function generateMetadata({ params }: CityPageProps): Promise<Metad
5556
openGraph: {
5657
title: `${location.name} Mesh Network | Denver MeshCore`,
5758
description: location.description,
58-
url: `https://denvermc.com/locations/${location.slug}`,
59+
url: `${BASE_URL}/locations/${location.slug}`,
5960
type: 'website',
6061
},
6162
twitter: {
@@ -117,17 +118,17 @@ export default async function CityPage({ params }: CityPageProps) {
117118
}
118119

119120
const breadcrumbData = generateBreadcrumbSchema([
120-
{ name: 'Home', url: 'https://denvermc.com' },
121-
{ name: 'Locations', url: 'https://denvermc.com/locations' },
122-
{ name: location.name, url: `https://denvermc.com/locations/${location.slug}` },
121+
{ name: 'Home', url: BASE_URL },
122+
{ name: 'Locations', url: `${BASE_URL}/locations` },
123+
{ name: location.name, url: `${BASE_URL}/locations/${location.slug}` },
123124
]);
124125

125126
const pageSchema = {
126127
'@context': 'https://schema.org',
127128
'@type': 'Place',
128129
name: `${location.name} Mesh Network`,
129130
description: location.description,
130-
url: `https://denvermc.com/locations/${location.slug}`,
131+
url: `${BASE_URL}/locations/${location.slug}`,
131132
geo: {
132133
'@type': 'GeoCoordinates',
133134
latitude: location.coordinates.lat,

src/app/locations/page.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import JsonLd from '@/components/JsonLd';
44
import { generateBreadcrumbSchema } from '@/lib/schemas/breadcrumb';
55
import { COLORADO_LOCATIONS } from '@/lib/data/locations';
66
import { getCoverageLabel, getCoverageBadgeColor, getCoverageColor } from '@/lib/utils/coverage';
7+
import { BASE_URL } from '@/lib/constants';
78

89
export const metadata: Metadata = {
910
title: 'Colorado Mesh Network Coverage | Front Range Cities',
@@ -30,7 +31,7 @@ export const metadata: Metadata = {
3031
title: 'Colorado Mesh Network Coverage | Denver MeshCore',
3132
description:
3233
'Explore MeshCore coverage across the Colorado Front Range. Find nodes in Denver, Boulder, Colorado Springs, and more.',
33-
url: 'https://denvermc.com/locations',
34+
url: `${BASE_URL}/locations`,
3435
type: 'website',
3536
},
3637
twitter: {
@@ -42,8 +43,8 @@ export const metadata: Metadata = {
4243
};
4344

4445
const breadcrumbData = generateBreadcrumbSchema([
45-
{ name: 'Home', url: 'https://denvermc.com' },
46-
{ name: 'Locations', url: 'https://denvermc.com/locations' },
46+
{ name: 'Home', url: BASE_URL },
47+
{ name: 'Locations', url: `${BASE_URL}/locations` },
4748
]);
4849

4950
const pageSchema = {
@@ -52,19 +53,19 @@ const pageSchema = {
5253
name: 'Colorado Mesh Network Coverage',
5354
description:
5455
'Explore Colorado mesh network coverage across the Front Range. Find MeshCore nodes in Denver, Boulder, Colorado Springs, and other Front Range cities.',
55-
url: 'https://denvermc.com/locations',
56+
url: `${BASE_URL}/locations`,
5657
publisher: {
5758
'@type': 'Organization',
5859
name: 'Denver MeshCore',
59-
url: 'https://denvermc.com',
60+
url: BASE_URL,
6061
},
6162
mainEntity: {
6263
'@type': 'ItemList',
6364
itemListElement: COLORADO_LOCATIONS.map((location, index) => ({
6465
'@type': 'ListItem',
6566
position: index + 1,
6667
name: `${location.name} Mesh Network`,
67-
url: `https://denvermc.com/locations/${location.slug}`,
68+
url: `${BASE_URL}/locations/${location.slug}`,
6869
})),
6970
},
7071
};

src/app/map/page.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Link from 'next/link';
33
import { NetworkMapWrapper } from '@/components';
44
import JsonLd from '@/components/JsonLd';
55
import { generateBreadcrumbSchema } from '@/lib/schemas/breadcrumb';
6+
import { BASE_URL } from '@/lib/constants';
67

78
// Force dynamic rendering to prevent stale cache issues on Netlify
89
export const dynamic = 'force-dynamic';
@@ -30,13 +31,13 @@ export const metadata: Metadata = {
3031
title: 'Network Map | Denver MeshCore',
3132
description:
3233
'Interactive map of Denver MeshCore network nodes. View node locations and coverage areas across Colorado.',
33-
url: 'https://denvermc.com/map',
34+
url: `${BASE_URL}/map`,
3435
},
3536
};
3637

3738
const breadcrumbData = generateBreadcrumbSchema([
38-
{ name: 'Home', url: 'https://denvermc.com' },
39-
{ name: 'Network Map', url: 'https://denvermc.com/map' },
39+
{ name: 'Home', url: BASE_URL },
40+
{ name: 'Network Map', url: `${BASE_URL}/map` },
4041
]);
4142

4243
export default function MapPage() {

src/app/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import Link from 'next/link';
22
import { StatsSection } from '@/components';
33
import JsonLd from '@/components/JsonLd';
44
import { generateBreadcrumbSchema } from '@/lib/schemas/breadcrumb';
5+
import { BASE_URL } from '@/lib/constants';
56

67
const breadcrumbData = generateBreadcrumbSchema([
7-
{ name: 'Home', url: 'https://denvermc.com' },
8+
{ name: 'Home', url: BASE_URL },
89
]);
910

1011
export default function Home() {

src/lib/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// Site Information
77
// =============================================================================
88

9+
export const BASE_URL = 'https://denvermc.com';
910
export const SITE_NAME = 'Denver MeshCore';
1011
export const SITE_TAGLINE = 'Colorado\'s decentralized mesh network community';
1112
export const SITE_DESCRIPTION = 'Join Colorado\'s growing mesh network community. Connect with fellow mesh enthusiasts, share knowledge, and help build resilient off-grid communication infrastructure.';

src/lib/schemas/blog.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { BlogPostFrontmatter } from '../blog';
2+
import { BASE_URL } from '../constants';
23

34
interface BlogPostingSchemaOptions {
45
slug: string;
@@ -17,7 +18,7 @@ export function generateBlogPostingSchema({
1718
frontmatter,
1819
readingTime,
1920
wordCount,
20-
baseUrl = 'https://denvermc.org',
21+
baseUrl = BASE_URL,
2122
}: BlogPostingSchemaOptions) {
2223
const postUrl = `${baseUrl}/blog/${slug}`;
2324

@@ -73,7 +74,7 @@ export function generateBlogPostingSchema({
7374
* Generate JSON-LD Blog schema for the blog listing page
7475
* @see https://schema.org/Blog
7576
*/
76-
export function generateBlogSchema(baseUrl = 'https://denvermc.org') {
77+
export function generateBlogSchema(baseUrl = BASE_URL) {
7778
return {
7879
'@context': 'https://schema.org',
7980
'@type': 'Blog',
@@ -99,7 +100,7 @@ export function generateArticleSchema({
99100
frontmatter,
100101
readingTime,
101102
wordCount,
102-
baseUrl = 'https://denvermc.org',
103+
baseUrl = BASE_URL,
103104
}: BlogPostingSchemaOptions) {
104105
const schema = generateBlogPostingSchema({
105106
slug,

0 commit comments

Comments
 (0)