Skip to content

CCIP overview card #2244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions src/assets/role-icons/concepts-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/role-icons/dapp-dev-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/assets/role-icons/frontend-dev-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/role-icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import conceptsIcon from "./concepts-icon.svg"
import dappDevIcon from "./dapp-dev-icon.svg"
import tokenDevIcon from "./token-dev-icon.svg"
import referenceIcon from "./reference-icon.svg"
import quickstartIcon from "./quickstart-icon.svg"
import frontendDevIcon from "./frontend-dev-icon.svg"

export const roleIconMap: Record<string, string> = {
concepts: conceptsIcon.src,
dappDev: dappDevIcon.src,
tokenDev: tokenDevIcon.src,
reference: referenceIcon.src,
quickstart: quickstartIcon.src,
frontendDev: frontendDevIcon.src,
}
5 changes: 5 additions & 0 deletions src/assets/role-icons/quickstart-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/role-icons/reference-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions src/assets/role-icons/token-dev-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 21 additions & 15 deletions src/components/CCIP/Chain/Chain.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
import CcipLayout from "~/layouts/CcipLayout.astro"
import { getEntry } from "astro:content"
import {
Environment,
getAllNetworkLanes,
@@ -12,14 +11,28 @@ import {
import ChainHero from "~/components/CCIP/ChainHero/ChainHero"
import ChainTable from "~/components/CCIP/Tables/ChainTable"
import { getTokenIconUrl } from "~/features/utils"
import Drawer from "../Drawer/Drawer"
import ChainTokenGrid from "./ChainTokenGrid"
import { BaseFrontmatter } from "~/content/config"

const { environment, network } = Astro.props

// Define frontmatter and headings directly
const frontmatter: BaseFrontmatter = {
title: `CCIP Supported Networks - ${network.name}`,
section: "ccip" as const,
metadata: {
description: `View supported tokens and lanes for ${network.name} on Chainlink CCIP.`,
},
}

const headings = [
{
depth: 1,
slug: "overview",
text: frontmatter.title,
},
]

// TODO: Add type for network
const { environment, network } = Astro.props as { environment: Environment; network: any }

const entry = await getEntry("ccip", "index")
const { headings } = await entry.render()
const networks = getAllNetworks({ filter: environment })

const allTokens = getTokensOfChain({
@@ -46,14 +59,7 @@ const lanes = await getAllNetworkLanes({
const searchLanes = getSearchLanes({ environment })
---

<CcipLayout
frontmatter={{
title: `CCIP Supported Networks - ${network.name}`,
section: "ccip",
}}
{headings}
environment={environment}
>
<CcipLayout frontmatter={frontmatter} {headings} environment={environment}>
<ChainHero
chains={networks}
tokens={allTokens}
23 changes: 19 additions & 4 deletions src/components/CCIP/Landing/ccip-landing.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
import CcipLayout from "~/layouts/CcipLayout.astro"
import { getEntry } from "astro:content"
import Hero from "~/components/CCIP/Hero/Hero"
import {
Environment,
@@ -13,13 +12,29 @@ import {
import { getTokenIconUrl } from "~/features/utils"
import NetworkGrid from "./NetworkGrid"
import TokenGrid from "../TokenGrid/TokenGrid"
import { BaseFrontmatter } from "~/content/config"

export type Props = {
environment: Environment
}
const { environment } = Astro.props as Props

const entry = await getEntry("ccip", "index")
const { headings } = await entry.render()
const frontmatter: BaseFrontmatter = {
title: "CCIP Directory",
section: "ccip" as const,
metadata: {
description: "View all supported networks and tokens on Chainlink CCIP.",
},
}

const headings = [
{
depth: 1,
slug: "overview",
text: frontmatter.title,
},
]

const networks = getAllNetworks({ filter: environment })
const supportedTokens = getAllSupportedTokens({
environment: environment,
@@ -40,7 +55,7 @@ const allTokens = tokens.map((token) => {
const searchLanes = getSearchLanes({ environment })
---

<CcipLayout frontmatter={entry.data} {headings} environment={environment}>
<CcipLayout frontmatter={frontmatter} {headings} environment={environment}>
<Hero chains={networks} tokens={allTokens} environment={environment} client:load lanes={searchLanes} />
<section class="layout">
<div>
29 changes: 17 additions & 12 deletions src/components/CCIP/Token/Token.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
import CcipLayout from "~/layouts/CcipLayout.astro"
import { getEntry } from "astro:content"
import {
getAllNetworks,
getAllSupportedTokens,
@@ -14,12 +13,25 @@ import {
import ChainHero from "~/components/CCIP/ChainHero/ChainHero"
import Table from "~/components/CCIP/Tables/TokenChainsTable"
import { directoryToSupportedChain, getChainIcon, getExplorer, getTitle, getTokenIconUrl } from "~/features/utils"
import Drawer from "~/components/CCIP/Drawer/Drawer"

const { token, logo, environment } = Astro.props as { token: string; logo: string; environment: Environment }

const entry = await getEntry("ccip", "index")
const { headings } = await entry.render()
const frontmatter = {
title: `CCIP Supported Tokens - ${token}`,
section: "ccip" as const,
metadata: {
description: `View supported blockchains and configurations for ${token} token on Chainlink CCIP.`,
},
}

const headings = [
{
depth: 1,
slug: "overview",
text: frontmatter.title,
},
]

const networks = getAllNetworks({ filter: environment })

const supportedTokens = getAllSupportedTokens({
@@ -56,14 +68,7 @@ const tokenLanes = getAllTokenLanes({
const searchLanes = getSearchLanes({ environment })
---

<CcipLayout
frontmatter={{
title: `CCIP Supported Tokens - ${token}`,
section: "ccip",
}}
{headings}
environment={environment}
>
<CcipLayout frontmatter={frontmatter} {headings} environment={environment}>
<ChainHero
chains={networks}
tokens={allTokens}
112 changes: 112 additions & 0 deletions src/config/roles/ccip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import type { ProductRoles } from "./types"

export const ccipRoles: ProductRoles = {
productId: "ccip",
roles: [
{
id: "overview",
title: "Concepts",
description: "Learn about CCIP and its core concepts",
iconType: "concepts",
links: [
{ type: "overview", title: "About CCIP", url: "/ccip/about" },
{ type: "concept", title: "Core Concepts", url: "/ccip/concepts" },
{ type: "concept", title: "Architecture", url: "/ccip/architecture" },
{ type: "concept", title: "Execution Latency", url: "/ccip/concepts/ccip-execution-latency" },
{ type: "concept", title: "Cross-Chain Tokens", url: "/ccip/concepts/cross-chain-tokens" },
{ type: "concept", title: "Manual Execution", url: "/ccip/concepts/manual-execution" },
{ type: "concept", title: "Billing", url: "/ccip/billing" },
],
},
{
id: "getting-started",
title: "Get Started",
description: "Start building with CCIP",
iconType: "quickstart",
links: [
{ type: "get-started", title: "Getting Started Guide", url: "/ccip/getting-started" },
{ type: "guide", title: "Acquire Test Tokens", url: "/ccip/test-tokens" },
{ type: "guide", title: "Transfer Tokens from Contract", url: "/ccip/tutorials/transfer-tokens-from-contract" },
{ type: "guide", title: "Transfer Tokens (EOA)", url: "/ccip/tutorials/transfer-tokens-from-eoa" },
{ type: "guide", title: "Send Arbitrary Data", url: "/ccip/tutorials/send-arbitrary-data" },
{ type: "reference", title: "CCIP Directory", url: "/ccip/directory" },
{ type: "reference", title: "CCIP Explorer", url: "https://ccip.chain.link" },
],
},
{
id: "token-dev",
title: "You are a Token Developer",
description: "Leverage the Cross-Chain Token (CCT) Standard to register and manage tokens on CCIP",
iconType: "tokenDev",
links: [
{ type: "concept", title: "Understanding Cross-Chain Tokens", url: "/ccip/concepts/cross-chain-tokens" },
{
type: "guide",
title: "Cross-Chain Token (CCT) guides",
url: "/ccip/tutorials/cross-chain-tokens",
},
{ type: "guide", title: "Transfer Tokens from Contract", url: "/ccip/tutorials/transfer-tokens-from-contract" },
{ type: "guide", title: "Transfer Tokens (EOA)", url: "/ccip/tutorials/transfer-tokens-from-eoa" },
{ type: "reference", title: "CCIP Directory", url: "/ccip/directory" },
{ type: "reference", title: "Service Responsibility", url: "/ccip/service-responsibility" },
{ type: "reference", title: "API Reference", url: "/ccip/api-reference" },
{ type: "reference", title: "Best Practices", url: "/ccip/best-practices" },
],
},
{
id: "dapp-dev",
title: "You are a dApp Developer",
description: "Build cross-chain applications with CCIP",
iconType: "dappDev",
links: [
{ type: "concept", title: "Manual Execution", url: "/ccip/concepts/manual-execution" },
{ type: "guide", title: "Test CCIP Locally", url: "/ccip/tutorials/test-ccip-locally" },
{ type: "guide", title: "Transfer Tokens with Data", url: "/ccip/tutorials/programmable-token-transfers" },
{
type: "guide",
title: "Transfer Tokens with Data (Defensive Programming)",
url: "/ccip/tutorials/programmable-token-transfers-defensive",
},
{ type: "guide", title: "Handle Receipts", url: "/ccip/tutorials/send-arbitrary-data-receipt-acknowledgment" },
{ type: "guide", title: "USDC Transfers", url: "/ccip/tutorials/usdc" },
{ type: "guide", title: "Manual Execution", url: "/ccip/tutorials/manual-execution" },
{ type: "guide", title: "Gas Limit Configuration", url: "/ccip/tutorials/ccipreceive-gaslimit" },
{ type: "reference", title: "CCIP Directory", url: "/ccip/directory" },
{ type: "reference", title: "CCIP Explorer", url: "https://ccip.chain.link" },
{ type: "reference", title: "Service Responsibility", url: "/ccip/service-responsibility" },
{ type: "reference", title: "API Reference", url: "/ccip/api-reference" },
{ type: "reference", title: "Best Practices", url: "/ccip/best-practices" },
],
},
{
id: "frontend-dev",
title: "You are a Frontend Developer",
description: "Build frontend applications that interact with CCIP",
iconType: "frontendDev",
links: [
{ type: "guide", title: "JavaScript SDK", url: "/ccip/ccip-javascript-sdk" },
{ type: "guide", title: "Off-chain Guides", url: "/ccip/tutorials/offchain" },
{ type: "reference", title: "API Reference", url: "/ccip/api-reference" },
{ type: "reference", title: "CCIP Explorer", url: "https://ccip.chain.link" },
{ type: "reference", title: "CCIP Directory", url: "/ccip/directory" },
{ type: "reference", title: "Best Practices", url: "/ccip/best-practices" },
],
},
{
id: "reference",
title: "Reference",
description: "API documentation and technical details",
iconType: "reference",
links: [
{ type: "guide", title: "JavaScript SDK", url: "/ccip/ccip-javascript-sdk" },
{ type: "reference", title: "API Reference", url: "/ccip/api-reference" },
{ type: "reference", title: "CCIP Directory", url: "/ccip/directory" },
{ type: "reference", title: "CCIP Explorer", url: "https://ccip.chain.link" },
{ type: "reference", title: "Service Limits", url: "/ccip/service-limits" },
{ type: "reference", title: "Billing", url: "/ccip/billing" },
{ type: "reference", title: "Service Responsibility", url: "/ccip/service-responsibility" },
{ type: "reference", title: "Release Notes", url: "/ccip/release-notes" },
],
},
],
}
7 changes: 7 additions & 0 deletions src/config/roles/getRolesByProduct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ProductRoles } from "./types"
import { ccipRoles } from "./ccip"

export const PRODUCT_CONFIGS: Record<string, ProductRoles> = {
ccip: ccipRoles,
// Add other products here when they're ready for the role-based layout
}
20 changes: 20 additions & 0 deletions src/config/roles/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export type LinkType = "overview" | "concept" | "get-started" | "guide" | "reference"

export interface RoleLink {
type: LinkType
title: string
url: string
}

export interface RoleConfig {
id: string
title: string
description: string
iconType: string
links: RoleLink[]
}

export interface ProductRoles {
productId: string
roles: RoleConfig[]
}
4 changes: 4 additions & 0 deletions src/config/sidebar.ts
Original file line number Diff line number Diff line change
@@ -971,6 +971,10 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
title: "Overview",
url: "ccip",
},
{
title: "About CCIP",
url: "ccip/about",
},
{
title: "Getting Started",
url: "ccip/getting-started",
3 changes: 2 additions & 1 deletion src/content/ccip/index.mdx → src/content/ccip/about.mdx
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@
section: ccip
date: Last Modified
title: "Chainlink CCIP"
isIndex: true
metadata:
description: "Chainlink CCIP is a secure blockchain interoperability protocol enabling cross-chain token transfers and messaging. Built with defense-in-depth security, it powers Web3 applications across multiple networks with industry-leading oracle infrastructure."
whatsnext:
{
"Complete the Getting Started guide to learn the basics": "/ccip/getting-started",
56 changes: 56 additions & 0 deletions src/features/landing/components/RoleCardGeneric.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from "react"
import type { RoleConfig } from "@config/roles/types"
import { roleIconMap } from "@assets/role-icons"
import styles from "./RoleCards.module.css"

interface RoleCardGenericProps {
role: RoleConfig
}

export const RoleCardGeneric = ({ role }: RoleCardGenericProps) => {
const { title, description, iconType, links } = role

const groupedLinks = links.reduce((acc, link) => {
if (!acc[link.type]) {
acc[link.type] = []
}
acc[link.type].push(link)
return acc
}, {} as Record<string, typeof links>)

return (
<article className={styles.card} role="region" aria-labelledby={`${role.id}-title`}>
<div className={styles.cardInner}>
<header className={styles.cardHeader}>
<div className={styles.iconWrapper}>
{iconType && (
<img src={roleIconMap[iconType]} alt="" className={styles.cardIcon} aria-hidden="true" loading="lazy" />
)}
</div>
<h2 id={`${role.id}-title`} className={styles.cardTitle}>
{title}
</h2>
</header>

<p className={styles.cardDescription}>{description}</p>

<nav className={styles.linkGroups} aria-label={`${title} navigation`}>
{Object.entries(groupedLinks).map(([type, typeLinks]) => (
<div key={type} className={styles.linkGroup}>
<h3 className={styles.linkGroupTitle}>{type.charAt(0).toUpperCase() + type.slice(1)}</h3>
<ul className={styles.linkList} role="list">
{typeLinks.map((link) => (
<li key={link.url}>
<a href={link.url} className={styles.link} onClick={(e) => e.currentTarget.blur()}>
<span className={styles.linkText}>{link.title}</span>
</a>
</li>
))}
</ul>
</div>
))}
</nav>
</div>
</article>
)
}
247 changes: 247 additions & 0 deletions src/features/landing/components/RoleCards.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
.rolesSection {
width: 100%;
max-width: var(--doc-content-width);
margin: 0 auto;
padding: var(--space-6x) var(--space-4x);
}

.rolesContainer {
margin: 0 auto;
width: 100%;
}

.cardGrid {
display: grid;
gap: var(--space-6x);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
max-width: 1200px;
margin: 0 auto;
align-items: start;
}

.card {
position: relative;
border-radius: 12px;
background: var(--color-background);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
height: 480px;
border: 1px solid var(--Card-Border, #e4e8ed);
background-color: var(--color-background, #ffffff);
display: flex;
}

.card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 12px rgba(26, 43, 107, 0.1);
background: var(--Blue-Blue-50, #eff6ff);
}

.cardInner {
padding: var(--space-6x);
display: flex;
flex-direction: column;
gap: var(--space-3x);
flex: 1;
width: 100%;
display: grid;
grid-template-rows: auto auto 1fr;
}

.cardHeader {
display: flex;
align-items: center;
gap: var(--space-4x);
}

.iconWrapper {
flex-shrink: 0;
padding: var(--space-2x);
border-radius: 8px;
background: var(--color-background-secondary);
transition: transform 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
}

.card:hover .iconWrapper {
transform: scale(1.05);
}

.cardIcon {
width: var(--space-8x);
height: var(--space-8x);
display: flex;
}

.cardTitle {
font-size: var(--font-size-xl);
font-weight: 600;
color: var(--color-text-heading);
margin: 0;
line-height: 1.2;
display: flex;
align-items: center;
}

.cardDescription {
color: var(--color-text-secondary);
font-size: var(--font-size-base);
line-height: 1.6;
margin: 0;
height: 4.8em;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
line-clamp: 3;
text-overflow: ellipsis;
opacity: 0.9;
}

.linkGroups {
display: flex;
flex-direction: column;
gap: var(--space-6x);
margin-top: var(--space-6x);
overflow-y: auto;
-webkit-overflow-scrolling: touch;
/* Customize scrollbar for modern browsers */
scrollbar-width: thin;
scrollbar-color: var(--gray-200) transparent;

/* Webkit scrollbar styling */
&::-webkit-scrollbar {
width: 6px;
}

&::-webkit-scrollbar-track {
background: transparent;
}

&::-webkit-scrollbar-thumb {
background-color: var(--gray-200);
border-radius: 3px;
}

&::-webkit-scrollbar-thumb:hover {
background-color: var(--gray-300);
}
@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
}

.linkGroup {
display: flex;
flex-direction: column;
gap: var(--space-2x);
}

.linkGroupTitle {
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--color-text-secondary);
text-transform: capitalize;
margin: 0;
letter-spacing: 0.5px;
}

.linkList {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: var(--space-2x);
}

.link {
color: var(--blue-500);
text-decoration: none;
font-size: var(--font-size-base);
line-height: 1.4;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
padding: var(--space-1x) 0;
position: relative;
font-weight: 500;
}

.linkText {
position: relative;
}

.linkText::after {
content: "";
position: absolute;
bottom: -2px;
left: 0;
width: 100%;
height: 1px;
background: currentColor;
transform: scaleX(0);
transform-origin: right;
transition: transform 0.3s ease;
}

.link:hover .linkText::after,
.link:focus .linkText::after {
transform: scaleX(1);
transform-origin: left;
}

.link:hover {
color: var(--blue-600);
text-decoration: underline;
}

/* Responsive adjustments */
@media (max-width: 1200px) {
.cardGrid {
grid-template-columns: repeat(2, 1fr);
}
}

@media (max-width: 768px) {
.rolesSection {
padding: var(--space-4x) var(--space-2x);
}

.cardGrid {
grid-template-columns: 1fr;
gap: var(--space-4x);
}

.cardInner {
padding: var(--space-4x);
}

.cardTitle {
font-size: var(--font-size-lg);
}
}

/* High contrast mode */
@media (forced-colors: active) {
.card {
border: 2px solid CanvasText;
}

.link:focus {
outline: 2px solid CanvasText;
}
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.card,
.iconWrapper,
.link,
.linkText::after {
transition: none;
}
}
21 changes: 21 additions & 0 deletions src/features/landing/components/RoleCardsGeneric.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.cardGrid {
display: grid;
gap: var(--space-6x);
width: 100%;
}

/* Single column by default */
@media (min-width: 640px) {
.cardGrid {
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--space-4x);
}
}

/* Two columns when there's enough space */
@media (min-width: 1024px) {
.cardGrid {
grid-template-columns: repeat(2, 1fr);
gap: var(--space-6x);
}
}
21 changes: 21 additions & 0 deletions src/features/landing/components/RoleCardsGeneric.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { RoleConfig } from "@config/roles/types"
import { RoleCardGeneric } from "./RoleCardGeneric"
import styles from "./RoleCards.module.css"

interface RoleCardsGenericProps {
roles: RoleConfig[]
}

export const RoleCardsGeneric = ({ roles }: RoleCardsGenericProps) => {
return (
<section className={styles.rolesSection} aria-label="Documentation by Role">
<div className={styles.rolesContainer}>
<div className={styles.cardGrid}>
{roles.map((role) => (
<RoleCardGeneric key={role.id} role={role} />
))}
</div>
</div>
</section>
)
}
16 changes: 11 additions & 5 deletions src/layouts/DocsLayout.astro
Original file line number Diff line number Diff line change
@@ -15,8 +15,10 @@ import { detectApiReference } from "@components/VersionSelector/utils/versions"
interface Props {
frontmatter: BaseFrontmatter
headings?: MarkdownHeading[]
hideRightSidebar?: boolean
hideWhatsNext?: boolean
}
const { frontmatter, headings } = Astro.props
const { frontmatter, headings, hideRightSidebar, hideWhatsNext } = Astro.props
const titleHeading: MarkdownHeading = {
text: frontmatter.title,
@@ -62,11 +64,15 @@ const { isApiReference, product, isVersioned } = detectApiReference(currentPage)
<PageContent {titleHeading}>
<slot />
</PageContent>
{whatsNext && <WhatsNext content={whatsNext} />}
{whatsNext && !hideWhatsNext && <WhatsNext content={whatsNext} />}
</div>
<aside id="grid-right" title="Table of Contents">
<RightSidebar {githubEditUrl} headings={initialHeadings} />
</aside>
{
!hideRightSidebar && (
<aside id="grid-right" title="Table of Contents">
<RightSidebar {githubEditUrl} headings={initialHeadings} />
</aside>
)
}
</div>
</main>

39 changes: 34 additions & 5 deletions src/pages/ccip/index.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
---
import DocsLayout from "~/layouts/DocsLayout.astro"
import { getEntry } from "astro:content"
const entry = await getEntry("ccip", "index")
const { Content, headings } = await entry.render()
import { RoleCardsGeneric } from "~/features/landing/components/RoleCardsGeneric"
import { PRODUCT_CONFIGS } from "~/config/roles/getRolesByProduct"
import type { BaseFrontmatter } from "~/content/config"
// Define frontmatter that was previously in index.mdx
const frontmatter: BaseFrontmatter = {
title: "Chainlink CCIP Documentation",
section: "ccip" as const,
metadata: {
description:
"Learn how to build cross-chain applications with Chainlink CCIP. Transfer tokens and/or data between blockchain networks securely and reliably.",
},
isIndex: true,
}
// Create headings array starting with the main title
const titleHeading = {
text: frontmatter.title,
slug: "overview",
depth: 1,
}
const headings = [titleHeading]
const productRoles = PRODUCT_CONFIGS.ccip
---

<DocsLayout frontmatter={entry.data} {headings}>
<Content />
<DocsLayout frontmatter={frontmatter} {headings} hideRightSidebar={true} hideWhatsNext={true}>
{productRoles && <RoleCardsGeneric roles={productRoles.roles} />}
</DocsLayout>

<style>
:global(#grid-main) {
max-width: var(--doc-content-width);
margin: 0 auto;
}
</style>
4 changes: 4 additions & 0 deletions src/types/svg.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module "*.svg" {
const content: string
export default content
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -30,7 +30,8 @@
"@utils": ["src/utils/"],
"@utils/*": ["src/utils/*"],
"@variables": ["src/config/markdown-variables.ts"],
"@abi": ["src/features/abi/index.ts"]
"@abi": ["src/features/abi/index.ts"],
"@assets/role-icons": ["src/assets/role-icons/index"]
},
"strictNullChecks": true,
"verbatimModuleSyntax": false