Skip to content

Commit

Permalink
馃摑 Improve blog capabilities and components
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Apr 20, 2024
1 parent e4e724d commit eb2001c
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 11 deletions.
14 changes: 14 additions & 0 deletions apps/docs/contribute/guides/blog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,17 @@ summary: 'A short summary of the blog post.'
```

By default the og image is generated from the title of the blog post. If you want to use a custom og image, you can specify a `image` field in the frontmatter.

All images need to be placed under the `public/images/blog/<POST_FILENAME>` folder where `<POST_FILENAME>` is the name of the mdx file you are creating/editing.

Here are all the components you can use in your blog post:

- `Image`: To display an image. Example: `<Image src="/images/blog/my-awesome-blog-post/image.jpg" alt="My awesome image" />`
- `Callout`: To display a callout. Example: `<Callout status="info">This is an info callout</Callout>`. You can provide a `status` prop with the value `info`, `warning`, `success`, or `error`.
- `Tweet`: To embed a tweet. Example: `<Tweet id="1234567890123456789" />`
- `Typebot`: To embed a typebot as a Standard component. Example: `<Typebot typebot="<YOUR_BOT_PUBLIC_ID>" />`. You can provide the same props as the [Standard component](../../deploy/web/libraries/react#standard).
- `YouTube`: To embed a YouTube video. Example: `<YouTube id="<YOUTUBE_VIDEO_ID>" />`
- `Loom`: To embed a Loom video. Example: `<Loom id="<LOOM_VIDEO_ID>" />`
- `Cta`: To display a call-to-action that redirects to Typebot. Example: `<Cta />`

For rendering tables you should use the native html table related tags.
3 changes: 3 additions & 0 deletions apps/docs/openapi/viewer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12033,6 +12033,9 @@
"content": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"maxBubbleWidth": {
"type": "number"
},
Expand Down
107 changes: 104 additions & 3 deletions apps/landing-page/app/blog/[slug]/Post.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
/* eslint-disable jsx-a11y/alt-text */
'use client'

import { Link } from '@chakra-ui/next-js'
import { Heading, Stack, Text } from '@chakra-ui/react'
import {
Alert,
AlertIcon,
Heading,
Stack,
Table,
TableCaption,
TableContainer,
Tbody,
Td,
Text,
Tfoot,
Th,
Thead,
Tr,
Image,
} from '@chakra-ui/react'
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'
import { highlight } from 'sugar-high'
import { Tweet } from './Tweet'
import { Standard } from '@typebot.io/nextjs'
import { EndCta } from '@/components/Homepage/EndCta'

type Props = {
metadata: {
Expand All @@ -14,7 +34,7 @@ type Props = {
}

export const Post = ({ metadata, mdxSource }: Props) => (
<Stack spacing={10} my="20">
<Stack spacing={10} my="20" w="full">
<Stack mx="auto" w="full" maxW="65ch">
<Heading>{metadata.title}</Heading>
<Text>{formatDate(metadata.publishedAt)}</Text>
Expand All @@ -23,7 +43,7 @@ export const Post = ({ metadata, mdxSource }: Props) => (
mx="auto"
spacing={0}
as="article"
className="prose prose-quoteless prose-neutral prose-invert"
className="prose prose-quoteless prose-neutral prose-invert max-w-none w-full px-3 sm:px-0"
>
<MDXRemote
{...mdxSource}
Expand All @@ -42,6 +62,87 @@ export const Post = ({ metadata, mdxSource }: Props) => (
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
link: (props: any) => <Link {...props} />,
Image: (props) => (
<Image rounded="md" maxW={['full', '65ch']} {...props} />
),
Callout: ({ children, ...props }) => (
<Alert rounded="md" {...props}>
<AlertIcon />
{children}
</Alert>
),
Tweet,
Typebot: Standard,
Youtube: ({ id }: { id: string }) => (
<div className="w-full">
<div
style={{
position: 'relative',
paddingBottom: '64.63195691202873%',
height: 0,
width: '100%',
}}
>
<iframe
src={`https://www.youtube.com/embed/${id}`}
allowFullScreen
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
}}
></iframe>
</div>
</div>
),
Loom: ({ id }: { id: string }) => (
<div className="w-full">
<div
style={{
position: 'relative',
paddingBottom: '64.63195691202873%',
height: 0,
width: '100%',
}}
>
<iframe
src={`https://www.loom.com/embed/${id}`}
allowFullScreen
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
}}
></iframe>
</div>
</div>
),
Cta: (props) => (
<EndCta
{...props}
style={{ maxWidth: 'none' }}
w="full"
height="70vh"
className="w-full"
bgGradient={undefined}
/>
),
table: (props) => (
<TableContainer>
<Table {...props} />
</TableContainer>
),
thead: Thead,
tbody: Tbody,
th: Th,
td: Td,
tfoot: Tfoot,
tr: Tr,
caption: TableCaption,
}}
/>
</Stack>
Expand Down
36 changes: 36 additions & 0 deletions apps/landing-page/app/blog/[slug]/Tweet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getTweet } from 'react-tweet/api'
import { EmbeddedTweet, TweetNotFound, type TweetProps } from 'react-tweet'
import './tweet.css'

const TweetContent = async ({ id, components, onError }: TweetProps) => {
let error
const tweet = id
? await getTweet(id).catch((err) => {
if (onError) {
error = onError(err)
} else {
console.error(err)
error = err
}
})
: undefined

if (!tweet) {
const NotFound = components?.TweetNotFound || TweetNotFound
return <NotFound error={error} />
}

return <EmbeddedTweet tweet={tweet} components={components} />
}

export const ReactTweet = (props: TweetProps) => <TweetContent {...props} />

export async function Tweet({ id }: { id: string }) {
return (
<div className="tweet my-6">
<div className={`flex justify-center`}>
<ReactTweet id={id} />
</div>
</div>
)
}
63 changes: 63 additions & 0 deletions apps/landing-page/app/blog/[slug]/tweet.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* Light theme (default) */
.tweet .react-tweet-theme {
/* margin is handled by our wrappers */
--tweet-container-margin: 0;
--tweet-font-family: inherit;
--tweet-font-color: inherit;

--tweet-bg-color: #222;
--tweet-bg-color-hover: var(--tweet-bg-color);
--tweet-quoted-bg-color-hover: rgba(255, 255, 255, 0.03);
--tweet-border: 1px solid #333;
--tweet-color-blue-secondary: theme('colors.white');
--tweet-color-blue-secondary-hover: #333;
--tweet-font-color-secondary: theme('colors.gray.400');

/* Common properties for both themes */
--tweet-quoted-bg-color-hover: rgba(0, 0, 0, 0.03);
--tweet-border: 1px solid rgb(64, 64, 64);
--tweet-skeleton-gradient: linear-gradient(
270deg,
#fafafa,
#eaeaea,
#eaeaea,
#fafafa
);
--tweet-color-red-primary: rgb(249, 24, 128);
--tweet-color-red-primary-hover: rgba(249, 24, 128, 0.1);
--tweet-color-green-primary: rgb(0, 186, 124);
--tweet-color-green-primary-hover: rgba(0, 186, 124, 0.1);
--tweet-twitter-icon-color: var(--tweet-font-color);
--tweet-verified-old-color: rgb(130, 154, 171);
--tweet-verified-blue-color: var(--tweet-color-blue-primary);

--tweet-actions-font-weight: 500;
--tweet-replies-font-weight: 500;
}

/* Common styles for both themes */
.tweet .react-tweet-theme p {
font-size: inherit;
line-height: 1.3rem;
}

.tweet .react-tweet-theme p a {
@apply border-b transition-[border-color] border-gray-500 text-white hover:border-white;
}

/* Remove link underline on hover for both themes */
.tweet .react-tweet-theme p a:hover {
text-decoration: none;
}

.tweet a div {
@apply font-medium tracking-tight;
}

.tweet div[class*='mediaWrapper'] {
max-height: 250px;
}

.tweet .react-tweet-theme img {
margin: 0;
}
2 changes: 0 additions & 2 deletions apps/landing-page/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { Metadata } from 'next'
import { Header } from 'components/common/Header/Header'
import { Footer } from 'components/common/Footer'
import { Providers } from './providers'
import { EndCta } from '@/components/Homepage/EndCta'
import 'assets/style.css'

export const metadata: Metadata = {
Expand Down Expand Up @@ -33,7 +32,6 @@ export default function RootLayout({
<Providers>
<Header />
{children}
<EndCta />
<Footer />
</Providers>
</body>
Expand Down
6 changes: 6 additions & 0 deletions apps/landing-page/assets/prose.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@
--sh-keyword: #f47067;
--sh-comment: #a19595;
}

.prose > * {
max-width: 65ch;
margin-left: auto;
margin-right: auto;
}
16 changes: 12 additions & 4 deletions apps/landing-page/components/Homepage/EndCta.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
'use client'

import { Heading, Button, Text, Flex, VStack } from '@chakra-ui/react'
import {
Heading,
Button,
Text,
Flex,
VStack,
StackProps,
} from '@chakra-ui/react'
import Link from 'next/link'
import React from 'react'
import { BackgroundPolygons } from './Hero/BackgroundPolygons'

export const EndCta = () => {
export const EndCta = (props: StackProps) => {
return (
<VStack
as="section"
Expand All @@ -14,6 +21,7 @@ export const EndCta = () => {
bgGradient="linear(to-b, gray.900, gray.800)"
height="100vh"
justifyContent="center"
{...props}
>
<BackgroundPolygons />
<VStack
Expand All @@ -29,7 +37,7 @@ export const EndCta = () => {
letterSpacing="tight"
data-aos="fade-up"
>
Take your forms to the next level
Improve conversion and user engagement with typebots
</Heading>
<Flex>
<Button
Expand All @@ -46,7 +54,7 @@ export const EndCta = () => {
</Flex>

<Text color="gray.400" data-aos="fade-up" data-aos-delay="400">
No trial. Generous, unlimited <strong>free</strong> plan.
No trial. Generous <strong>free</strong> plan.
</Text>
</VStack>
</VStack>
Expand Down
16 changes: 14 additions & 2 deletions apps/landing-page/content/example.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ title: 'Blog post example'
summary: 'A short summary of the blog post.'
---

This is a blog post example.
<Image src="/images/builder-screenshot.png" alt="awesome image" />

This can be deleted once we published the first blog post.
<Callout rounded='md'>

This is a callout. It can be used to highlight important information.

</Callout>

<Tweet id="1780513200565285038" />

Occaecat nostrud fugiat aliqua non deserunt ad adipisicing amet anim do commodo aliquip ipsum esse. Aute nisi voluptate nisi excepteur nulla velit incididunt aute laborum culpa Lorem magna reprehenderit. Aliqua cupidatat nisi ut nisi. Cillum irure enim officia aute nulla. Sunt culpa deserunt sunt. Laborum ipsum ad proident cillum officia culpa enim do id quis eiusmod.

<Cta />

Occaecat nostrud fugiat aliqua non deserunt ad adipisicing amet anim do commodo aliquip ipsum esse. Aute nisi voluptate nisi excepteur nulla velit incididunt aute laborum culpa Lorem magna reprehenderit. Aliqua cupidatat nisi ut nisi. Cillum irure enim officia aute nulla. Sunt culpa deserunt sunt. Laborum ipsum ad proident cillum officia culpa enim do id quis eiusmod.
1 change: 1 addition & 0 deletions apps/landing-page/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"next-mdx-remote": "4.4.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-tweet": "3.2.1",
"sugar-high": "0.6.0"
},
"devDependencies": {
Expand Down

0 comments on commit eb2001c

Please sign in to comment.