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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@ export default {
trailingSlash: true,
tagline: "GraphQL platform engineered for scale",
headTags: [
{
tagName: "script",
attributes: {
id: "chatbotscript",
"data-accountid": "CZPG9aVdtk59Tjz4SMTu8w==",
"data-websiteid": "75VGI0NlBqessD4BQn2pFg==",
src: "https://app.robofy.ai/bot/js/common.js?v=" + new Date().getTime(),
},
},
{
tagName: "script",
attributes: {
Expand Down Expand Up @@ -78,9 +69,7 @@ export default {
editUrl: `https://github.com/${organization}/${project}/tree/develop`,
},
blog: false,
theme: {
customCss: require.resolve("./src/css/custom.css"),
},
theme: {},
sitemap: {
changefreq: "weekly",
priority: 0.5,
Expand Down Expand Up @@ -152,6 +141,7 @@ export default {
tableOfContents: {},
} satisfies Preset.ThemeConfig,
plugins: [
"./plugins/static-homepage-plugin.ts",
[
"./plugins/custom-blog-plugin.ts",
{
Expand Down
22 changes: 22 additions & 0 deletions plugins/static-homepage-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import fs from "fs/promises"
import path from "path"

function staticHomepagePlugin() {
return {
name: "static-homepage-plugin",
async postBuild({outDir}: {outDir: string}) {
const indexPath = path.join(outDir, "index.html")
const html = await fs.readFile(indexPath, "utf8")
const staticHtml = html
.replace(/<script data-rh="true">function insertBanner\(\)[\s\S]*?<\/script>/, "")
.replace(/<link rel="stylesheet" href="\/assets\/css\/styles\.[^"]+\.css">/g, "")
.replace(/<script src="\/assets\/js\/runtime~main\.[^"]+\.js" defer="defer"><\/script>/g, "")
.replace(/<script src="\/assets\/js\/main\.[^"]+\.js" defer="defer"><\/script>/g, "")
.replace("</head>", "<style>html,body{margin:0}*{box-sizing:border-box}</style></head>")

await fs.writeFile(indexPath, staticHtml)
},
}
}

export default staticHomepagePlugin
20 changes: 20 additions & 0 deletions src/components/shared/GlobalLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ const GlobalLayout: React.FC = () => {
}
}, [cookieConsent])

useEffect(() => {
if (typeof window === "undefined" || document.getElementById("chatbotscript")) return

const loadChatbot = () => {
const script = document.createElement("script")
script.id = "chatbotscript"
script.dataset.accountid = "CZPG9aVdtk59Tjz4SMTu8w=="
script.dataset.websiteid = "75VGI0NlBqessD4BQn2pFg=="
script.src = "https://app.robofy.ai/bot/js/common.js"
script.async = true
document.body.appendChild(script)
}

if ("requestIdleCallback" in window) {
window.requestIdleCallback(loadChatbot)
} else {
window.setTimeout(loadChatbot, 1500)
}
}, [])

return (
<>
<CookieConsentModal
Expand Down
6 changes: 2 additions & 4 deletions src/css/custom.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;700&family=Space+Mono&display=swap");

@tailwind base;
@tailwind components;
@tailwind utilities;
Expand Down Expand Up @@ -34,7 +32,7 @@

:root {
/* Font and Dimension Tokens */
--ifm-font-family-base: "Space Grotesk", sans-serif;
--ifm-font-family-base: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--header-height: 6.5rem;
--ifm-navbar-height: 6.5rem;
--ifm-navbar-height-sm: 4.5rem;
Expand Down Expand Up @@ -72,7 +70,7 @@
--ifm-color-brand-light-opacity-15: rgba(255, 255, 255, 0.15);

/* Code Settings */
--ifm-font-family-monospace: "Space Mono";
--ifm-font-family-monospace: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
--ifm-code-background: rgb(246, 247, 248);
--ifm-code-border-radius: var(--ifm-global-radius);
--ifm-code-font-size: 0.9eem;
Expand Down
254 changes: 230 additions & 24 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,238 @@
import React, {useEffect} from "react"
import Layout from "@theme/Layout"
import ReactGA from "react-ga4"
import {useLocation} from "@docusaurus/router"

import HomePage from "../components/home"
import React from "react"
import Head from "@docusaurus/Head"
import Link from "@docusaurus/Link"
import {PageDescription, PageTitle} from "../constants/titles"
import Announcement from "../components/shared/Announcement"

const styles: Record<string, React.CSSProperties> = {
main: {
minHeight: "100vh",
background: "#ffffff",
color: "#111827",
fontFamily: 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
},
header: {
maxWidth: 1120,
margin: "0 auto",
padding: "24px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: 24,
},
brand: {
display: "flex",
alignItems: "center",
gap: 12,
color: "#111827",
fontWeight: 700,
textDecoration: "none",
},
logo: {
width: 36,
height: 36,
},
nav: {
display: "flex",
alignItems: "center",
gap: 20,
fontSize: 14,
fontWeight: 600,
},
navLink: {
color: "#111827",
textDecoration: "none",
},
hero: {
maxWidth: 1120,
margin: "0 auto",
padding: "40px 24px 80px",
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(280px, 1fr))",
gap: 40,
alignItems: "center",
},
h1: {
maxWidth: 720,
margin: 0,
fontSize: "clamp(48px, 8vw, 72px)",
lineHeight: 1.05,
fontWeight: 800,
letterSpacing: 0,
},
highlight: {
display: "inline-block",
background: "#ffdb59",
borderRadius: 14,
padding: "0 10px",
},
copy: {
maxWidth: 660,
margin: "24px 0 0",
color: "#4b5563",
fontSize: 20,
lineHeight: 1.6,
},
actions: {
display: "flex",
flexWrap: "wrap",
gap: 12,
marginTop: 32,
},
primaryButton: {
display: "inline-flex",
minHeight: 48,
alignItems: "center",
justifyContent: "center",
borderRadius: 999,
background: "#111827",
color: "#ffffff",
padding: "0 28px",
fontSize: 14,
fontWeight: 700,
textDecoration: "none",
},
secondaryButton: {
display: "inline-flex",
minHeight: 48,
alignItems: "center",
justifyContent: "center",
border: "1px solid #111827",
borderRadius: 999,
color: "#111827",
padding: "0 28px",
fontSize: 14,
fontWeight: 700,
textDecoration: "none",
},
codeWrap: {
border: "1px solid #e5e7eb",
borderRadius: 24,
background: "#f9fafb",
padding: 24,
},
codeInner: {
borderRadius: 18,
background: "#ffffff",
padding: 20,
boxShadow: "0 1px 4px rgba(17,24,39,0.08)",
},
pre: {
margin: 0,
overflowX: "auto",
color: "#374151",
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace',
fontSize: 14,
lineHeight: 1.65,
},
features: {
borderTop: "1px solid #e5e7eb",
background: "#f9fafb",
},
featureGrid: {
maxWidth: 1120,
margin: "0 auto",
padding: "48px 24px",
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
gap: 24,
},
featureTitle: {
margin: 0,
fontSize: 18,
fontWeight: 800,
},
featureCopy: {
margin: "8px 0 0",
color: "#4b5563",
fontSize: 14,
lineHeight: 1.6,
},
}

const Home = (): JSX.Element => {
const isDevelopment = process.env.NODE_ENV === "development"
const location = useLocation()
return (
<>
<Head>
<title>{PageTitle.HOME}</title>
<meta name="description" content={PageDescription.HOME} />
<style>{`html,body{margin:0}*{box-sizing:border-box}`}</style>
</Head>
<main style={styles.main}>
<header style={styles.header}>
<Link to="/" style={styles.brand}>
<img src="/icons/companies/tailcall.svg" alt="" style={styles.logo} width="36" height="36" />
<span>Tailcall</span>
</Link>
<nav style={styles.nav}>
<Link to="/docs/" style={styles.navLink}>
Docs
</Link>
<Link to="/blog/" style={styles.navLink}>
Blog
</Link>
</nav>
</header>

useEffect(() => {
ReactGA.send({hitType: "pageview", page: location.pathname, title: "Home Page"})
}, [])
<section style={styles.hero}>
<div>
<h1 style={styles.h1}>
The modern <span style={styles.highlight}>GraphQL</span> platform.
</h1>
<p style={styles.copy}>
Leverage AI to design and ship best-practice GraphQL backends atop existing data sources and APIs.
</p>
<div style={styles.actions}>
<Link to="/docs/" style={styles.primaryButton}>
Get started
</Link>
<Link to="/graphql/" style={styles.secondaryButton}>
Learn GraphQL
</Link>
</div>
</div>

return (
<Layout title={PageTitle.HOME} description={PageDescription.HOME}>
<HomePage />
{!isDevelopment && (
<img
style={{height: 0, width: 0}}
referrerPolicy="no-referrer-when-downgrade"
src="https://static.scarf.sh/a.png?x-pxid=45ec365f-ab8a-4848-a6a9-bd4ffecfe72e"
alt="pixel"
/>
)}
</Layout>
<div style={styles.codeWrap}>
<div style={styles.codeInner}>
<pre style={styles.pre}>
<code>{`schema @server(port: 8000) {
query: Query
}

type Query {
users: [User] @http(url: "/users")
}

type User {
id: ID!
name: String!
}`}</code>
</pre>
</div>
</div>
</section>

<section style={styles.features}>
<div style={styles.featureGrid}>
<div>
<h2 style={styles.featureTitle}>Instant GraphQL</h2>
<p style={styles.featureCopy}>Connect REST, gRPC, and GraphQL APIs without hand-written BFF code.</p>
</div>
<div>
<h2 style={styles.featureTitle}>Built for scale</h2>
<p style={styles.featureCopy}>
Static checks, query planning, and runtime performance for production teams.
</p>
</div>
<div>
<h2 style={styles.featureTitle}>Open source</h2>
<p style={styles.featureCopy}>
Adopt incrementally, inspect everything, and deploy where your stack already runs.
</p>
</div>
</div>
</section>
</main>
</>
)
}

Expand Down
1 change: 1 addition & 0 deletions src/theme/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Footer from "@theme/Footer"
import LayoutProvider from "@theme/Layout/Provider"
import ErrorPageContent from "@theme/ErrorPageContent"
import type {Props} from "@theme/Layout"
import "../../css/custom.css"
import styles from "./styles.module.css"
import GlobalLayout from "@site/src/components/shared/GlobalLayout"
import Announcement from "@site/src/components/shared/Announcement"
Expand Down
Loading