There are some nifty MDX components available for use in Markdown content. Because these components are included globally, you don't need to do anything special to use them (like renaming .md
to .mdx
or manually importing them at the top of the file).
Product screenshots
The <ProductScreenshot />
component encapsulates an image with a border and background. It's useful since the app's background matches the website background, and without using this component, it can be hard to differentiate between the screenshot and normal page content. (See an example of this component in action.)
It supports dark mode screenshots (optional). Here's how to use it:
Import the image(s) at the top of the post (directly following the MDX file's frontmatter and dashes):
---export const ImgSampleConfigLight = "https://res.cloudinary.com/dmukukwp6/image/upload/posthog.com/contents/handbook/images/tutorials/limit-session-recordings/sampling-config-light.png"export const ImgSampleConfigDark = "https://res.cloudinary.com/dmukukwp6/image/upload/posthog.com/contents/handbook/images/tutorials/limit-session-recordings/sampling-config-dark.png"Use the component wherever you want the image to appear.
<ProductScreenshotimageLight={ImgSampleConfigLight}imageDark={ImgSampleConfigDark}alt="Sampling config shown set to 100% i.e. no sampling"classes="rounded"/>Optionally pass
zoom={false}
if you don't want the image to be zoomable, otherwise it will be zoomable by default.Note: If you don't have a dark image, just leave out the
imageDark
prop and the light screenshot will be used for both color modes.
Product videos
Th <ProductVideo />
component works the same as product screenshots (above) but supports light and dark videos.
Import the video(s) at the top of the post (directly following the MDX file's frontmatter and dashes):
---export const NewFunnelLight = "https://res.cloudinary.com/dmukukwp6/video/upload/posthog.com/contents/handbook/images/docs/user-guides/funnels/new-funnel.mp4"export const NewFunnelDark = "https://res.cloudinary.com/dmukukwp6/video/upload/posthog.com/contents/handbook/images/docs/user-guides/funnels/new-funnel-dark.mp4"Use the component wherever you want the video(s) to appear.
<ProductVideovideoLight={NewFunnelLight}videoDark={NewFunnelDark}classes="rounded"/>Note: If you don't have a dark video, just leave out the
videoDark
prop and the light video will be used for both color modes.
Codeblocks
The PostHog website has a custom codeblock component that comes with a number of useful features built-in:
Basic codeblock
Codeblocks in PostHog are created by enclosing your snippet using three backticks (```) or three tildes (~~~), as shown below:
```{"name": "Max, Hedgehog in Residence","age": 2}```
This will produce the following codeblock:
{"name": "Max, Hedgehog in Residence","age": 2}
Adding syntax highlighting
Syntax highlighting can be added by specifying a language for the codeblock, which is done by appending the name of the language directly after the opening backticks or tildes as shown below.
```json{"name": "Max, Hedgehog in Residence","age": 2}```
This will produce the following output:
{"name": "Max, Hedgehog in Residence","age": 2}
Supported languages
Here is a list of all the languages that are supported in codeblocks:
Frontend
HTML | html |
CSS / SCSS / LESS | css / less |
JavaScript | js |
JSX | jsx |
TypeScript | ts |
TSX | tsx |
Swift | swift |
Dart | dart |
Objective-C | objectivec |
Backend
Node.js | node |
Elixir | elixir |
Golang | go |
Java | java |
PHP | php |
Ruby | ruby |
Python | python |
C / C++ | c / cpp |
Misc.
Terminal | bash or shell |
JSON | json |
XML | xml |
SQL | sql |
GraphQL | graphql |
Markdown | markdown |
MDX | mdx |
YAML | yaml |
Git | git |
Note: If you want syntax highlighting for a snippet in another language, feel free to add your language to the imports here and open a PR.
Multiple code snippets in one block
With PostHog's MultiLanguage
component, it's possible to group multiple code snippets together into a single block.
<MultiLanguage>```jsconsole.log("Hello world!")``````html<div>Hello world!</div>```</MultiLanguage>
Note: Make sure to include empty lines between all your code snippets, as well as above and below the
MultiLanguage
tag
This will render the following codeblock:
console.log("Hello world!")
Specifying which file a snippet is from
You can specify a filename that a code snippet belongs to using the file
parameter, which will be displayed in the top bar of the block.
```yaml file=values.yamlcloud: 'aws'ingress:hostname: <your-hostname>nginx:enabled: truecert-manager:enabled: true```
Note: Make sure not to surround your filename in quotes. Each parameter-value pair is delimited by spaces.
This produces the following codeblock:
cloud: 'aws'ingress:hostname: <your-hostname>nginx:enabled: truecert-manager:enabled: true
Links
Linking internally
Use Markdown's standard syntax for linking internally.
[Link text](/absolute-path/to/url)
Be sure to use relative links (exclude https://posthog.com
) with absolute paths (reference the root of the domain with a preceding /
).
Correct syntax | /absolute-path/to/url |
Incorrect syntax | https://posthog.com/absolute-path/to/url |
Linking externally
The <Link />
component is used throughout the site, and is accessible within Markdown. (When used internally, it takes advantage of Gatsby's <Link />
features like prefetching and client-side navigation between routes).
While that doesn't apply here, using it comes with some handy parameters that you can see in action via the link above:
- Add
external
to a) open the link in a new tab, and b) add the external link icon (for UX best practices if forcing a link to open in a new window) - If, for some reason, you need to hide the icon, use
externalNoIcon
instead
Example:
<Link to="#" external>click here</Link>
Private links
Sometimes we link to confidential information in our handbook. Since the handbook is public, it's useful to indicate when a link is private so visitors aren't confused as to why they can't access a URL. Use the <PrivateLink />
component for this. (Here's an example.)
<PrivateLink url="https://path/to/private/link">click here</PrivateLink>
Private links will always open in a new tab.
Mention a team member
Use this component to mention a team member in a post. It will link to their community profile and appears like this: Cory Watilo
<TeamMember name="Cory Watilo" />
There's also a photo
parameter which will inline their photo next to their name like this: Cory WatiloCory Watilo
Embedded posts
You can embed what looks like a Tweet an X post using the <Tweet>
component. It's used on the terms and privacy policy pages, but was componentized for use in blog posts to break up bullet points at the top of the post.
Note: This does not actually embed an X post; it's just styled to look like one.
Here's what a post looks like. It's designed to have a familiar look that makes it easy to scan.
If you show multiple posts in a row, they'll be connected by a vertical line to make it look like a thread.
Usage
Be sure to change the alert message which appears if you click one of the action buttons (reply, repost, like).
<TweetclassName="mx-auto"alertMessage="Gen Z? Don't get distracted. You're here to read our exciting embedded post component.">If you show multiple posts in a row, they'll be connected by a vertical line to make it look like a thread.</Tweet>
You can optionally center the post with the mx-auto
class (shown in the example code, but not used in the preview above).