fix: code blocks rendering + consistent styling with ciphera-website /learn
- Convert MDX CodeBlock components to standard markdown code fences - Add rehype-mdx-code-props to pass filename meta to code components - Custom pre/code MDX components map fences to CodeBlock - Add brand color badges (product + category) matching /learn layout - Match prose styling: orange inline code, orange links, white strong - Remove brand color background glow (not in /learn)
This commit is contained in:
@@ -10,14 +10,34 @@ import type { Metadata } from 'next'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import rehypeMdxCodeProps from 'rehype-mdx-code-props'
|
||||
import { CodeBlock } from '@ciphera-net/ui'
|
||||
import { integrations, getIntegration } from '@/lib/integrations'
|
||||
import { getIntegrationGuide } from '@/lib/integration-content'
|
||||
import { IntegrationGuide } from '@/components/IntegrationGuide'
|
||||
|
||||
// * ─── MDX Components ────────────────────────────────────────────
|
||||
// Maps markdown code fences to CodeBlock. The `filename` meta is passed
|
||||
// as a prop via rehype-mdx-code-props (e.g. ```tsx filename="app.tsx").
|
||||
const mdxComponents = {
|
||||
CodeBlock,
|
||||
pre: ({ children }: { children: React.ReactNode }) => children,
|
||||
code: ({ children, className, filename, ...props }: {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
filename?: string
|
||||
[key: string]: unknown
|
||||
}) => {
|
||||
// Block code (inside <pre>) has className like "language-tsx"
|
||||
if (className?.startsWith('language-') || filename) {
|
||||
return (
|
||||
<CodeBlock filename={filename || 'code'}>
|
||||
{String(children).replace(/\n$/, '')}
|
||||
</CodeBlock>
|
||||
)
|
||||
}
|
||||
// Inline code
|
||||
return <code className={className} {...props}>{children}</code>
|
||||
},
|
||||
}
|
||||
|
||||
// * ─── Static Params ─────────────────────────────────────────────
|
||||
@@ -115,7 +135,7 @@ export default async function IntegrationPage({ params }: PageProps) {
|
||||
<MDXRemote
|
||||
source={guide.content}
|
||||
components={mdxComponents}
|
||||
options={{ mdxOptions: { remarkPlugins: [remarkGfm] } }}
|
||||
options={{ mdxOptions: { remarkPlugins: [remarkGfm], rehypePlugins: [rehypeMdxCodeProps] } }}
|
||||
/>
|
||||
</IntegrationGuide>
|
||||
</>
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
* @file Shared layout component for individual integration guide pages.
|
||||
*
|
||||
* Provides the background atmosphere, back-link, header (logo + title),
|
||||
* prose-styled content area, and a related integrations section.
|
||||
* category badge, prose-styled content area, and a related integrations section.
|
||||
* Styling matches ciphera-website /learn article layout for consistency.
|
||||
*/
|
||||
|
||||
import Link from 'next/link'
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from '@ciphera-net/ui'
|
||||
import { type ReactNode } from 'react'
|
||||
import { type Integration, getIntegration } from '@/lib/integrations'
|
||||
import { type Integration, getIntegration, categoryLabels } from '@/lib/integrations'
|
||||
|
||||
interface IntegrationGuideProps {
|
||||
/** Integration metadata (name, icon, etc.) */
|
||||
@@ -35,6 +36,8 @@ export function IntegrationGuide({ integration, children }: IntegrationGuideProp
|
||||
.filter((i): i is Integration => i !== undefined)
|
||||
.slice(0, 4)
|
||||
|
||||
const categoryLabel = categoryLabels[integration.category]
|
||||
|
||||
return (
|
||||
<div className="relative min-h-screen flex flex-col overflow-hidden">
|
||||
{/* * --- ATMOSPHERE (Background) --- */}
|
||||
@@ -47,6 +50,7 @@ export function IntegrationGuide({ integration, children }: IntegrationGuideProp
|
||||
</div>
|
||||
|
||||
<div className="flex-grow w-full max-w-4xl mx-auto px-4 pt-20 pb-10 z-10">
|
||||
{/* * --- Back link --- */}
|
||||
<Link
|
||||
href="/integrations"
|
||||
className="inline-flex items-center text-sm text-neutral-500 hover:text-brand-orange mb-8 transition-colors"
|
||||
@@ -55,16 +59,31 @@ export function IntegrationGuide({ integration, children }: IntegrationGuideProp
|
||||
Back to Integrations
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-4 mb-8">
|
||||
<div className="p-3 bg-neutral-800 rounded-xl">
|
||||
{headerIcon}
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-white">
|
||||
{integration.name} Integration
|
||||
</h1>
|
||||
{/* * --- Category + Official site badges --- */}
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<span
|
||||
className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-medium border"
|
||||
style={{
|
||||
color: integration.brandColor,
|
||||
borderColor: `${integration.brandColor}33`,
|
||||
backgroundColor: `${integration.brandColor}15`,
|
||||
}}
|
||||
>
|
||||
<div className="[&_svg]:w-3.5 [&_svg]:h-3.5">{integration.icon}</div>
|
||||
{integration.name}
|
||||
</span>
|
||||
<span className="inline-flex items-center px-3 py-1 rounded-full border border-neutral-700 bg-neutral-800 text-xs text-neutral-400">
|
||||
{categoryLabel}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="prose prose-invert max-w-none">
|
||||
{/* * --- Title --- */}
|
||||
<h1 className="text-3xl sm:text-4xl font-bold text-white leading-tight mb-8">
|
||||
{integration.name} Integration
|
||||
</h1>
|
||||
|
||||
{/* * --- Prose content (matches ciphera-website /learn styling) --- */}
|
||||
<div className="prose prose-invert prose-neutral max-w-none prose-headings:text-white prose-a:text-brand-orange prose-a:no-underline hover:prose-a:underline prose-strong:text-white prose-code:text-brand-orange prose-code:bg-neutral-800 prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:before:content-none prose-code:after:content-none">
|
||||
{children}
|
||||
|
||||
<hr className="my-8 border-neutral-800" />
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the script to your `src/index.html` — the single entry point for all Angul
|
||||
|
||||
Place the Pulse script inside the `<head>` tag of your Angular app's `src/index.html`.
|
||||
|
||||
<CodeBlock filename="src/index.html">{`<!doctype html>
|
||||
```html filename="src/index.html"
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@@ -34,6 +35,7 @@ Place the Pulse script inside the `<head>` tag of your Angular app's `src/index.
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Angular docs](https://angular.dev/guide/components).
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your base layout so it's included on every page of your
|
||||
|
||||
Place the Pulse script in the `<head>` of your shared layout component.
|
||||
|
||||
<CodeBlock filename="src/layouts/BaseLayout.astro">{`---
|
||||
```html filename="src/layouts/BaseLayout.astro"
|
||||
---
|
||||
interface Props {
|
||||
title: string
|
||||
}
|
||||
@@ -41,7 +42,8 @@ const { title } = Astro.props
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
If you're using Astro's View Transitions, the script will persist across navigations by default since it's in the `<head>`.
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your base template with a debug guard.
|
||||
|
||||
Use Django's template tags to only load the script when `DEBUG` is `False`.
|
||||
|
||||
<CodeBlock filename="templates/base.html">{`<!DOCTYPE html>
|
||||
```html filename="templates/base.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -35,7 +36,8 @@ Use Django's template tags to only load the script when `DEBUG` is `False`.
|
||||
<body>
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
Make sure to pass `debug` to the template context via `settings.DEBUG`, or use a context processor to make it available globally.
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ Install the [Asset Injector](https://www.drupal.org/project/asset_injector) modu
|
||||
|
||||
Add the script directly to your theme's `html.html.twig` template in the head area.
|
||||
|
||||
<CodeBlock filename="templates/html.html.twig">{`<!DOCTYPE html>
|
||||
```twig filename="templates/html.html.twig"
|
||||
<!DOCTYPE html>
|
||||
<html{{ html_attributes }}>
|
||||
<head>
|
||||
<head-placeholder token="{{ placeholder_token }}">
|
||||
@@ -40,6 +41,7 @@ Add the script directly to your theme's `html.html.twig` template in the head ar
|
||||
{{ page_bottom }}
|
||||
<js-bottom-placeholder token="{{ placeholder_token }}">
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Drupal theming docs](https://www.drupal.org/docs/theming-drupal).
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your base Nunjucks or Liquid layout.
|
||||
|
||||
Place the Pulse script inside the `<head>` of your shared base template.
|
||||
|
||||
<CodeBlock filename="src/_includes/base.njk">{`<!DOCTYPE html>
|
||||
```html filename="src/_includes/base.njk"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -33,6 +34,7 @@ Place the Pulse script inside the `<head>` of your shared base template.
|
||||
<body>
|
||||
{{ content | safe }}
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Eleventy layouts docs](https://www.11ty.dev/docs/layouts/).
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your template engine's layout (EJS, Pug, Handlebars) or
|
||||
|
||||
If you use EJS as your template engine, add the script to your layout with a production guard.
|
||||
|
||||
<CodeBlock filename="views/layout.ejs">{`<!DOCTYPE html>
|
||||
```html filename="views/layout.ejs"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -35,13 +36,15 @@ If you use EJS as your template engine, add the script to your layout with a pro
|
||||
<body>
|
||||
<%- body %>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Method 2: Static HTML
|
||||
|
||||
If you serve static HTML files via Express, add the script directly.
|
||||
|
||||
<CodeBlock filename="public/index.html">{`<!DOCTYPE html>
|
||||
```html filename="public/index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -58,4 +61,5 @@ If you serve static HTML files via Express, add the script directly.
|
||||
<body>
|
||||
<h1>Hello World</h1>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your Jinja2 base template with a debug guard.
|
||||
|
||||
Use Jinja2's conditional to only load the script when `DEBUG` is off.
|
||||
|
||||
<CodeBlock filename="templates/base.html">{`<!DOCTYPE html>
|
||||
```html filename="templates/base.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -35,6 +36,7 @@ Use Jinja2's conditional to only load the script when `DEBUG` is off.
|
||||
<body>
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Flask template docs](https://flask.palletsprojects.com/en/stable/patterns/templateinheritance/).
|
||||
|
||||
@@ -16,10 +16,12 @@ Add the Pulse script to your Framer project's custom code settings.
|
||||
|
||||
Go to **Project Settings -> General -> Custom Code -> Head** and paste the Pulse script.
|
||||
|
||||
<CodeBlock filename="Project Settings -> Head">{`<script
|
||||
```html filename="Project Settings -> Head"
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
For more details, see the [Framer custom code docs](https://www.framer.com/help/articles/custom-code/).
|
||||
|
||||
@@ -16,7 +16,8 @@ Use the Gatsby SSR API or the Gatsby Head API to add Pulse to your site.
|
||||
|
||||
Use the `onRenderBody` hook to inject the Pulse script into every page's `<head>`.
|
||||
|
||||
<CodeBlock filename="gatsby-ssr.js">{`import React from "react"
|
||||
```jsx filename="gatsby-ssr.js"
|
||||
import React from "react"
|
||||
|
||||
export const onRenderBody = ({ setHeadComponents }) => {
|
||||
setHeadComponents([
|
||||
@@ -27,13 +28,15 @@ export const onRenderBody = ({ setHeadComponents }) => {
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
/>,
|
||||
])
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
## Method 2: Gatsby Head API (v4.19+)
|
||||
|
||||
If you're on Gatsby 4.19 or later, you can use the Head export in any page or template component.
|
||||
|
||||
<CodeBlock filename="src/pages/index.tsx">{`import React from "react"
|
||||
```tsx filename="src/pages/index.tsx"
|
||||
import React from "react"
|
||||
|
||||
export function Head() {
|
||||
return (
|
||||
@@ -47,6 +50,7 @@ export function Head() {
|
||||
|
||||
export default function IndexPage() {
|
||||
return <h1>Hello World</h1>
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
For more details, see the [Gatsby Head API docs](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-head/).
|
||||
|
||||
@@ -16,11 +16,13 @@ Use Ghost's built-in Code Injection feature to add the Pulse script — no theme
|
||||
|
||||
Go to **Settings -> Code injection -> Site Header** and paste the Pulse script.
|
||||
|
||||
<CodeBlock filename="Settings -> Code injection -> Site Header">{`<script
|
||||
```html filename="Settings -> Code injection -> Site Header"
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
Alternatively, you can add the script directly to your theme's `default.hbs` template file.
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ Follow these steps to add Pulse through GTM:
|
||||
3. Set the trigger to **All Pages**
|
||||
4. Publish your container
|
||||
|
||||
<CodeBlock filename="GTM -> Custom HTML Tag">{`<script defer src="https://pulse.ciphera.net/script.js"></script>`}</CodeBlock>
|
||||
```html filename="GTM -> Custom HTML Tag"
|
||||
<script defer src="https://pulse.ciphera.net/script.js"></script>
|
||||
```
|
||||
|
||||
That's it. Pulse auto-detects the domain from the page, so no extra configuration is needed.
|
||||
|
||||
@@ -30,10 +32,12 @@ That's it. Pulse auto-detects the domain from the page, so no extra configuratio
|
||||
|
||||
If your site is registered under a different domain than the page hostname, or you need custom options (API endpoint, storage mode, etc.), use `pulseConfig`:
|
||||
|
||||
<CodeBlock filename="GTM -> Custom HTML Tag (with config)">{`<script>
|
||||
```html filename="GTM -> Custom HTML Tag (with config)"
|
||||
<script>
|
||||
window.pulseConfig = { domain: "your-site.com" };
|
||||
</script>
|
||||
<script defer src="https://pulse.ciphera.net/script.js"></script>`}</CodeBlock>
|
||||
<script defer src="https://pulse.ciphera.net/script.js"></script>
|
||||
```
|
||||
</details>
|
||||
|
||||
For more details, see the [GTM Custom HTML tag docs](https://support.google.com/tagmanager/answer/6103696).
|
||||
|
||||
@@ -16,19 +16,22 @@ Add the Pulse script via a Hugo partial or directly in your base template.
|
||||
|
||||
Create an analytics partial with a production guard using Hugo's `.Site.IsServer` flag.
|
||||
|
||||
<CodeBlock filename="layouts/partials/analytics.html">{`{{ if not .Site.IsServer }}
|
||||
```html filename="layouts/partials/analytics.html"
|
||||
{{ if not .Site.IsServer }}
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>
|
||||
{{ end }}`}</CodeBlock>
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
## Method 2: Include the partial in your base layout
|
||||
|
||||
Add the partial to your `baseof.html` layout.
|
||||
|
||||
<CodeBlock filename="layouts/_default/baseof.html">{`<!DOCTYPE html>
|
||||
```html filename="layouts/_default/baseof.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ .Site.Language }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@@ -39,6 +42,7 @@ Add the partial to your `baseof.html` layout.
|
||||
<body>
|
||||
{{ block "main" . }}{{ end }}
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Hugo partials docs](https://gohugo.io/templates/partials/).
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your Blade layout template with a production guard.
|
||||
|
||||
Use Laravel's `@production` directive to only load the script in production.
|
||||
|
||||
<CodeBlock filename="resources/views/layouts/app.blade.php">{`<!DOCTYPE html>
|
||||
```php filename="resources/views/layouts/app.blade.php"
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@@ -36,6 +37,7 @@ Use Laravel's `@production` directive to only load the script in production.
|
||||
<body>
|
||||
@yield('content')
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Laravel @production docs](https://laravel.com/docs/blade#the-production-directive).
|
||||
|
||||
@@ -16,7 +16,8 @@ The best way to add Pulse to your Next.js application is using the built-in `nex
|
||||
|
||||
Add the Pulse script to your root layout so it loads on every page.
|
||||
|
||||
<CodeBlock filename="app/layout.tsx">{`import Script from 'next/script'
|
||||
```tsx filename="app/layout.tsx"
|
||||
import Script from 'next/script'
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
@@ -36,13 +37,15 @@ export default function RootLayout({
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
## Method 2: Pages Router
|
||||
|
||||
If you're using the Pages Router, add the script to your custom `_app.tsx`.
|
||||
|
||||
<CodeBlock filename="pages/_app.tsx">{`import Script from 'next/script'
|
||||
```tsx filename="pages/_app.tsx"
|
||||
import Script from 'next/script'
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
@@ -57,7 +60,8 @@ export default function App({ Component, pageProps }: AppProps) {
|
||||
<Component {...pageProps} />
|
||||
</>
|
||||
)
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration options
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ Configure Pulse analytics in your `nuxt.config` for a framework-native setup.
|
||||
|
||||
Add the Pulse script via the `app.head` option in your Nuxt 3 config.
|
||||
|
||||
<CodeBlock filename="nuxt.config.ts">{`export default defineNuxtConfig({
|
||||
```tsx filename="nuxt.config.ts"
|
||||
export default defineNuxtConfig({
|
||||
app: {
|
||||
head: {
|
||||
script: [
|
||||
@@ -28,13 +29,15 @@ Add the Pulse script via the `app.head` option in your Nuxt 3 config.
|
||||
],
|
||||
},
|
||||
},
|
||||
})`}</CodeBlock>
|
||||
})
|
||||
```
|
||||
|
||||
## Method 2: Nuxt 2
|
||||
|
||||
In Nuxt 2, use the `head` property in your config.
|
||||
|
||||
<CodeBlock filename="nuxt.config.js">{`export default {
|
||||
```jsx filename="nuxt.config.js"
|
||||
export default {
|
||||
head: {
|
||||
script: [
|
||||
{
|
||||
@@ -44,6 +47,7 @@ In Nuxt 2, use the `head` property in your config.
|
||||
},
|
||||
],
|
||||
},
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
For more details, see the [Nuxt head config docs](https://nuxt.com/docs/api/nuxt-config#head).
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your application layout with a production environment gu
|
||||
|
||||
Use an `if` guard to only load the script in production.
|
||||
|
||||
<CodeBlock filename="app/views/layouts/application.html.erb">{`<!DOCTYPE html>
|
||||
```erb filename="app/views/layouts/application.html.erb"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -37,6 +38,7 @@ Use an `if` guard to only load the script in production.
|
||||
<body>
|
||||
<%= yield %>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
For more details, see the [Rails layout docs](https://guides.rubyonrails.org/layouts_and_rendering.html).
|
||||
|
||||
@@ -16,7 +16,8 @@ For standard React SPAs, add the script to your `index.html`.
|
||||
|
||||
The simplest approach is to add the Pulse script directly to your HTML entry point.
|
||||
|
||||
<CodeBlock filename="public/index.html">{`<!DOCTYPE html>
|
||||
```html filename="public/index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
@@ -33,13 +34,15 @@ The simplest approach is to add the Pulse script directly to your HTML entry poi
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Method 2: Programmatic injection via useEffect
|
||||
|
||||
If you prefer to inject the script programmatically (e.g. only in production), use a `useEffect` hook.
|
||||
|
||||
<CodeBlock filename="src/App.tsx">{`import { useEffect } from 'react'
|
||||
```tsx filename="src/App.tsx"
|
||||
import { useEffect } from 'react'
|
||||
|
||||
function App() {
|
||||
useEffect(() => {
|
||||
@@ -53,4 +56,5 @@ function App() {
|
||||
}, [])
|
||||
|
||||
return <div className="App"><h1>Hello World</h1></div>
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the Pulse script to your `app/root.tsx` so it's included on every route.
|
||||
|
||||
The root route is the top-level layout in Remix. Add the Pulse script inside the `<head>` section.
|
||||
|
||||
<CodeBlock filename="app/root.tsx">{`import {
|
||||
```tsx filename="app/root.tsx"
|
||||
import {
|
||||
Links,
|
||||
Meta,
|
||||
Outlet,
|
||||
@@ -45,6 +46,7 @@ export default function App() {
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}`}</CodeBlock>
|
||||
}
|
||||
```
|
||||
|
||||
For more details, see the [Remix root docs](https://remix.run/docs/en/main/file-conventions/root).
|
||||
|
||||
@@ -16,14 +16,16 @@ Add Pulse to any website by pasting a single script tag into your HTML. This wor
|
||||
|
||||
Add the following script tag inside the `<head>` section of your website:
|
||||
|
||||
<CodeBlock filename="index.html">{`<head>
|
||||
```html filename="index.html"
|
||||
<head>
|
||||
<!-- ... other head elements ... -->
|
||||
<script
|
||||
defer
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
data-domain="your-site.com"
|
||||
></script>
|
||||
</head>`}</CodeBlock>
|
||||
</head>
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@ Add the Pulse script via the Shopify theme editor — no app needed.
|
||||
|
||||
Go to **Online Store -> Themes -> Edit code** and open `layout/theme.liquid`. Add the Pulse script before the closing `</head>` tag.
|
||||
|
||||
<CodeBlock filename="layout/theme.liquid">{`<!-- Add before </head> -->
|
||||
```liquid filename="layout/theme.liquid"
|
||||
<!-- Add before </head> -->
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
## Method 2: Shopify Plus — Customer Events
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@ Use Squarespace's Code Injection feature to add the Pulse script.
|
||||
|
||||
Go to **Settings -> Developer Tools -> Code Injection -> Header** and paste the Pulse script.
|
||||
|
||||
<CodeBlock filename="Settings -> Code Injection -> Header">{`<script
|
||||
```html filename="Settings -> Code Injection -> Header"
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
**Note:** Code Injection requires a Business or Commerce plan.
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the script to your `index.html` for Vite-based Svelte, or use `<svelte:head>
|
||||
|
||||
For standard Svelte projects using Vite, add the Pulse script to your `index.html`.
|
||||
|
||||
<CodeBlock filename="index.html">{`<!DOCTYPE html>
|
||||
```html filename="index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
@@ -34,13 +35,15 @@ For standard Svelte projects using Vite, add the Pulse script to your `index.htm
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Method 2: SvelteKit
|
||||
|
||||
In SvelteKit, use `<svelte:head>` in your root layout to add the script to every page.
|
||||
|
||||
<CodeBlock filename="src/routes/+layout.svelte">{`<svelte:head>
|
||||
```svelte filename="src/routes/+layout.svelte"
|
||||
<svelte:head>
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
@@ -48,6 +51,7 @@ In SvelteKit, use `<svelte:head>` in your root layout to add the script to every
|
||||
></script>
|
||||
</svelte:head>
|
||||
|
||||
<slot />`}</CodeBlock>
|
||||
<slot />
|
||||
```
|
||||
|
||||
Alternatively, you can add the script directly to `src/app.html` in your SvelteKit project.
|
||||
|
||||
@@ -16,7 +16,8 @@ Add the script to your `index.html` — works for both Vue CLI and Vite-based pr
|
||||
|
||||
Both Vue CLI and Vite use an `index.html` as the entry point. Simply add the Pulse script inside the `<head>` tag.
|
||||
|
||||
<CodeBlock filename="index.html">{`<!DOCTYPE html>
|
||||
```html filename="index.html"
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
@@ -34,6 +35,7 @@ Both Vue CLI and Vite use an `index.html` as the entry point. Simply add the Pul
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>`}</CodeBlock>
|
||||
</html>
|
||||
```
|
||||
|
||||
Looking for Nuxt? Check the dedicated [Nuxt guide](/integrations/nuxt).
|
||||
|
||||
@@ -16,11 +16,13 @@ Paste the Pulse script into your Webflow project's custom code settings.
|
||||
|
||||
Go to **Project Settings -> Custom Code -> Head Code** and paste the Pulse script.
|
||||
|
||||
<CodeBlock filename="Project Settings -> Head Code">{`<script
|
||||
```html filename="Project Settings -> Head Code"
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
**Note:** Custom code requires a paid Webflow site plan. The script won't appear in the Designer preview — publish your site to see it in action.
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@ Use Wix's Custom Code settings to add the Pulse script.
|
||||
|
||||
Go to **Settings -> Custom Code -> Add Custom Code**. Set the placement to **Head** and apply it to **All pages**.
|
||||
|
||||
<CodeBlock filename="Custom Code Snippet">{`<script
|
||||
```html filename="Custom Code Snippet"
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
**Note:** Custom Code requires a Wix Premium plan.
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@ Add the Pulse script via a plugin or by editing your theme's header file directl
|
||||
|
||||
The easiest way is to use the [WPCode (Insert Headers and Footers)](https://wordpress.org/plugins/insert-headers-and-footers/) plugin. Install it, then go to **Code Snippets -> Header & Footer** and paste the Pulse script into the Header section.
|
||||
|
||||
<CodeBlock filename="Header Script">{`<script
|
||||
```html filename="Header Script"
|
||||
<script
|
||||
defer
|
||||
data-domain="your-site.com"
|
||||
src="https://pulse.ciphera.net/script.js"
|
||||
></script>`}</CodeBlock>
|
||||
></script>
|
||||
```
|
||||
|
||||
## Method 2: Edit header.php directly
|
||||
|
||||
|
||||
48
package-lock.json
generated
48
package-lock.json
generated
@@ -47,6 +47,7 @@
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-use-measure": "^2.1.7",
|
||||
"recharts": "^2.15.0",
|
||||
"rehype-mdx-code-props": "^3.0.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"sonner": "^2.0.7",
|
||||
"svg-dotted-map": "^2.0.1",
|
||||
@@ -9918,6 +9919,18 @@
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-util-value-to-estree": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.5.0.tgz",
|
||||
"integrity": "sha512-aMV56R27Gv3QmfmF1MY12GWkGzzeAezAX+UplqHVASfjc9wNzI/X6hC0S9oxq61WT4aQesLGslWP9tKk6ghRZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/remcohaszing"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-util-visit": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz",
|
||||
@@ -10616,6 +10629,23 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/hast-util-properties-to-mdx-jsx-attributes": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/hast-util-properties-to-mdx-jsx-attributes/-/hast-util-properties-to-mdx-jsx-attributes-1.1.1.tgz",
|
||||
"integrity": "sha512-MMrAoGgvhYULEqMB/r6AlcVz1D3Cyml/9cMB2NIqZsIsEJ+XEXPMqH0gjba8dVs9AnQUYvPReAS+OIYx4ip+Ug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"@types/hast": "^3.0.0",
|
||||
"estree-util-value-to-estree": "^3.0.0",
|
||||
"mdast-util-mdx-jsx": "^3.0.0",
|
||||
"property-information": "^7.0.0",
|
||||
"style-to-js": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/remcohaszing"
|
||||
}
|
||||
},
|
||||
"node_modules/hast-util-to-estree": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz",
|
||||
@@ -14383,6 +14413,24 @@
|
||||
"regjsparser": "bin/parser"
|
||||
}
|
||||
},
|
||||
"node_modules/rehype-mdx-code-props": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rehype-mdx-code-props/-/rehype-mdx-code-props-3.0.1.tgz",
|
||||
"integrity": "sha512-BWWKn0N6r7/qd7lbLgv5J8of7imz1l1PyCNoY7BH0AOR9JdJlQIfA9cKqTZVEb2h2GPKh473qrBajF0i01fq3A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/hast": "^3.0.0",
|
||||
"hast-util-properties-to-mdx-jsx-attributes": "^1.0.0",
|
||||
"mdast-util-from-markdown": "^2.0.0",
|
||||
"mdast-util-mdx": "^3.0.0",
|
||||
"micromark-extension-mdxjs": "^3.0.0",
|
||||
"unified": "^11.0.0",
|
||||
"unist-util-visit-parents": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/remcohaszing"
|
||||
}
|
||||
},
|
||||
"node_modules/rehype-recma": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-use-measure": "^2.1.7",
|
||||
"recharts": "^2.15.0",
|
||||
"rehype-mdx-code-props": "^3.0.1",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"sonner": "^2.0.7",
|
||||
"svg-dotted-map": "^2.0.1",
|
||||
|
||||
Reference in New Issue
Block a user