Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
3930ada
fix(adsense): make editorial pages content-first
SamoTech Oct 6, 2026
01475b4
fix(adsense): make homepage editorial-first
SamoTech Oct 6, 2026
d66ae39
docs(adsense): add approval readiness gate
SamoTech Oct 6, 2026
696039a
docs(adsense): add content-value operating gate
SamoTech Oct 6, 2026
8d343a1
docs(adsense): record low-value remediation state
SamoTech Oct 6, 2026
9de933b
content(adsense): remove unsupported editorial claims
SamoTech Oct 6, 2026
fe70dbd
docs(content): remove unsupported personal-testing claim
SamoTech Oct 6, 2026
9a3adad
content(adsense): quarantine thin legacy guides
SamoTech Oct 6, 2026
17cc019
fix(seo): exclude quarantined guides from sitemap
SamoTech Oct 6, 2026
13867f9
fix(seo): noindex quarantined editorial guides
SamoTech Oct 6, 2026
9a1b230
docs(adsense): record editorial inventory audit
SamoTech Oct 6, 2026
19143f2
fix(adsense): noindex thin product commerce pages
SamoTech Oct 6, 2026
1c64c05
fix(adsense): noindex dynamic marketplace category pages
SamoTech Oct 6, 2026
a057a5d
fix(seo): keep commerce routes out of editorial sitemap
SamoTech Oct 6, 2026
e280473
docs(content): align writer with editorial quality gate
SamoTech Oct 6, 2026
4eec85e
docs(adsense): record commerce indexation remediation
SamoTech Oct 6, 2026
e0c6b79
fix(adsense): gate repetitive editorial corpus from indexing
SamoTech Oct 6, 2026
0f25ebf
docs(adsense): reconcile full editorial corpus
SamoTech Oct 6, 2026
8298644
fix(adsense): quarantine legacy templated guides
SamoTech Oct 6, 2026
fd0a4c3
docs(adsense): narrow indexable editorial corpus
SamoTech Oct 6, 2026
232b558
fix(adsense): quarantine short marketplace guide cohort
SamoTech Oct 6, 2026
77b69bd
fix(adsense): reserve indexing for cornerstone content
SamoTech Oct 6, 2026
5f81cd6
fix(adsense): quarantine off-topic AI marketplace article
SamoTech Oct 6, 2026
59ac6c3
fix(adsense): quarantine short legacy articles
SamoTech Oct 6, 2026
d552adf
content: add cornerstone buyer-guide analysis
SamoTech Oct 6, 2026
976eaa0
content: promote selected cornerstone guides
SamoTech Oct 6, 2026
f431e37
docs(adsense): record controlled indexable cohort
SamoTech Oct 6, 2026
4d4ce2f
docs(status): record controlled AdSense remediation state
SamoTech Oct 6, 2026
96663bd
content(adsense): quarantine counterfeit checklist and remove unsuppo…
SamoTech Oct 6, 2026
6bc7842
fix(adsense): expose only quality-gated editorial guides
SamoTech Oct 6, 2026
d98dd5e
fix(adsense): keep related article links inside indexable corpus
SamoTech Oct 6, 2026
ee272f1
fix(adsense): remove category ad placement and clarify directory purpose
SamoTech Oct 6, 2026
d5550e3
fix(adsense): remove ads from research tools
SamoTech Oct 6, 2026
7f25415
fix(adsense): remove ads from research tools
SamoTech Oct 6, 2026
7c5c17b
fix(adsense): remove nonstandard ai-content metadata
SamoTech Oct 6, 2026
0d0d53f
fix(adsense): remove placeholder social links and add real contact path
SamoTech Oct 6, 2026
1ce3110
fix(adsense): replace unsupported about-page claims with editorial di…
SamoTech Oct 6, 2026
da4e1e3
fix(adsense): rewrite FAQ with current factual site behavior
SamoTech Oct 6, 2026
6bf1574
fix(adsense): noindex direct sponsorship sales page
SamoTech Oct 6, 2026
b80a362
fix(adsense): exclude commercial sponsorship page from sitemap
SamoTech Oct 6, 2026
356005d
fix(adsense): repair footer structure after social-link cleanup
SamoTech Oct 6, 2026
16dcad4
fix(adsense): keep blog category discovery limited to indexable guides
SamoTech Oct 6, 2026
e642d20
content: correct cornerstone guide reading-time estimates
SamoTech Oct 6, 2026
eff6fc4
refactor(adsense): isolate favorites client view
SamoTech Oct 6, 2026
75d546d
refactor(adsense): isolate compare client view
SamoTech Oct 6, 2026
6382fc6
fix(adsense): noindex personalized favorites utility
SamoTech Oct 6, 2026
8b09b0b
fix(adsense): noindex personalized compare utility
SamoTech Oct 6, 2026
b3b66b2
test(adsense): enforce editorial corpus and commercial restraint
SamoTech Oct 6, 2026
18a04c9
fix(adsense): remove homepage commercial slots and feature editorial …
SamoTech Oct 6, 2026
981850d
test(adsense): include homepage in commercial restraint gate
SamoTech Oct 6, 2026
b28dc10
fix(adsense): reduce homepage commercial density and remove affiliate…
SamoTech Oct 6, 2026
09339b0
fix(adsense): remove redundant high-value marketplace feed
SamoTech Oct 6, 2026
cf22e8c
fix(adsense): remove commercial product links from editorial article …
SamoTech Oct 6, 2026
395f3e8
fix(adsense): remove unsupported contact claims and placeholder socia…
SamoTech Oct 6, 2026
460d2df
fix(adsense): replace contact placeholders with functional factual page
SamoTech Oct 6, 2026
359d09d
fix(adsense): quarantine legacy corpus and remove slug collisions
SamoTech Oct 6, 2026
9c612af
fix(adsense): remove redundant high-value marketplace feed completely
SamoTech Oct 6, 2026
eecf446
fix(adsense): remove redundant high-value merchandising section
SamoTech Oct 6, 2026
f0a1754
fix(adsense): remove direct sponsorship promotion from global navigation
SamoTech Oct 6, 2026
d4567da
test(adsense): align footer assertions with transparent navigation
SamoTech Oct 6, 2026
44cd6ef
fix(adsense): remove legacy expanded slug collisions
SamoTech Oct 6, 2026
493a927
fix(adsense): finalize unique legacy article slugs
SamoTech Oct 6, 2026
35470de
fix: close related-posts JSX comment
SamoTech Oct 6, 2026
28c26f9
content(adsense): promote differentiated cornerstone cohort 31-40
SamoTech Oct 6, 2026
ed40cd4
content: correct promoted guide reading-time estimates
SamoTech Oct 6, 2026
0016798
test(adsense): enforce eleven-guide editorial corpus
SamoTech Oct 6, 2026
7b78e47
fix(adsense): noindex category directory surface
SamoTech Oct 6, 2026
a6615fb
fix(adsense): exclude noindex category directory from sitemap
SamoTech Oct 6, 2026
2fe3c05
content(adsense): remove unsupported Black Friday category timing claim
SamoTech Oct 6, 2026
57d9d6c
content(adsense): deepen promoted guides with category-specific analysis
SamoTech Oct 6, 2026
e8ada0c
fix: close cornerstone supplements object entries
SamoTech Oct 6, 2026
dccb33f
fix(seo): remove ai-content metadata from global SEO config
SamoTech Oct 6, 2026
66b88b9
fix(seo): rely on metadata title template for compare page
SamoTech Oct 6, 2026
9309fd3
fix(seo): rely on metadata title template for favorites page
SamoTech Oct 6, 2026
343653a
fix(seo): prevent duplicated categories title
SamoTech Oct 6, 2026
689187c
fix(seo): remove duplicated title suffix from app/terms/page.tsx
SamoTech Oct 6, 2026
cb93d94
fix(seo): remove duplicated title suffix from app/privacy/page.tsx
SamoTech Oct 6, 2026
62182bc
fix(seo): remove duplicated title suffix from app/cookies/page.tsx
SamoTech Oct 6, 2026
8364394
fix(seo): remove duplicated title suffix from app/disclaimer/page.tsx
SamoTech Oct 6, 2026
fcfea4f
fix(seo): remove duplicated title suffix from app/compare/layout.tsx
SamoTech Oct 6, 2026
7a74785
fix(seo): remove duplicated title suffix from app/favorites/layout.tsx
SamoTech Oct 6, 2026
03288b2
fix(seo): remove remaining ai-content metadata
SamoTech Oct 6, 2026
3916d33
fix(seo): include trust and disclosure pages in sitemap
SamoTech Oct 6, 2026
dea91df
docs(adsense): reconcile final remediation gate state
SamoTech Oct 6, 2026
d0176bd
docs(adsense): reconcile project status with verified remediation
SamoTech Oct 6, 2026
cfa2608
docs(adsense): record final corpus and verification reconciliation
SamoTech Oct 6, 2026
328fb6f
fix(seo): normalize app/contact/page.tsx title
SamoTech Oct 6, 2026
d114f56
fix(seo): normalize app/faq/page.tsx title
SamoTech Oct 6, 2026
4453050
fix(seo): normalize app/research/ebay-deal-comparison-methodology/pag…
SamoTech Oct 6, 2026
bafc8e0
fix(seo): normalize app/tools/deal-comparison/layout.tsx title
SamoTech Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ Do not fabricate personal experiences, tests, expert credentials, prices, produc

Affiliate disclosure must remain intact.

### AdSense content-value gate

When the repository is under an AdSense low-value-content remediation, treat publisher value as a first-class acceptance gate. Editorial content must be the focal user value, not a wrapper around eBay inventory or affiliate conversion. Do not solve a low-value decision by mass-producing generic articles. Audit originality, evidence, repetition, factual risk, and commercial intent before publishing or expanding content. Keep AdSense blocks and sponsorship surfaces out of editorial content when they materially compete with the content's focal purpose. See `docs/ADSENSE_APPROVAL_GATE.md`.

## SEO / AI visibility rules

SEO work must preserve:
Expand Down
45 changes: 45 additions & 0 deletions __tests__/adsense/editorial-gate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import fs from 'node:fs';
import path from 'node:path';
import { blogArticles } from '../../lib/blog-data';

describe('AdSense editorial gate', () => {
it('keeps the public editorial corpus intentionally small and explicit', () => {
expect(blogArticles.filter((article) => article.indexable !== false).map((article) => article.id))
.toEqual([31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 61]);
});

it('keeps the indexable corpus above the minimum content threshold', () => {
expect(blogArticles.filter((article) => article.indexable !== false).length).toBe(11);
});

it('does not expose duplicate article slugs', () => {
const slugs = blogArticles.map((article) => article.slug);
expect(new Set(slugs).size).toBe(slugs.length);
});

it('keeps selected guides free of fabricated first-person testing claims', () => {
const selected = blogArticles.filter((article) => article.indexable !== false);
const articleText = selected
.flatMap((article) => article.content)
.map((block) => [block.text ?? '', ...(block.items ?? [])].join(' '))
.join(' ');

expect(articleText).not.toMatch(/\b(I\s+(?:tested|personally|owned|used)|my\s+(?:testing|experience)|we\s+(?:tested|personally))\b/i);
});

it('keeps commercial ad/sponsorship components out of editorial and research pages', () => {
const routes = [
'app/page.tsx',
'app/blog/[slug]/page.tsx',
'app/blog/page.tsx',
'app/categories/page.tsx',
'app/tools/deal-comparison/page.tsx',
'app/research/ebay-deal-comparison-methodology/page.tsx',
];

for (const route of routes) {
const source = fs.readFileSync(path.join(process.cwd(), route), 'utf8');
expect(source).not.toMatch(/AdSenseBlock|SponsorSlot/);
}
});
});
6 changes: 4 additions & 2 deletions __tests__/components/Footer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { render, screen } from '@testing-library/react';
import Footer from '@/components/Footer';

describe('Footer', () => {
it('renders accessible footer content without a custom visitor counter', () => {
it('renders accessible footer content without advertising or placeholder social links', () => {
render(<Footer />);

expect(screen.getByRole('contentinfo')).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Facebook' })).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Contact page' })).toBeInTheDocument();
expect(screen.queryByRole('link', { name: 'Advertise' })).not.toBeInTheDocument();
expect(screen.queryAllByRole('link', { name: /Facebook|Twitter|Instagram/i })).toHaveLength(0);
expect(screen.queryByText(/Site visits:/i)).not.toBeInTheDocument();
});
});
289 changes: 86 additions & 203 deletions app/about/page.tsx

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/advertise/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { sponsorPackages } from '@/config/sponsor-packages';
import { SPONSORSHIP_CONTACT } from '@/config/sponsorship';

export const metadata: Metadata = {
robots: { index: false, follow: true },
title: 'Advertise on Saleh Store',
description:
'Direct sponsorship opportunities on Saleh Store for brands, stores, and relevant services.',
Expand Down
85 changes: 2 additions & 83 deletions app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ import { Metadata } from 'next';
import Link from 'next/link';
import { notFound } from 'next/navigation';
import { blogArticles, BlogArticle } from '../../../lib/blog-data';
import { allProducts, categories } from '../../../lib/products';
import SocialShare from '../../../components/SocialShare';
import Footer from '../../../components/Footer';
import { absoluteUrl } from '../../../lib/site';
import { generateArticleSchema, generateBreadcrumbSchema, SchemaScript } from '../../../lib/schema';
import AdSenseBlock from '../../../components/AdSenseBlock';
import { getRelatedBlogPosts } from '../../../lib/related-blog-posts';
import SponsorSlot from '../../../components/SponsorSlot';

interface BlogPostPageProps {
params: Promise<{
Expand Down Expand Up @@ -59,6 +56,7 @@ export async function generateMetadata({ params }: BlogPostPageProps): Promise<M
alternates: {
canonical: absoluteUrl(`/blog/${post.slug}`),
},
...(post.indexable === false ? { robots: { index: false, follow: true } } : {}),
};
}

Expand All @@ -82,32 +80,6 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
});
const allRelatedPosts = getRelatedBlogPosts(post, blogArticles, 3);

const blogCategoryMap: Record<string, string> = {
Electronics: 'electronics',
Gaming: 'gaming',
'Smart Home': 'smart-home',
Auto: 'auto',
Office: 'office',
Home: 'home',
Collectibles: 'collectibles',
'Cameras & Photo': 'cameras-photo',
Computers: 'computers-tablets-networking',
};
const categorySlug = blogCategoryMap[post.category];
const linkedCategory = categorySlug
? categories.find((category) => category.slug === categorySlug)
: undefined;
const resourceCategories = (post.relatedCategorySlugs ?? (categorySlug ? [categorySlug] : []))
.map((slug) => categories.find((category) => category.slug === slug))
.filter((category): category is (typeof categories)[number] => Boolean(category));
const linkedProducts = resourceCategories.length > 0
? allProducts
.filter((product) => resourceCategories.some((category) => product.category.toLowerCase() === category.name.toLowerCase()))
.slice(0, 6)
: linkedCategory
? allProducts.filter((product) => product.category.toLowerCase() === linkedCategory.name.toLowerCase()).slice(0, 4)
: [];

const breadcrumbSchema = generateBreadcrumbSchema([
{ name: 'Home', url: absoluteUrl('/') },
{ name: 'Blog', url: absoluteUrl('/blog') },
Expand Down Expand Up @@ -211,8 +183,6 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
</p>
</div>

<AdSenseBlock placement="article-before-main-content" className="px-0 py-4" />

{/* Main Content */}
<div
className="prose prose-lg dark:prose-invert max-w-none
Expand All @@ -229,8 +199,6 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
dangerouslySetInnerHTML={{ __html: contentHtml }}
/>

<SponsorSlot slot="article-middle" className="px-0 py-4" />

{/* Internal Linking */}
<section className="mt-12 p-6 rounded-2xl bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700" aria-labelledby="continue-reading">
<h2 id="continue-reading" className="text-2xl font-bold text-gray-900 dark:text-white mb-4">Continue Your Research</h2>
Expand All @@ -254,7 +222,7 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
{/* Social Share - Bottom */}
<div className="mt-12 pt-8 border-t border-gray-200 dark:border-gray-700">
<p className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-4">
Found this helpful? Share it with your network!
Share this guide
</p>
<SocialShare
url={postUrl}
Expand Down Expand Up @@ -283,57 +251,8 @@ export default async function BlogPostPage({ params }: BlogPostPageProps) {
</div>
</div>

<SponsorSlot slot="article-bottom" className="px-0 py-4" />
</article>

{/* Related Shopping Resources */}
{(linkedCategory || linkedProducts.length > 0) && (
<section className="max-w-4xl mx-auto px-4 pb-12" aria-labelledby="related-shopping-resources">
<div className="rounded-2xl bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 p-6">
<h2 id="related-shopping-resources" className="text-2xl font-bold text-gray-900 dark:text-white">
Related Shopping Resources
</h2>
<p className="mt-2 text-gray-600 dark:text-gray-400">
Continue researching the category and compare related products before buying.
</p>
{resourceCategories.length > 0 ? (
<div className="mt-5 flex flex-wrap gap-3">
{resourceCategories.map((category) => (
<Link
key={category.slug}
href={`/category/${category.slug}`}
className="inline-flex font-semibold text-blue-600 dark:text-blue-400 hover:underline"
>
Browse {category.name} →
</Link>
))}
</div>
) : linkedCategory ? (
<Link
href={`/category/${linkedCategory.slug}`}
className="mt-5 inline-flex font-semibold text-blue-600 dark:text-blue-400 hover:underline"
>
Browse {linkedCategory.name} →
</Link>
) : null}
{linkedProducts.length > 0 && (
<ul className="mt-5 grid sm:grid-cols-2 gap-3">
{linkedProducts.map((product) => (
<li key={product.id}>
<Link
href={`/product/${product.id}`}
className="font-semibold text-gray-900 dark:text-white hover:text-blue-600 dark:hover:text-blue-400"
>
{product.title}
</Link>
</li>
))}
</ul>
)}
</div>
</section>
)}

{/* Related Posts */}
{allRelatedPosts.length > 0 && (
<section className="max-w-4xl mx-auto px-4 py-12">
Expand Down
14 changes: 7 additions & 7 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const metadata: Metadata = {
},
};

const displayPosts = blogArticles;
const displayPosts = blogArticles.filter((post) => post.indexable !== false);

export default function BlogPage() {
const blogSchema = {
Expand All @@ -38,8 +38,8 @@ export default function BlogPage() {
'@type': 'ItemList',
'@id': absoluteUrl('/blog#articles'),
name: 'Saleh Store shopping guides',
numberOfItems: blogArticles.length,
itemListElement: blogArticles.map((article, index) => ({
numberOfItems: displayPosts.length,
itemListElement: displayPosts.map((article, index) => ({
'@type': 'ListItem',
position: index + 1,
url: absoluteUrl(`/blog/${article.slug}`),
Expand Down Expand Up @@ -122,8 +122,8 @@ export default function BlogPage() {
Browse by Category
</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{Array.from(new Set(blogArticles.map(article => article.category))).map((category) => {
const count = blogArticles.filter(article => article.category === category).length;
{Array.from(new Set(displayPosts.map(article => article.category))).map((category) => {
const count = displayPosts.filter(article => article.category === category).length;
return (
<div key={category} className="p-4 bg-blue-50 dark:bg-blue-900/20 rounded-xl">
<div className="text-2xl mb-2">📝</div>
Expand All @@ -140,10 +140,10 @@ export default function BlogPage() {
{/* Back to Shopping CTA */}
<div className="mt-12 text-center bg-gray-100 dark:bg-gray-800 rounded-2xl p-8">
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-4">
🎯 Ready to Start Shopping?
Continue From Research to Shopping
</h3>
<p className="text-gray-600 dark:text-gray-300 mb-6">
Browse curated products across 12 categories and compare current eBay listings, seller details, and purchase terms.
Use the guides above to narrow the product and configuration you need, then compare current eBay listings, seller details, condition, and purchase terms.
</p>
<Link
href="/"
Expand Down
12 changes: 6 additions & 6 deletions app/categories/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import type { Metadata } from 'next';
import Link from 'next/link';
import { categories } from '../../lib/products';
import { absoluteUrl } from '../../lib/site';
import AdSenseBlock from '../../components/AdSenseBlock';

export const metadata: Metadata = {
title: 'All Categories | Saleh Store',
title: 'All Categories',
description: 'Explore Saleh Store categories covering electronics, motors, fashion, home, collectibles, sports, business, travel and more across eBay.',
alternates: { canonical: absoluteUrl('/categories') },
robots: { index: false, follow: true },
};

export default function CategoriesPage() {
Expand All @@ -24,18 +24,18 @@ export default function CategoriesPage() {
</nav>
<h1 className="text-4xl md:text-5xl font-black tracking-tight">All Categories</h1>
<p className="mt-4 max-w-3xl text-lg text-blue-100">
Browse popular Saleh Store departments and broad eBay marketplace categories. Each category is a searchable landing page for products in that department.
Browse the current Saleh Store category directory. Category pages are product-discovery surfaces; our independent buying guides provide the research used to evaluate configuration, compatibility, condition, cost, and purchase terms.
</p>
</div>
</section>

<AdSenseBlock placement="categories-before-directory" />

<section className="max-w-6xl mx-auto px-4 py-10" aria-labelledby="category-directory-heading">
<div className="flex items-end justify-between gap-4 mb-6">
<div>
<h2 id="category-directory-heading" className="text-2xl font-black text-gray-900 dark:text-white">Marketplace directory</h2>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">{visibleCategories.length} category landing pages available.</p>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
{visibleCategories.length} searchable category destinations. Start with a guide when you need decision help, then use a category to inspect current listings.
</p>
</div>
<Link href="/" className="hidden sm:inline-flex text-sm font-bold text-[#0064d2] hover:underline">Back to home</Link>
</div>
Expand Down
7 changes: 3 additions & 4 deletions app/category/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import CategoryPageClient from '../../../components/CategoryPageClient';
import { allProducts, categories } from '../../../lib/products';
import { absoluteUrl } from '../../../lib/site';
import { generateBreadcrumbSchema, SchemaScript } from '../../../lib/schema';
import AdSenseBlock from '../../../components/AdSenseBlock';
import SponsorSlot from '../../../components/SponsorSlot';

const categoryFocus: Record<string, string> = {
electronics: 'Compare consumer electronics, devices, accessories, and related eBay listings with clear product details and current marketplace links.',
Expand Down Expand Up @@ -46,6 +44,9 @@ export async function generateMetadata({ params }: { params: Promise<{ slug: str
url: absoluteUrl(`/category/${slug}`),
},
alternates: { canonical: absoluteUrl(`/category/${slug}`) },
// Category pages are dynamic marketplace discovery surfaces; keep them usable while
// reserving search indexing for independent editorial and research content.
robots: { index: false, follow: true },
};
}

Expand Down Expand Up @@ -140,8 +141,6 @@ export default async function CategoryPage({ params }: { params: Promise<{ slug:
</section>
)}

<SponsorSlot slot="category-top" />
<AdSenseBlock placement="category-after-intro" />
<CategoryPageClient slug={slug} />
</>
);
Expand Down
Loading
Loading