Skip to content

Commit 134d0d4

Browse files
committed
Update web content
1 parent ee51d7a commit 134d0d4

14 files changed

Lines changed: 354 additions & 21 deletions

web/app/docs/[slug]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { notFound } from "next/navigation";
22
import Link from "next/link";
33
import { getDocPage, getAllDocPages } from "@/lib/content/loader";
44
import MarkdownContent from "@/components/MarkdownContent";
5+
import GettingStartedGuides from "@/components/GettingStartedGuides";
56
import type { Metadata } from "next";
67

78
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://ai-devkit.com";
@@ -102,6 +103,7 @@ export default async function DocPage({ params }: DocPageProps) {
102103
)}
103104

104105
<MarkdownContent content={doc.content} />
106+
<GettingStartedGuides />
105107
</article>
106108
<nav className="mt-16 pt-8 border-t border-gray-200 mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
107109
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">

web/app/docs/page.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Link from 'next/link';
22
import { getAllDocPages } from '@/lib/content/loader';
3+
import GettingStartedGuides from '@/components/GettingStartedGuides';
34
import type { Metadata } from 'next';
45

56
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://ai-devkit.com';
@@ -79,6 +80,8 @@ export default function DocsPage() {
7980
</div>
8081
)}
8182

83+
<GettingStartedGuides />
84+
8285
<div className="mt-12 pt-12 border-t border-gray-200">
8386
<h2 className="text-2xl font-bold mb-4">Need Help?</h2>
8487
<p className="text-gray-600 mb-4">
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { notFound } from "next/navigation";
22
import type { Metadata } from "next";
33
import MarkdownContent from "@/components/MarkdownContent";
4+
import FaqKeywordLinks from "@/components/FaqKeywordLinks";
45
import { getDocPage } from "@/lib/content/loader";
56
import {
67
findSeoKeywordBySlug,
@@ -50,13 +51,13 @@ export async function generateMetadata({
5051
if (!entry) {
5152
return {
5253
title: "Page Not Found",
53-
description: "The requested SEO page could not be found.",
54+
description: "The requested FAQ page could not be found.",
5455
};
5556
}
5657

5758
const title = `${entry.keyword} | AI DevKit`;
5859
const description = buildDescription(entry.keyword);
59-
const pageUrl = `${siteUrl}/s/${entry.slug}`;
60+
const pageUrl = `${siteUrl}/faq/${entry.slug}`;
6061

6162
return {
6263
title,
@@ -102,7 +103,7 @@ export default async function SeoKeywordPage({ params }: SeoPageProps) {
102103
"AI DevKit provides structured workflows, reusable commands, and memory to improve AI-assisted development.";
103104

104105
const content = buildSeoContent(entry.keyword, baseContent);
105-
const pageUrl = `${siteUrl}/s/${entry.slug}`;
106+
const pageUrl = `${siteUrl}/faq/${entry.slug}`;
106107
const structuredData = {
107108
"@context": "https://schema.org",
108109
"@type": "Article",
@@ -134,6 +135,7 @@ export default async function SeoKeywordPage({ params }: SeoPageProps) {
134135
{buildDescription(entry.keyword)}
135136
</p>
136137
<MarkdownContent content={content} />
138+
<FaqKeywordLinks />
137139
</article>
138140
</div>
139141
);
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { notFound } from "next/navigation";
2+
import type { Metadata } from "next";
3+
import MarkdownContent from "@/components/MarkdownContent";
4+
import { getDocPage } from "@/lib/content/loader";
5+
import {
6+
findSetupToolBySlug,
7+
setupToolEntries,
8+
} from "@/lib/seo/setup-tools";
9+
10+
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://ai-devkit.com";
11+
const baseDocSlug = "1-getting-started";
12+
13+
interface SetupPageProps {
14+
params: Promise<{ tool: string }>;
15+
}
16+
17+
function buildTitle(tool: string): string {
18+
return `Setting up AI DevKit for ${tool}`;
19+
}
20+
21+
function buildDescription(tool: string): string {
22+
return `Set up AI DevKit for ${tool} with structured workflows, commands, and memory to keep AI-assisted development consistent.`;
23+
}
24+
25+
function buildSeoContent(tool: string, baseContent: string): string {
26+
const intro = [
27+
"",
28+
`Learn how to set up AI DevKit for **${tool}** so your team can rely on consistent AI-assisted workflows.`,
29+
"",
30+
`AI DevKit adds structured phases, reusable commands, and memory to ${tool} so every project follows the same playbook.`,
31+
"",
32+
"## What you'll configure",
33+
"",
34+
"- Project initialization and environment selection",
35+
"- AI editor files like rules, agents, and commands",
36+
"- Memory and skills for repeatable workflows",
37+
"",
38+
].join("\n");
39+
40+
const outro = [
41+
"",
42+
"## Next steps",
43+
"",
44+
`Once AI DevKit is set up in ${tool}, follow the getting started guide and run your first workflow command.`,
45+
].join("\n");
46+
47+
return `${intro}${baseContent}${outro}`;
48+
}
49+
50+
export async function generateStaticParams() {
51+
return setupToolEntries.map((entry) => ({
52+
tool: entry.slug,
53+
}));
54+
}
55+
56+
export async function generateMetadata({
57+
params,
58+
}: SetupPageProps): Promise<Metadata> {
59+
const { tool: slug } = await params;
60+
const entry = findSetupToolBySlug(slug);
61+
62+
if (!entry) {
63+
return {
64+
title: "Page Not Found",
65+
description: "The requested setup page could not be found.",
66+
};
67+
}
68+
69+
const title = buildTitle(entry.tool);
70+
const description = buildDescription(entry.tool);
71+
const pageUrl = `${siteUrl}/faq/getting-started/${entry.slug}`;
72+
73+
return {
74+
title,
75+
description,
76+
keywords: [
77+
title,
78+
entry.tool,
79+
"AI DevKit",
80+
"AI coding assistant",
81+
"setup guide",
82+
"structured workflows",
83+
"commands",
84+
"memory",
85+
],
86+
openGraph: {
87+
title,
88+
description,
89+
url: pageUrl,
90+
siteName: "AI DevKit",
91+
locale: "en_US",
92+
type: "article",
93+
},
94+
twitter: {
95+
card: "summary_large_image",
96+
title,
97+
description,
98+
},
99+
alternates: {
100+
canonical: pageUrl,
101+
},
102+
};
103+
}
104+
105+
export default async function SetupToolPage({ params }: SetupPageProps) {
106+
const { tool: slug } = await params;
107+
const entry = findSetupToolBySlug(slug);
108+
109+
if (!entry) {
110+
notFound();
111+
}
112+
113+
const baseDoc = getDocPage(baseDocSlug);
114+
const baseContent =
115+
baseDoc?.content ||
116+
"AI DevKit provides structured workflows, reusable commands, and memory to improve AI-assisted development.";
117+
118+
const content = buildSeoContent(entry.tool, baseContent);
119+
const pageUrl = `${siteUrl}/faq/getting-started/${entry.slug}`;
120+
const structuredData = {
121+
"@context": "https://schema.org",
122+
"@type": "Article",
123+
headline: buildTitle(entry.tool),
124+
description: buildDescription(entry.tool),
125+
url: pageUrl,
126+
author: {
127+
"@type": "Organization",
128+
name: "AI DevKit",
129+
},
130+
publisher: {
131+
"@type": "Organization",
132+
name: "AI DevKit",
133+
url: siteUrl,
134+
},
135+
};
136+
137+
return (
138+
<div className="bg-white py-16">
139+
<article className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
140+
<script
141+
type="application/ld+json"
142+
dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
143+
/>
144+
<h1 className="text-4xl md:text-5xl font-bold mb-4">
145+
{buildTitle(entry.tool)}
146+
</h1>
147+
<p className="text-xl text-gray-600 mb-12">
148+
{buildDescription(entry.tool)}
149+
</p>
150+
<MarkdownContent content={content} />
151+
</article>
152+
</div>
153+
);
154+
}

web/app/faq/page.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import type { Metadata } from "next";
2+
import Link from "next/link";
3+
import { seoKeywordEntries } from "@/lib/seo/keywords";
4+
5+
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://ai-devkit.com";
6+
7+
export const metadata: Metadata = {
8+
title: "FAQ | AI DevKit",
9+
description:
10+
"Browse AI DevKit FAQ topics covering AI coding assistants, workflows, and development best practices.",
11+
keywords: [
12+
"AI DevKit FAQ",
13+
"AI coding assistant",
14+
"AI development tools",
15+
"structured workflows",
16+
"commands",
17+
"memory",
18+
],
19+
openGraph: {
20+
title: "AI DevKit FAQ",
21+
description:
22+
"Browse AI DevKit FAQ topics covering AI coding assistants, workflows, and development best practices.",
23+
url: `${siteUrl}/faq`,
24+
siteName: "AI DevKit",
25+
locale: "en_US",
26+
type: "website",
27+
},
28+
twitter: {
29+
card: "summary_large_image",
30+
title: "AI DevKit FAQ",
31+
description:
32+
"Browse AI DevKit FAQ topics covering AI coding assistants, workflows, and development best practices.",
33+
},
34+
alternates: {
35+
canonical: `${siteUrl}/faq`,
36+
},
37+
};
38+
39+
export default function FaqIndexPage() {
40+
return (
41+
<div className="bg-white py-16">
42+
<div className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
43+
<h1 className="text-4xl font-bold mb-4">FAQ</h1>
44+
<p className="text-xl text-gray-600 mb-12">
45+
Explore AI DevKit topics focused on AI coding assistants, workflows,
46+
and tools.
47+
</p>
48+
49+
<div className="space-y-4">
50+
{seoKeywordEntries.map((entry) => (
51+
<Link
52+
key={entry.slug}
53+
href={`/faq/${entry.slug}`}
54+
className="block rounded-lg border border-gray-200 px-6 py-4 text-lg font-semibold transition-colors hover:border-black no-underline"
55+
>
56+
{entry.keyword}
57+
</Link>
58+
))}
59+
</div>
60+
</div>
61+
</div>
62+
);
63+
}

web/app/sitemap.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { MetadataRoute } from 'next';
22
import { getAllDocPages } from '@/lib/content/loader';
33
import { seoKeywordEntries } from '@/lib/seo/keywords';
4+
import { setupToolEntries } from '@/lib/seo/setup-tools';
45

56
export const dynamic = 'force-static';
67

@@ -14,6 +15,12 @@ export default function sitemap(): MetadataRoute.Sitemap {
1415
changeFrequency: 'weekly' as const,
1516
priority: 1.0,
1617
},
18+
{
19+
url: `${baseUrl}/faq`,
20+
lastModified: new Date(),
21+
changeFrequency: 'weekly' as const,
22+
priority: 0.8,
23+
},
1724
{
1825
url: `${baseUrl}/docs`,
1926
lastModified: new Date(),
@@ -43,12 +50,19 @@ export default function sitemap(): MetadataRoute.Sitemap {
4350
}));
4451

4552
const seoRoutes = seoKeywordEntries.map((entry) => ({
46-
url: `${baseUrl}/s/${entry.slug}`,
53+
url: `${baseUrl}/faq/${entry.slug}`,
54+
lastModified: new Date(),
55+
changeFrequency: 'weekly' as const,
56+
priority: 0.6,
57+
}));
58+
59+
const setupRoutes = setupToolEntries.map((entry) => ({
60+
url: `${baseUrl}/faq/getting-started/${entry.slug}`,
4761
lastModified: new Date(),
4862
changeFrequency: 'weekly' as const,
4963
priority: 0.6,
5064
}));
5165

52-
return [...staticRoutes, ...docRoutes, ...seoRoutes];
66+
return [...staticRoutes, ...docRoutes, ...seoRoutes, ...setupRoutes];
5367
}
5468

web/components/FaqKeywordLinks.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Link from "next/link";
2+
import { seoKeywordEntries } from "@/lib/seo/keywords";
3+
4+
export default function FaqKeywordLinks() {
5+
return (
6+
<section className="mt-12 border-t border-gray-200 pt-8">
7+
<h2 className="text-2xl font-bold mb-4">More FAQ Topics</h2>
8+
<p className="text-gray-600 mb-6">
9+
Explore related AI DevKit questions and topics.
10+
</p>
11+
<ul className="list-disc pl-5 space-y-2">
12+
{seoKeywordEntries.map((entry) => (
13+
<li key={entry.slug}>
14+
<Link
15+
href={`/faq/${entry.slug}`}
16+
className="hover:opacity-70 transition-opacity"
17+
>
18+
{entry.keyword}
19+
</Link>
20+
</li>
21+
))}
22+
</ul>
23+
</section>
24+
);
25+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Link from "next/link";
2+
import { setupToolEntries } from "@/lib/seo/setup-tools";
3+
4+
export default function GettingStartedGuides() {
5+
return (
6+
<section className="mt-12 border-t border-gray-200 pt-8">
7+
<h2 className="text-2xl font-bold mb-4">
8+
Getting Started Guides by Tool
9+
</h2>
10+
<p className="text-gray-600 mb-6">
11+
Choose your AI tool for a tailored setup guide.
12+
</p>
13+
<ul className="list-disc pl-5 space-y-2">
14+
{setupToolEntries.map((entry) => (
15+
<li key={entry.slug}>
16+
<Link
17+
href={`/faq/getting-started/${entry.slug}`}
18+
className="hover:opacity-70 transition-opacity"
19+
>
20+
{`Setting up AI DevKit for ${entry.tool}`}
21+
</Link>
22+
</li>
23+
))}
24+
</ul>
25+
</section>
26+
);
27+
}

0 commit comments

Comments
 (0)