Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.next
_pagefind/
node_modules
.pnpm-store
.vercel
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enable-pre-post-scripts=true
33 changes: 33 additions & 0 deletions app/[[...mdxPath]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Suspense } from 'react'
import { generateStaticParamsFor, importPage } from 'nextra/pages'
import { useMDXComponents as getMDXComponents } from '../../mdx-components'
import { MainContentWrapper } from '@/components/MainContentWrapper'

export const generateStaticParams = generateStaticParamsFor('mdxPath')

export async function generateMetadata(props: {
params: Promise<{ mdxPath?: string[] }>
}) {
const params = await props.params
const { metadata } = await importPage(params.mdxPath)
return metadata
}

const Wrapper = getMDXComponents().wrapper

export default async function Page(props: {
params: Promise<{ mdxPath?: string[] }>
}) {
const params = await props.params
const result = await importPage(params.mdxPath)
const { default: MDXContent, toc, metadata } = result
return (
<Suspense fallback={null}>
<MainContentWrapper>
<Wrapper toc={toc} metadata={metadata}>
<MDXContent {...props} params={params} />
</Wrapper>
</MainContentWrapper>
</Suspense>
)
}
101 changes: 101 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Footer, Layout, Navbar } from 'nextra-theme-docs'
import { Head, Search } from 'nextra/components'
import { getPageMap } from 'nextra/page-map'
import 'nextra-theme-docs/style-prefixed.css'
import '../style.css'
import '../src/overrides.css'
import 'vidstack/styles/base.css'
import { Providers } from './providers'
import { Logo } from '@/components/logo'
import { Button } from '@/components/ui/button'
import { TOCExtraContent } from '@/components/TOCExtraContent'
import Link from 'next/link'
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: {
template: '%s - Lamatic.ai Docs',
default: 'Lamatic.ai Docs',
},
description: 'Lamatic.ai documentation',
metadataBase: new URL('https://lamatic.ai'),
openGraph: {
siteName: 'Lamatic.ai',
type: 'website',
},
twitter: {
card: 'summary_large_image',
site: 'lamatic.ai',
},
other: {
'theme-color': '#000',
},
}

const logo = <Logo />

const navbarExtra = (
<Button size="xs" asChild className="whitespace-nowrap w-[70px]">
<Link href="https://studio.lamatic.ai/signup">Sign Up</Link>
</Button>
)

const navbar = (
<Navbar
logo={logo}
projectLink="https://github.com/lamatic/docs"
>
<Search placeholder="Search..." />
{navbarExtra}
</Navbar>
)

const footer = <Footer />

export default async function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" dir="ltr" suppressHydrationWarning>
<Head
faviconGlyph="L"
>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16x16.png"
/>
</Head>
<body>
<Providers>
<Layout
pageMap={await getPageMap()}
docsRepositoryBase="https://github.com/lamatic/docs/tree/main"
editLink="Edit this page on GitHub"
feedback={{ labels: 'feedback', content: 'Question? Give us feedback', link: 'https://product.lamatic.ai/' }}
sidebar={{ defaultMenuCollapseLevel: 1, toggleButton: true }}
toc={{ extraContent: <TOCExtraContent /> }}
navbar={navbar}
footer={footer}
>
{children}
</Layout>
</Providers>
</body>
</html>
)
}
82 changes: 82 additions & 0 deletions app/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
'use client'

import { useEffect } from 'react'
import { usePathname } from 'next/navigation'
import posthog from 'posthog-js'
import { PostHogProvider } from 'posthog-js/react'
import { GeistSans } from 'geist/font/sans'
import { GeistMono } from 'geist/font/mono'
import ChatbotScript from '@/components/ChatbotScript'
import { SidebarSwitcher } from '@/components/SidebarSwitcher'
import { hsPageView } from '@/components/analytics/hubspot'

function Analytics() {
const pathname = usePathname()

useEffect(() => {
// Initialize PostHog once
if (typeof window !== 'undefined' && !(window as any).__posthog_initialized) {
(window as any).__posthog_initialized = true
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host:
process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://eu.posthog.com',
loaded: (posthog) => {
if (process.env.NODE_ENV === 'development') posthog.debug()
},
})
}

// Initialize GTM once
if (typeof window !== 'undefined' && !(window as any).dataLayer) {
(window as any).dataLayer = (window as any).dataLayer || []
function gtag(...args: any[]) {
(window as any).dataLayer.push(args)
}
gtag('js', new Date())
gtag('config', process.env.NEXT_PUBLIC_GTM_ID)

const gtmScript = document.createElement('script')
gtmScript.async = true
gtmScript.src = `https://www.googletagmanager.com/gtm.js?id=${process.env.NEXT_PUBLIC_GTM_ID}`
document.head.appendChild(gtmScript)
}
}, [])

// Track page views on route changes
useEffect(() => {
posthog.capture('$pageview')
hsPageView(pathname)
}, [pathname])

// Sync pathname to html for CSS selectors (e.g. embed/agentkit overrides)
useEffect(() => {
if (typeof document !== 'undefined') {
document.documentElement.dataset.pathname = pathname ?? ''
}
}, [pathname])

return null
}

export function Providers({ children }: { children: React.ReactNode }) {
return (
<div
className={`${GeistSans.variable} font-sans ${GeistMono.variable}`}
>
<PostHogProvider client={posthog}>
<noscript>
<iframe
src={`https://www.googletagmanager.com/ns.html?id=${process.env.NEXT_PUBLIC_GTM_ID}`}
height="0"
width="0"
style={{ display: 'none', visibility: 'hidden' }}
/>
</noscript>
<Analytics />
{children}
<SidebarSwitcher />
<ChatbotScript />
</PostHogProvider>
</div>
)
}
10 changes: 5 additions & 5 deletions components/AgentsKitsIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"use client";
import React, { useState, useMemo } from "react";
import Link from "next/link";
import Image from "next/image";
import { getPagesUnderRoute } from "nextra/context";
import { useGetPagesUnderRoute } from "@/lib/nextra-compat";
import { type Page } from "nextra";
import {
Card,
Expand Down Expand Up @@ -217,12 +218,11 @@ const AgentsKitsIndex = () => {
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const [viewMode, setViewMode] = useState<"grid" | "list">("grid");

// Get all pages under /templates/agentkits (including subfolders)
const allPages = getPagesUnderRoute("/templates/agentkits");
const allPages = useGetPagesUnderRoute("/agentkits");
const pages = flattenPages(allPages).filter(
(page) =>
page.route !== "/templates/agentkits" &&
page.route !== "/templates/agentkits/index"
page.route !== "/agentkits" &&
page.route !== "/agentkits/index"
);

// Group by type/category from route path or frontmatter
Expand Down
6 changes: 3 additions & 3 deletions components/AppsDataSourcesTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getPagesUnderRoute } from "nextra/context";
"use client";
import { useGetPagesUnderRoute } from "@/lib/nextra-compat";
import { type Page } from "nextra";
import Link from "next/link";
import { ExternalLinkIcon } from "lucide-react";
Expand All @@ -25,8 +26,7 @@ function flattenPages(pages) {
}

export const AppsDataSourcesTable = () => {
// Get all pages under /integrations/apps-data-sources
const allPages = getPagesUnderRoute("/integrations/apps-data-sources");
const allPages = useGetPagesUnderRoute("/integrations/apps-data-sources");
const pages = flattenPages(allPages).filter(
(page) =>
page.route !== "/integrations/apps-data-sources" &&
Expand Down
2 changes: 2 additions & 0 deletions components/Contributors.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import React, { useEffect, useState } from 'react';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
Expand Down
27 changes: 14 additions & 13 deletions components/CookbookIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { getPagesUnderRoute } from "nextra/context";
"use client";
import { useGetPagesUnderRoute } from "@/lib/nextra-compat";
import { type Page } from "nextra";
import { Card, Cards } from "nextra-theme-docs";
import { Cards } from "nextra/components";
import { FileCode } from "lucide-react";

export const CookbookIndex = () => (
export const CookbookIndex = () => {
const pages = (useGetPagesUnderRoute("/guides/cookbook") as Array<
Page & { frontMatter: any }
>).filter((page) => page.route !== "/cookbook" && page.route !== "/guides/cookbook");
return (
<>
{Object.entries(
(
getPagesUnderRoute("/guides/cookbook") as Array<
Page & { frontMatter: any }
>
)
.filter((page) => page.route !== "/cookbook")
pages
.reduce((acc, page) => {
const category = page.frontMatter?.category || "Other";
if (!acc[category]) acc[category] = [];
Expand All @@ -29,20 +29,21 @@ export const CookbookIndex = () => (
<h3 className="nx-font-semibold nx-tracking-tight nx-text-slate-900 dark:nx-text-slate-100 nx-mt-8 nx-text-2xl">
{category}
</h3>
<Cards num={2}>
<Cards.Cards num={2}>
{pages.map((page) => (
<Card
<Cards.Card
href={page.route}
key={page.route}
title={page.meta?.title || page.frontMatter?.title || page.name}
icon={<FileCode />}
arrow
>
{""}
</Card>
</Cards.Card>
))}
</Cards>
</div>
))}
</>
);
);
};
Loading