Skip to content

Commit 689c02c

Browse files
committed
feat: Add new components and pages for landing, pricing, privacy, terms, tools, and examples
- Implement LandingHero component for the landing page with AI SDK v5 and React 19 announcement. - Create LandingStats component to display key statistics about the platform. - Develop NetworksList component to showcase various agent networks with search functionality. - Introduce PageHeader component for consistent page headers across the application. - Add PricingTiers component to present pricing options with monthly and yearly plans. - Implement PrivacyContent component to outline the privacy policy. - Create TermsContent component to detail the terms of service. - Develop ToolsList component to display available tools with search and category filtering. - Add ContactPage for user inquiries with a contact form. - Create Getting Started documentation page with installation and usage instructions. - Implement DocsPage and ExamplesPage for documentation navigation and examples display. - Add PricingPage, PrivacyPage, TermsPage, and ToolsPage for respective content display. - Enhance MDX components for better styling and functionality in documentation.
1 parent f6ab7e1 commit 689c02c

52 files changed

Lines changed: 3718 additions & 287 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
---
2+
name: Code Conventions
3+
description: Guidelines and best practices for writing code in the Mastra project.
4+
applyTo: '**'
5+
---
6+
# Code Conventions
7+
8+
## Tool Implementation Pattern
9+
10+
All tools follow this structure:
11+
12+
```typescript
13+
import { createTool } from "@mastra/core/tools";
14+
import { z } from "zod";
15+
import { AISpanType } from "@mastra/core/ai-tracing";
16+
import type { RuntimeContext } from "@mastra/core/runtime-context";
17+
import { log } from "../config/logger";
18+
19+
// Define the Zod schema for the runtime context
20+
const myToolContextSchema = z.object({
21+
temperatureUnit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
22+
})
23+
24+
// Infer the TypeScript type from the Zod schema
25+
export type MyToolContext = z.infer<typeof myToolContextSchema>
26+
27+
export const myTool = createTool({
28+
id: "my-tool",
29+
description: "Clear description of what the tool does",
30+
inputSchema: z.object({
31+
param: z.string().describe("Parameter description")
32+
}),
33+
outputSchema: z.object({
34+
data: z.any().describe("Result data"),
35+
error: z.string().optional()
36+
}),
37+
execute: async ({ context, tracingContext, runtimeContext }) => {
38+
const startTime = Date.now();
39+
40+
// Create root tracing span
41+
const rootSpan = tracingContext?.currentSpan?.createChildSpan({
42+
type: AISpanType.TOOL_CALL,
43+
name: 'my-tool',
44+
input: context,
45+
runtimeContext: myToolContextSchema.parse(runtimeContext.toObject()),
46+
});
47+
48+
try {
49+
// Tool logic here
50+
log.info('my-tool executed', { context });
51+
52+
rootSpan?.end({ output: result });
53+
return result;
54+
} catch (error) {
55+
log.error('my-tool error', { error, context });
56+
rootSpan?.error({ error });
57+
return { data: null, error: errorMessage };
58+
}
59+
}
60+
});
61+
```
62+
63+
## Key Patterns
64+
65+
### Zod Schemas Everywhere
66+
67+
- All tool inputs and outputs use Zod schemas
68+
- Add `.describe()` to every field for LLM understanding
69+
- Use strict validation - no `any` without good reason
70+
71+
### Error Handling
72+
73+
- Always return structured errors, never throw from tools
74+
- Use `{ data: result, error: undefined }` pattern
75+
- Log errors with context using `log.error()`
76+
- Update tracing spans with error information
77+
78+
### Tracing & Observability
79+
80+
- Create child spans for all significant operations
81+
- Log operations with `log.info()`, `log.error()`, etc.
82+
- Include governance context (userId, tenantId, roles) when available
83+
- Track timing for performance monitoring
84+
85+
### Environment Variables
86+
87+
- Use `process.env.VAR_NAME` for API keys
88+
- Check for undefined/null/empty before use
89+
- Return error if required env var is missing
90+
- Never log or expose API keys (use `[REDACTED]`)
91+
92+
### Runtime Context
93+
94+
- Extract governance info from runtimeContext
95+
- Support optional context fields with defaults
96+
- Type runtime context with custom interfaces when needed
97+
98+
### API Calls
99+
100+
- Create child spans for external API calls
101+
- Redact API keys in logged URLs
102+
- Handle response errors gracefully
103+
- Track timing for performance monitoring
104+
105+
## Agent Implementation Pattern
106+
107+
```typescript
108+
import { Agent } from '@mastra/core/agent'
109+
import { googleAI } from '../config/google'
110+
import { pgMemory } from '../config/pg-storage'
111+
112+
export const myAgent = new Agent({
113+
id: 'my-agent',
114+
name: 'My Agent',
115+
description: 'What this agent does',
116+
instructions: ({ runtimeContext }) => {
117+
// Dynamic instructions based on context
118+
return `You are an expert at...`;
119+
},
120+
model: googleAI,
121+
tools: {
122+
tool1,
123+
tool2,
124+
},
125+
memory: pgMemory,
126+
scorers: {
127+
quality: {
128+
scorer: myScorer,
129+
sampling: { type: "ratio", rate: 0.5 }
130+
}
131+
}
132+
});
133+
```
134+
135+
## Testing Conventions
136+
137+
### Test Structure
138+
139+
```typescript
140+
import { describe, it, expect, beforeEach, vi } from 'vitest'
141+
142+
describe('myTool', () => {
143+
beforeEach(() => {
144+
vi.clearAllMocks()
145+
})
146+
147+
it('should successfully execute', async () => {
148+
// Mock external dependencies
149+
global.fetch = vi.fn().mockResolvedValue({
150+
json: () => Promise.resolve(mockData)
151+
});
152+
153+
// Create mock contexts
154+
const mockRuntimeContext = {
155+
get: vi.fn().mockReturnValue(value)
156+
} as any;
157+
158+
const mockTracingContext = {
159+
currentSpan: {
160+
createChildSpan: vi.fn().mockReturnValue({
161+
end: vi.fn(),
162+
error: vi.fn()
163+
})
164+
}
165+
} as any;
166+
167+
// Execute and assert
168+
const result = await myTool.execute({
169+
context: { param: 'value' },
170+
runtimeContext: mockRuntimeContext,
171+
tracingContext: mockTracingContext
172+
});
173+
174+
expect(result.data).toBeDefined();
175+
expect(result.error).toBeUndefined();
176+
});
177+
178+
it('should handle errors', async () => {
179+
// Test error cases
180+
});
181+
});
182+
```
183+
184+
### Testing Rules
185+
186+
- Mock all external API calls with `vi.fn()`
187+
- Test success and error paths
188+
- Mock runtimeContext and tracingContext
189+
- Use `beforeEach` to clear mocks
190+
- Colocate tests in `tests/` subdirectory
191+
- Aim for 95%+ coverage
192+
193+
## TypeScript Conventions
194+
195+
- Use strict mode (enabled in tsconfig.json)
196+
- Prefer interfaces for public APIs, types for internal
197+
- Use explicit return types for public functions
198+
- Avoid `any` - use `unknown` or proper types
199+
- Use optional chaining (`?.`) for nullable access
200+
- Use nullish coalescing (`??`) for defaults
201+
202+
## Import Organization
203+
204+
```typescript
205+
// 1. External framework imports
206+
import { createTool } from "@mastra/core/tools";
207+
import { z } from "zod";
208+
209+
// 2. Type imports
210+
import type { RuntimeContext } from "@mastra/core/runtime-context";
211+
212+
// 3. Internal imports (config, tools, etc.)
213+
import { log } from "../config/logger";
214+
import { pgQueryTool } from "../config/pg-storage";
215+
```
216+
217+
## Security Practices
218+
219+
- Validate all inputs with Zod schemas
220+
- Sanitize HTML content (use JSDOM/Cheerio)
221+
- Validate file paths to prevent traversal
222+
- Mask sensitive data in logs
223+
- Use JWT/RBAC for access control
224+
- Never commit API keys or secrets
225+
226+
## Naming Conventions
227+
228+
- Tools: camelCase with "Tool" suffix (e.g., `webScraperTool`)
229+
- Agents: camelCase with "Agent" suffix (e.g., `researchAgent`)
230+
- Functions: camelCase (e.g., `extractLearnings`)
231+
- Constants: UPPER_SNAKE_CASE (e.g., `API_KEY`)
232+
- Types/Interfaces: PascalCase (e.g., `RuntimeContext`)
233+
- Files: kebab-case (e.g., `web-scraper-tool.ts`)

app/about/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Navbar } from "@/app/components/navbar"
2+
import { Footer } from "@/app/components/footer"
3+
import { AboutContent } from "@/app/components/about-content"
4+
5+
export default function AboutPage() {
6+
return (
7+
<div className="flex min-h-screen flex-col bg-background">
8+
<Navbar />
9+
<main className="flex-1">
10+
<AboutContent />
11+
</main>
12+
<Footer />
13+
</div>
14+
)
15+
}

app/api-reference/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Navbar } from "@/app/components/navbar"
2+
import { Footer } from "@/app/components/footer"
3+
import { ApiReferenceContent } from "@/app/components/api-reference-content"
4+
5+
export default function ApiReferencePage() {
6+
return (
7+
<div className="flex min-h-screen flex-col bg-background">
8+
<Navbar />
9+
<main className="flex-1">
10+
<ApiReferenceContent />
11+
</main>
12+
<Footer />
13+
</div>
14+
)
15+
}

app/api/v0/route.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { v0 } from 'v0-sdk';
2+
3+
export async function POST(req: Request) {
4+
const { prompt }: { prompt: string } = await req.json();
5+
const result = await v0.chats.create({
6+
system: 'You are an expert coder',
7+
message: prompt,
8+
modelConfiguration: {
9+
modelId: 'v0-1.5-sm',
10+
imageGenerations: false,
11+
thinking: false,
12+
},
13+
});
14+
return Response.json(result);
15+
}

app/blog/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Navbar } from "@/app/components/navbar"
2+
import { Footer } from "@/app/components/footer"
3+
import { BlogList } from "@/app/components/blog-list"
4+
5+
export default function BlogPage() {
6+
return (
7+
<div className="flex min-h-screen flex-col bg-background">
8+
<Navbar />
9+
<main className="flex-1">
10+
<BlogList />
11+
</main>
12+
<Footer />
13+
</div>
14+
)
15+
}

app/careers/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Navbar } from "@/app/components/navbar"
2+
import { Footer } from "@/app/components/footer"
3+
import { CareersContent } from "@/app/components/careers-content"
4+
5+
export default function CareersPage() {
6+
return (
7+
<div className="flex min-h-screen flex-col bg-background">
8+
<Navbar />
9+
<main className="flex-1">
10+
<CareersContent />
11+
</main>
12+
<Footer />
13+
</div>
14+
)
15+
}

app/changelog/page.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Navbar } from "@/app/components/navbar"
2+
import { Footer } from "@/app/components/footer"
3+
import { ChangelogList } from "@/app/components/changelog-list"
4+
5+
export default function ChangelogPage() {
6+
return (
7+
<div className="flex min-h-screen flex-col bg-background">
8+
<Navbar />
9+
<main className="flex-1">
10+
<ChangelogList />
11+
</main>
12+
<Footer />
13+
</div>
14+
)
15+
}

0 commit comments

Comments
 (0)