@promptbook/cli 0.103.0-66 → 0.103.0-68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/apps/agents-server/TODO.txt +1 -5
  2. package/apps/agents-server/config.ts +3 -1
  3. package/apps/agents-server/package-lock.json +8 -2317
  4. package/apps/agents-server/package.json +0 -9
  5. package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +34 -2
  6. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +1 -1
  7. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +4 -0
  8. package/apps/agents-server/src/app/humans.txt/route.ts +15 -0
  9. package/apps/agents-server/src/app/layout.tsx +31 -0
  10. package/apps/agents-server/src/app/robots.txt/route.ts +15 -0
  11. package/apps/agents-server/src/app/security.txt/route.ts +15 -0
  12. package/apps/agents-server/src/app/sitemap.xml/route.ts +37 -0
  13. package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +28 -23
  14. package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +19 -18
  15. package/apps/agents-server/src/components/Footer/Footer.tsx +13 -13
  16. package/apps/agents-server/src/components/Header/Header.tsx +95 -20
  17. package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +3 -0
  18. package/apps/agents-server/src/components/_utils/generateMetaTxt.ts +28 -0
  19. package/apps/agents-server/src/components/_utils/headlessParam.tsx +36 -0
  20. package/apps/agents-server/src/middleware.ts +6 -2
  21. package/apps/agents-server/src/tools/$provideCdnForServer.ts +13 -1
  22. package/apps/agents-server/src/utils/cdn/classes/DigitalOceanSpaces.ts +119 -0
  23. package/apps/agents-server/src/utils/cdn/classes/VercelBlobStorage.ts +2 -1
  24. package/esm/index.es.js +191 -14
  25. package/esm/index.es.js.map +1 -1
  26. package/esm/typings/src/_packages/components.index.d.ts +2 -0
  27. package/esm/typings/src/_packages/types.index.d.ts +6 -0
  28. package/esm/typings/src/book-components/BookEditor/BookEditor.d.ts +10 -0
  29. package/esm/typings/src/book-components/BookEditor/BookEditorActionbar.d.ts +4 -0
  30. package/esm/typings/src/book-components/icons/CameraIcon.d.ts +11 -0
  31. package/esm/typings/src/execution/LlmExecutionTools.d.ts +5 -1
  32. package/esm/typings/src/execution/PromptResult.d.ts +7 -1
  33. package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +4 -0
  34. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +13 -1
  35. package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
  36. package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +6 -6
  37. package/esm/typings/src/types/ModelRequirements.d.ts +13 -1
  38. package/esm/typings/src/types/ModelVariant.d.ts +1 -1
  39. package/esm/typings/src/types/Prompt.d.ts +13 -1
  40. package/esm/typings/src/version.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/umd/index.umd.js +191 -14
  43. package/umd/index.umd.js.map +1 -1
@@ -8,14 +8,5 @@
8
8
  "start": "next start -p 4440",
9
9
  "lint": "next lint",
10
10
  "postinstall": "cd ../../ && npm ci"
11
- },
12
- "devDependencies": {
13
- "@tailwindcss/typography": "^0.5.19",
14
- "autoprefixer": "^10.4.21",
15
- "postcss": "^8.5.6",
16
- "tailwindcss": "^3.4.18"
17
- },
18
- "dependencies": {
19
- "remark-gfm": "^4.0.1"
20
11
  }
21
12
  }
@@ -32,6 +32,7 @@ const barlowCondensed = Barlow_Condensed({
32
32
 
33
33
  type AgentOptionsMenuProps = {
34
34
  agentName: string;
35
+ derivedAgentName: string;
35
36
  agentUrl: string;
36
37
  agentEmail: string;
37
38
  brandColorHex: string;
@@ -42,6 +43,7 @@ type AgentOptionsMenuProps = {
42
43
 
43
44
  export function AgentOptionsMenu({
44
45
  agentName,
46
+ derivedAgentName,
45
47
  agentUrl,
46
48
  agentEmail,
47
49
  brandColorHex,
@@ -119,7 +121,33 @@ export function AgentOptionsMenu({
119
121
  const historyLink = links.find((l) => l.title === 'History & Feedback')!;
120
122
  const allLinksLink = links.find((l) => l.title === 'All Links')!;
121
123
 
124
+ // "Update URL" logic
125
+ const showUpdateUrl = agentName !== derivedAgentName;
126
+ const updateUrlHref = `/agents/${encodeURIComponent(derivedAgentName)}`;
127
+
128
+ const handleUpdateUrl = () => {
129
+ if (
130
+ window.confirm(
131
+ `Are you sure you want to change the agent URL from "/agents/${agentName}" to "/agents/${derivedAgentName}"?`
132
+ )
133
+ ) {
134
+ window.location.href = updateUrlHref;
135
+ }
136
+ };
137
+
122
138
  const menuItems = [
139
+ ...(showUpdateUrl
140
+ ? [
141
+ {
142
+ type: 'action' as const,
143
+ icon: MoreHorizontalIcon,
144
+ label: 'Update URL',
145
+ onClick: handleUpdateUrl,
146
+ highlight: true,
147
+ },
148
+ { type: 'divider' as const },
149
+ ]
150
+ : []),
123
151
  {
124
152
  type: 'link' as const,
125
153
  href: `/agents/${encodeURIComponent(agentName)}/chat`,
@@ -268,9 +296,13 @@ export function AgentOptionsMenu({
268
296
  // Keep menu open for copy feedback
269
297
  }
270
298
  }}
271
- className="flex items-center gap-3 px-4 py-2.5 text-gray-700 hover:bg-gray-50 transition-colors w-full text-left"
299
+ className={`flex items-center gap-3 px-4 py-2.5 w-full text-left transition-colors
300
+ ${item.highlight
301
+ ? 'bg-yellow-100 text-yellow-900 font-bold hover:bg-yellow-200'
302
+ : 'text-gray-700 hover:bg-gray-50'}
303
+ `}
272
304
  >
273
- <item.icon className="w-4 h-4 text-gray-500" />
305
+ <item.icon className={`w-4 h-4 ${item.highlight ? 'text-yellow-700' : 'text-gray-500'}`} />
274
306
  <span className="text-sm font-medium">{item.label}</span>
275
307
  </button>
276
308
  );
@@ -57,7 +57,7 @@ export function AgentProfileChat({ agentUrl, agentName, fullname, brandColorHex,
57
57
  // The fallback above matches AgentChat.tsx default.
58
58
 
59
59
  return (
60
- <div className="w-full h-[400px] md:h-[500px]">
60
+ <div className="w-full h-[calc(100dvh-300px)] min-h-[350px] md:h-[500px]">
61
61
  <Chat
62
62
  title={`Chat with ${fullname}`}
63
63
  participants={[
@@ -19,6 +19,9 @@ type AgentProfileWrapperProps = {
19
19
  export function AgentProfileWrapper(props: AgentProfileWrapperProps) {
20
20
  const { agent, agentUrl, agentEmail, agentName, brandColorHex, isAdmin, isHeadless, actions, children } = props;
21
21
 
22
+ // Derived agentName from agent data
23
+ const derivedAgentName = agent.agentName;
24
+
22
25
  return (
23
26
  <AgentProfile
24
27
  agent={agent}
@@ -28,6 +31,7 @@ export function AgentProfileWrapper(props: AgentProfileWrapperProps) {
28
31
  renderMenu={({ onShowQrCode }) => (
29
32
  <AgentOptionsMenu
30
33
  agentName={agentName}
34
+ derivedAgentName={derivedAgentName}
31
35
  agentUrl={agentUrl}
32
36
  agentEmail={agentEmail}
33
37
  brandColorHex={brandColorHex}
@@ -0,0 +1,15 @@
1
+ // Dynamic humans.txt for Agents Server
2
+
3
+ import { generateHumansTxt } from '@/src/components/_utils/generateMetaTxt';
4
+ import { NextResponse } from 'next/server';
5
+
6
+ export const dynamic = 'force-dynamic';
7
+
8
+ export async function GET() {
9
+ const txt = generateHumansTxt();
10
+ return new NextResponse(txt, {
11
+ headers: {
12
+ 'Content-Type': 'text/plain',
13
+ },
14
+ });
15
+ }
@@ -7,6 +7,7 @@ import { $provideAgentCollectionForServer } from '../tools/$provideAgentCollecti
7
7
  import { $provideServer } from '../tools/$provideServer';
8
8
  import { getCurrentUser } from '../utils/getCurrentUser';
9
9
  import { isUserAdmin } from '../utils/isUserAdmin';
10
+ import { getFederatedServersFromMetadata } from '../utils/getFederatedServersFromMetadata';
10
11
  import './globals.css';
11
12
 
12
13
  const barlowCondensed = Barlow_Condensed({
@@ -82,6 +83,35 @@ export default async function RootLayout({
82
83
  console.error('Failed to parse FOOTER_LINKS', error);
83
84
  }
84
85
 
86
+ // Fetch federated servers and add to footerLinks
87
+ let federatedServers: Array<{ url: string; title: string; logoUrl: string | null }> = [];
88
+ try {
89
+ const federatedServersRaw = await getFederatedServersFromMetadata();
90
+ federatedServers = await Promise.all(
91
+ federatedServersRaw.map(async (url: string) => {
92
+ let logoUrl: string | null = null;
93
+ try {
94
+ // Try to fetch logo from metadata endpoint if available
95
+ const res = await fetch(`${url}/api/metadata`);
96
+ if (res.ok) {
97
+ const meta = await res.json();
98
+ logoUrl = meta.SERVER_LOGO_URL || null;
99
+ }
100
+ } catch {
101
+ logoUrl = null;
102
+ }
103
+ return {
104
+ title: `Federated: ${new URL(url).hostname}`,
105
+ url,
106
+ logoUrl,
107
+ };
108
+ })
109
+ );
110
+ footerLinks = [...footerLinks, ...federatedServers];
111
+ } catch (error) {
112
+ console.error('Failed to fetch federated servers for footer', error);
113
+ }
114
+
85
115
  const collection = await $provideAgentCollectionForServer();
86
116
  const agents = await collection.listAgents();
87
117
 
@@ -97,6 +127,7 @@ export default async function RootLayout({
97
127
  agents={JSON.parse(JSON.stringify(agents))}
98
128
  isFooterShown={isFooterShown}
99
129
  footerLinks={footerLinks}
130
+ federatedServers={federatedServers}
100
131
  >
101
132
  {children}
102
133
  </LayoutWrapper>
@@ -0,0 +1,15 @@
1
+ // Dynamic robots.txt for Agents Server
2
+
3
+ import { generateRobotsTxt } from '@/src/components/_utils/generateMetaTxt';
4
+ import { NextResponse } from 'next/server';
5
+
6
+ export const dynamic = 'force-dynamic';
7
+
8
+ export async function GET() {
9
+ const txt = generateRobotsTxt();
10
+ return new NextResponse(txt, {
11
+ headers: {
12
+ 'Content-Type': 'text/plain',
13
+ },
14
+ });
15
+ }
@@ -0,0 +1,15 @@
1
+ // Dynamic security.txt for Agents Server
2
+
3
+ import { generateSecurityTxt } from '@/src/components/_utils/generateMetaTxt';
4
+ import { NextResponse } from 'next/server';
5
+
6
+ export const dynamic = 'force-dynamic';
7
+
8
+ export async function GET() {
9
+ const txt = generateSecurityTxt();
10
+ return new NextResponse(txt, {
11
+ headers: {
12
+ 'Content-Type': 'text/plain',
13
+ },
14
+ });
15
+ }
@@ -0,0 +1,37 @@
1
+ // Dynamic sitemap.xml for Agents Server
2
+
3
+ import { NEXT_PUBLIC_SITE_URL } from '@/config';
4
+ import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
5
+ import { spaceTrim } from '@promptbook-local/utils';
6
+ import { NextResponse } from 'next/server';
7
+
8
+ export const dynamic = 'force-dynamic';
9
+
10
+ export async function GET() {
11
+ const collection = await $provideAgentCollectionForServer();
12
+
13
+ // Assume collection.listAgents() returns an array of agent names
14
+ const agentNames = await collection.listAgents();
15
+
16
+ // Get base URL from environment or config
17
+ const baseUrl = NEXT_PUBLIC_SITE_URL?.href || process.env.PUBLIC_URL || 'https://ptbk.io';
18
+
19
+ const urls = agentNames
20
+ .map(({ agentName }) => `<url><loc>${baseUrl}agents/${encodeURIComponent(agentName)}</loc></url>`)
21
+ .join('\n');
22
+
23
+ const xml = spaceTrim(
24
+ (block) => `
25
+ <?xml version="1.0" encoding="UTF-8"?>
26
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
27
+ ${block(urls)}
28
+ </urlset>
29
+ `,
30
+ );
31
+
32
+ return new NextResponse(xml, {
33
+ headers: {
34
+ 'Content-Type': 'application/xml',
35
+ },
36
+ });
37
+ }
@@ -208,11 +208,14 @@ export function AgentProfile(props: AgentProfileProps) {
208
208
  )}
209
209
 
210
210
  {/* Main profile content */}
211
- <div className="relative z-10 flex flex-col md:flex-row items-center md:items-start gap-8 md:gap-12 max-w-5xl w-full">
211
+ <div className="relative z-10 grid grid-cols-[auto_1fr] gap-x-6 gap-y-4 md:gap-12 max-w-5xl w-full items-start">
212
212
  {/* Agent image card (Flippable) */}
213
- <div className="flex-shrink-0 perspective-1000 group" style={{ perspective: '1000px' }}>
213
+ <div
214
+ className="flex-shrink-0 perspective-1000 group row-start-1 col-start-1 md:row-span-3"
215
+ style={{ perspective: '1000px' }}
216
+ >
214
217
  <div
215
- className="relative w-72 md:w-80 transition-all duration-700 transform-style-3d cursor-pointer"
218
+ className="relative w-24 md:w-80 transition-all duration-700 transform-style-3d cursor-pointer"
216
219
  style={{
217
220
  aspectRatio: '1 / 1.618', // Golden Ratio
218
221
  transformStyle: 'preserve-3d',
@@ -222,7 +225,7 @@ export function AgentProfile(props: AgentProfileProps) {
222
225
  >
223
226
  {/* Front of Card (Image) */}
224
227
  <div
225
- className="absolute inset-0 w-full h-full backface-hidden rounded-3xl shadow-2xl overflow-hidden backdrop-blur-sm"
228
+ className="absolute inset-0 w-full h-full backface-hidden rounded-lg md:rounded-3xl shadow-lg md:shadow-2xl overflow-hidden backdrop-blur-sm"
226
229
  style={{
227
230
  backfaceVisibility: 'hidden',
228
231
  backgroundColor: brandColorDarkHex,
@@ -234,7 +237,7 @@ export function AgentProfile(props: AgentProfileProps) {
234
237
  <img src={imageUrl} alt={fullname} className="w-full h-full object-cover" />
235
238
  ) : (
236
239
  <div
237
- className="w-full h-full flex items-center justify-center text-8xl font-bold text-white/80"
240
+ className="w-full h-full flex items-center justify-center text-3xl md:text-8xl font-bold text-white/80"
238
241
  style={{ backgroundColor: brandColorDarkHex }}
239
242
  >
240
243
  {fullname.charAt(0).toUpperCase()}
@@ -242,14 +245,14 @@ export function AgentProfile(props: AgentProfileProps) {
242
245
  )}
243
246
 
244
247
  {/* Flip hint icon */}
245
- <div className="absolute bottom-4 right-4 bg-black/30 p-2 rounded-full text-white/80 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity">
246
- <RepeatIcon className="w-5 h-5" />
248
+ <div className="absolute bottom-2 md:bottom-4 right-2 md:right-4 bg-black/30 p-1 md:p-2 rounded-full text-white/80 backdrop-blur-md opacity-0 group-hover:opacity-100 transition-opacity">
249
+ <RepeatIcon className="w-3 h-3 md:w-5 md:h-5" />
247
250
  </div>
248
251
  </div>
249
252
 
250
253
  {/* Back of Card (QR Code) */}
251
254
  <div
252
- className="absolute inset-0 w-full h-full backface-hidden rounded-3xl shadow-2xl overflow-hidden backdrop-blur-sm flex flex-col items-center justify-center p-6"
255
+ className="absolute inset-0 w-full h-full backface-hidden rounded-lg md:rounded-3xl shadow-lg md:shadow-2xl overflow-hidden backdrop-blur-sm flex flex-col items-center justify-center p-2 md:p-6"
253
256
  style={{
254
257
  backfaceVisibility: 'hidden',
255
258
  transform: 'rotateY(180deg)',
@@ -269,18 +272,18 @@ export function AgentProfile(props: AgentProfileProps) {
269
272
  </div>
270
273
 
271
274
  {/* Flip hint icon */}
272
- <div className="absolute bottom-4 right-4 bg-black/10 p-2 rounded-full text-black/50 backdrop-blur-md">
273
- <RepeatIcon className="w-5 h-5" />
275
+ <div className="absolute bottom-2 md:bottom-4 right-2 md:right-4 bg-black/10 p-1 md:p-2 rounded-full text-black/50 backdrop-blur-md">
276
+ <RepeatIcon className="w-3 h-3 md:w-5 md:h-5" />
274
277
  </div>
275
278
  </div>
276
279
  </div>
277
280
  </div>
278
281
 
279
- {/* Agent info */}
280
- <div className="flex flex-col items-center md:items-start text-center md:text-left gap-6">
282
+ {/* Agent info - Header Area */}
283
+ <div className="row-start-1 col-start-2 flex flex-col justify-center md:justify-start h-full md:h-auto gap-1 md:gap-6">
281
284
  {/* Agent name with custom font */}
282
285
  <h1
283
- className="text-4xl md:text-5xl lg:text-6xl font-bold text-gray-900 tracking-tight"
286
+ className="text-2xl md:text-5xl lg:text-6xl font-bold text-gray-900 tracking-tight leading-tight"
284
287
  style={{
285
288
  textShadow: '0 2px 20px rgba(255, 255, 255, 0.5)',
286
289
  }}
@@ -289,20 +292,22 @@ export function AgentProfile(props: AgentProfileProps) {
289
292
  </h1>
290
293
 
291
294
  {/* Short description */}
292
- <p className="text-lg md:text-xl text-gray-700 max-w-lg leading-relaxed font-medium">
295
+ <p className="text-sm md:text-xl text-gray-700 max-w-lg leading-relaxed font-medium line-clamp-3 md:line-clamp-none">
293
296
  {personaDescription}
294
297
  </p>
298
+ </div>
295
299
 
296
- {/* Chat */}
297
- <div className="w-full">{children}</div>
298
-
299
- {/* Secondary Actions */}
300
- {!isHeadless && (
301
- <div className="flex flex-wrap justify-center md:justify-start items-center gap-4 md:gap-6 mt-2">
302
- {actions}
303
- </div>
304
- )}
300
+ {/* Chat Area */}
301
+ <div className="col-span-2 md:col-span-1 md:col-start-2 w-full mt-2 md:mt-0">
302
+ {children}
305
303
  </div>
304
+
305
+ {/* Secondary Actions */}
306
+ {!isHeadless && (
307
+ <div className="col-span-2 md:col-span-1 md:col-start-2 flex flex-wrap justify-center md:justify-start items-center gap-4 md:gap-6 mt-2">
308
+ {actions}
309
+ </div>
310
+ )}
306
311
  </div>
307
312
 
308
313
  {/* Subtle gradient overlay at bottom */}
@@ -1,7 +1,4 @@
1
- import ReactMarkdown from 'react-markdown';
2
- import remarkGfm from 'remark-gfm';
3
- import { string_book } from '../../../../../src/book-2.0/agent-source/string_book';
4
- import { BookEditor } from '../../../../../src/book-components/BookEditor/BookEditor';
1
+ import { MarkdownContent } from '@promptbook-local/components';
5
2
  import { OpenMojiIcon } from '../OpenMojiIcon/OpenMojiIcon';
6
3
 
7
4
  type DocumentationContentProps = {
@@ -17,16 +14,22 @@ type DocumentationContentProps = {
17
14
 
18
15
  export function DocumentationContent({ primary, aliases = [], isPrintOnly = false }: DocumentationContentProps) {
19
16
  return (
20
- <div className={`bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden ${isPrintOnly ? 'shadow-none border-none' : ''}`}>
21
- <div className={`p-8 border-b border-gray-100 bg-gray-50/50 ${isPrintOnly ? 'border-none bg-white p-0 mb-4' : ''}`}>
17
+ <div
18
+ className={`bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden ${
19
+ isPrintOnly ? 'shadow-none border-none' : ''
20
+ }`}
21
+ >
22
+ <div
23
+ className={`p-8 border-b border-gray-100 bg-gray-50/50 ${
24
+ isPrintOnly ? 'border-none bg-white p-0 mb-4' : ''
25
+ }`}
26
+ >
22
27
  <div className="flex items-center gap-4 mb-4">
23
28
  <h1 className="text-4xl font-bold text-gray-900 tracking-tight">
24
29
  <OpenMojiIcon icon={primary.icon} className="mr-3" />
25
30
  {primary.type}
26
31
  {aliases.length > 0 && (
27
- <span className="text-gray-400 font-normal ml-4 text-2xl">
28
- / {aliases.join(' / ')}
29
- </span>
32
+ <span className="text-gray-400 font-normal ml-4 text-2xl">/ {aliases.join(' / ')}</span>
30
33
  )}
31
34
  </h1>
32
35
  {!isPrintOnly && (
@@ -36,16 +39,15 @@ export function DocumentationContent({ primary, aliases = [], isPrintOnly = fals
36
39
  )}
37
40
  </div>
38
41
  {primary.description && (
39
- <p className="text-xl text-gray-600 leading-relaxed max-w-3xl">
40
- {primary.description}
41
- </p>
42
+ <p className="text-xl text-gray-600 leading-relaxed max-w-3xl">{primary.description}</p>
42
43
  )}
43
44
  </div>
44
-
45
+
45
46
  <div className={`p-8 ${isPrintOnly ? 'p-0' : ''}`}>
46
47
  <article className="prose prose-lg prose-slate max-w-none prose-headings:font-bold prose-headings:tracking-tight prose-headings:text-gray-900 prose-h1:text-4xl prose-h1:mb-8 prose-h2:text-2xl prose-h2:mt-12 prose-h2:mb-6 prose-h2:pb-2 prose-h2:border-b prose-h2:border-gray-200 prose-h3:text-xl prose-h3:mt-8 prose-h3:mb-4 prose-h3:text-gray-800 prose-p:text-gray-600 prose-p:leading-relaxed prose-p:mb-6 prose-a:text-blue-600 prose-a:no-underline hover:prose-a:text-blue-700 hover:prose-a:underline prose-a:transition-colors prose-strong:font-bold prose-strong:text-gray-900 prose-code:text-blue-600 prose-code:bg-blue-50 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded-md prose-code:before:content-none prose-code:after:content-none prose-code:font-medium prose-pre:bg-gray-900 prose-pre:text-gray-100 prose-pre:shadow-lg prose-pre:rounded-xl prose-pre:p-6 prose-ul:list-disc prose-ul:pl-6 prose-li:marker:text-gray-400 prose-li:mb-2 prose-ol:list-decimal prose-ol:pl-6 prose-li:mb-2 prose-blockquote:border-l-4 prose-blockquote:border-blue-500 prose-blockquote:bg-blue-50/50 prose-blockquote:py-2 prose-blockquote:px-4 prose-blockquote:rounded-r-lg prose-blockquote:not-italic prose-blockquote:text-gray-700 prose-blockquote:my-8 prose-img:rounded-xl prose-img:shadow-md prose-img:my-8 prose-hr:border-gray-200 prose-hr:my-10 prose-table:w-full prose-th:text-left prose-th:py-2 prose-th:px-3 prose-th:bg-gray-100 prose-th:font-semibold prose-th:text-gray-900 prose-td:py-2 prose-td:px-3 prose-td:border-b prose-td:border-gray-200 prose-tr:hover:bg-gray-50">
47
- <ReactMarkdown
48
- remarkPlugins={[remarkGfm]}
48
+ <MarkdownContent
49
+ content={primary.documentation}
50
+ /* TODO: !!!!
49
51
  components={{
50
52
  code(props) {
51
53
  const { children, className, node, ...rest } = props;
@@ -77,9 +79,8 @@ export function DocumentationContent({ primary, aliases = [], isPrintOnly = fals
77
79
  );
78
80
  },
79
81
  }}
80
- >
81
- {primary.documentation}
82
- </ReactMarkdown>
82
+ */
83
+ />
83
84
  </article>
84
85
  </div>
85
86
  </div>
@@ -1,4 +1,4 @@
1
- import Link from 'next/link';
1
+ import { HeadlessLink } from '../_utils/headlessParam';
2
2
 
3
3
  export type FooterLink = {
4
4
  title: string;
@@ -33,14 +33,14 @@ export function Footer(props: FooterProps) {
33
33
  <h3 className="font-bold">Product</h3>
34
34
  <ul className="space-y-2 text-sm">
35
35
  <li>
36
- <Link href="/get-started" className="text-gray-500 hover:text-gray-900">
36
+ <HeadlessLink href="/get-started" className="text-gray-500 hover:text-gray-900">
37
37
  Get started
38
- </Link>
38
+ </HeadlessLink>
39
39
  </li>
40
40
  <li>
41
- <Link href="/manifest" className="text-gray-500 hover:text-gray-900">
41
+ <HeadlessLink href="/manifest" className="text-gray-500 hover:text-gray-900">
42
42
  Manifest
43
- </Link>
43
+ </HeadlessLink>
44
44
  </li>
45
45
  <li>
46
46
  <a
@@ -51,14 +51,14 @@ export function Footer(props: FooterProps) {
51
51
  </a>
52
52
  </li>
53
53
  <li>
54
- <Link href="/terms" className="text-gray-500 hover:text-gray-900">
54
+ <HeadlessLink href="/terms" className="text-gray-500 hover:text-gray-900">
55
55
  Terms of Service
56
- </Link>
56
+ </HeadlessLink>
57
57
  </li>
58
58
  <li>
59
- <Link href="/privacy" className="text-gray-500 hover:text-gray-900">
59
+ <HeadlessLink href="/privacy" className="text-gray-500 hover:text-gray-900">
60
60
  Privacy Policy
61
- </Link>
61
+ </HeadlessLink>
62
62
  </li>
63
63
  </ul>
64
64
  </div>
@@ -86,9 +86,9 @@ export function Footer(props: FooterProps) {
86
86
  </a>
87
87
  </li>
88
88
  <li>
89
- <Link href="/design" className="text-gray-500 hover:text-gray-900">
89
+ <HeadlessLink href="/design" className="text-gray-500 hover:text-gray-900">
90
90
  Logos & Branding
91
- </Link>
91
+ </HeadlessLink>
92
92
  </li>
93
93
  </ul>
94
94
  </div>
@@ -122,9 +122,9 @@ export function Footer(props: FooterProps) {
122
122
  </a>
123
123
  </li>
124
124
  <li>
125
- <Link href="/contact" className="text-gray-500 hover:text-gray-900">
125
+ <HeadlessLink href="/contact" className="text-gray-500 hover:text-gray-900">
126
126
  More
127
- </Link>
127
+ </HeadlessLink>
128
128
  </li>
129
129
  </ul>
130
130
  </div>