diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6cefd4127d..eaf4852f93f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -209,8 +209,9 @@ jobs: NODE_OPTIONS: '--max-old-space-size=8192' - name: Check Internal Links - uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0 + uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0 with: + lycheeVersion: v0.24.2 args: >- --root-dir $GITHUB_WORKSPACE/.vercel/output/static --config lychee.toml diff --git a/lychee.toml b/lychee.toml index 88c2d5701bd..e3c1d3016b5 100644 --- a/lychee.toml +++ b/lychee.toml @@ -1,44 +1,68 @@ # Lychee Link Checker Configuration # https://lychee.cli.rs/ -# Only check local files (no network requests) +# Check only local build files; never make network requests. offline = true -# Check links in code blocks -include_verbatim = true +# Ignore illustrative URLs inside ,
, and Markdown code blocks.
+# These are examples, not navigational links that users can click.
+include_verbatim = false
 
-# Don't show progress bar (better for CI)
+# Validate standard anchors such as /page#section.
+# Text fragments such as #:~:text=... remain out of scope.
+include_fragments = "anchor-only"
+
+# Resolve Astro pretty URLs to their generated index.html file.
+# Do not add "." as a fallback: directories without index.html must remain errors.
+index_files = ["index.html"]
+
+# Disable the interactive progress bar in CI logs.
 no_progress = true
 
-# Patterns to exclude from link checking
+# URLs matching these patterns are not checked.
 exclude = [
-    # Markdown alternates emitted into built HTML
+    # Markdown alternatives emitted into built HTML are not part of the static site.
     '.*\.md$',
 
-    # CSS files
+    # Generated CSS assets are outside the scope of the internal navigation check.
     'assets/.*\.css$',
     '_astro/.*\.css$',
 
-    # Dynamic pages with query params
-    '/ccip/directory/.*',
+    # Astro handles this exact route as a redirect to /ccip/directory/mainnet,
+    # so no local index.html is generated for it.
+    '/ccip/directory/?(?:[?#].*)?$',
+
+    # CCIP Directory pages reuse headings that are not rendered on those pages.
+    # Ignore only their fragments; the existence of each target page is still checked.
+    '/ccip/directory/.*#.*$',
+
+    # Ignore only query-dependent CCIP Directory URLs.
+    # Child pages without query parameters remain fully checked.
+    '/ccip/directory/.+\?.*',
+
+    # Dynamic pages whose query parameters cannot be reproduced by the static build.
     '/data-feeds/price-feeds/addresses\?.*',
     '/data-feeds/smartdata/addresses\?.*',
 
-    # Other files
+    # Swagger UI creates this deep-link target client-side.
+    '/api/ace/coordinator/docs#/Organizations$',
+
+    # In offline mode, href="/" can resolve to file:/// even though the root page
+    # exists in the deployed site. Match only this exact local URL.
+    '^file:///$',
+
+    # Build/runtime references that are not navigational pages.
     'sitemap-index\.xml',
     '@vite/client',
 
-    # Database connection strings
+    # Connection strings found in documentation examples.
     'postgresql:',
     'mysql:',
 ]
 
-# Paths to exclude from scanning (won't check links on these pages)
+# Input HTML files matching these patterns are not scanned.
+# Use this only when the entire generated page is intentionally out of scope.
 exclude_path = [
     'ccip/api-reference/evm/v162/.*',
     'ccip/api-reference/evm/v163/.*',
-]
-
-# TODO: Re-enable fragment checking once Astro slug generation compatibility is resolved
-# include_fragments = true
-# Astro's heading ID generation and lychee's GitHub-style kebab-case expectations
\ No newline at end of file
+]
\ No newline at end of file
diff --git a/public/ccip/llms.txt b/public/ccip/llms.txt
index 7b440c30fcd..f872d35d8c7 100644
--- a/public/ccip/llms.txt
+++ b/public/ccip/llms.txt
@@ -44,14 +44,14 @@ Use directory pages only when retrieving current chain, lane, token, or contract
 - [Best Practices (SVM)](https://docs.chain.link/ccip/concepts/best-practices/svm.md)
 - [Best Practices (TON)](https://docs.chain.link/ccip/concepts/best-practices/ton.md)
 - [Billing](https://docs.chain.link/ccip/billing.md)
-- [Service Limits](https://docs.chain.link/ccip/service-limits.md)
+- [Service Limits](https://docs.chain.link/ccip/evm/service-limits.md)
 - [Test Tokens](https://docs.chain.link/ccip/test-tokens.md)
 
 ## Tools and Reference
 
 On-chain contracts and interfaces:
 
-- [EVM contracts and interfaces reference](https://docs.chain.link/ccip/api-reference.md)
+- [EVM contracts and interfaces reference](https://docs.chain.link/ccip/evm/api-reference/v2.0.0/overview.md)
 - [SVM program interfaces reference](https://docs.chain.link/ccip/api-reference/svm.md)
 - [Aptos Move module interfaces reference](https://docs.chain.link/ccip/api-reference/aptos.md)
 - [TON contract interfaces reference](https://docs.chain.link/ccip/api-reference/ton.md)
diff --git a/src/components/QuickLinks/data/productChainLinks.ts b/src/components/QuickLinks/data/productChainLinks.ts
index 4376e5e06a3..2135648e745 100644
--- a/src/components/QuickLinks/data/productChainLinks.ts
+++ b/src/components/QuickLinks/data/productChainLinks.ts
@@ -105,7 +105,7 @@ export const productChainLinks: ProductChainLinks = {
       dogeos: "/ccip/directory/testnet/chain/dogeos-testnet-chikyu",
       "adi-network": "/ccip/directory/testnet/chain/adi-testnet",
       edge: "/ccip/directory/mainnet/chain/edge-mainnet",
-      robinhood: "/ccip/directory/testnet/chain/robinhood-mainnet",
+      robinhood: "/ccip/directory/mainnet/chain/robinhood-mainnet",
       ton: "/ccip/directory/mainnet/chain/ton-mainnet",
       creditcoin: "/ccip/directory/mainnet/chain/creditcoin-mainnet",
     },
@@ -377,7 +377,7 @@ export const productChainLinks: ProductChainLinks = {
     treasure: "/resources/link-token-contracts#treasure",
     unichain: "/resources/link-token-contracts#unichain",
     wemix: "/resources/link-token-contracts#wemix",
-    worldchain: "/resources/link-token-contracts#world",
+    worldchain: "/resources/link-token-contracts#world-chain",
     xdc: "/resources/link-token-contracts#xdc",
     xlayer: "/resources/link-token-contracts#x-layer",
     zircuit: "/resources/link-token-contracts#zircuit",
diff --git a/src/content/ace/guides/identity-manager/manage-registries.mdx b/src/content/ace/guides/identity-manager/manage-registries.mdx
index 7fb2f0f5982..aafa843359a 100644
--- a/src/content/ace/guides/identity-manager/manage-registries.mdx
+++ b/src/content/ace/guides/identity-manager/manage-registries.mdx
@@ -52,7 +52,7 @@ Each sub-registry corresponds to a smart contract deployed on a specific blockch
       }'
     ```
 
-    When you omit the `address` field, ACE deploys a new managed contract on that chain. To import an existing contract instead, provide its address — see [Import an existing registry](#import-an-existing-registry).
+    When you omit the `address` field, ACE deploys a new managed contract on that chain. To import an existing contract instead, provide its address.
 
     The response includes the registry ID and the status of each sub-registry deployment:
 
diff --git a/src/content/ace/guides/policy-manager/manage-engines.mdx b/src/content/ace/guides/policy-manager/manage-engines.mdx
index 691810d914f..63e47725ac1 100644
--- a/src/content/ace/guides/policy-manager/manage-engines.mdx
+++ b/src/content/ace/guides/policy-manager/manage-engines.mdx
@@ -31,7 +31,7 @@ A **policy engine** is the on-chain orchestrator that evaluates policies wheneve
     1. Submit the wizard and wait for onchain deployment to complete. The engine starts in `creation_pending` status until deployment finishes.
     1. Open the engine in Policy Manager and confirm its status is **Active**. Click the **gear icon** to view the onchain contract addresses and attached extractors.
 
-    For verification and troubleshooting during deployment, see [Create a PolicyEngine](/ace/getting-started/policy-manager#create-a-policyengine) in the Policy Manager Quick Start.
+    For verification and troubleshooting during deployment, see [Create a PolicyEngine](/ace/getting-started/policy-manager#3-create-a-policyengine) in the Policy Manager Quick Start.
 
     
 
diff --git a/src/content/ccip/v2/evm/tutorials/application-developers/programmable-token-transfers.mdx b/src/content/ccip/v2/evm/tutorials/application-developers/programmable-token-transfers.mdx
index abdd66e91a0..4b51959075d 100644
--- a/src/content/ccip/v2/evm/tutorials/application-developers/programmable-token-transfers.mdx
+++ b/src/content/ccip/v2/evm/tutorials/application-developers/programmable-token-transfers.mdx
@@ -278,7 +278,7 @@ On the destination blockchain, the router calls the inherited `ccipReceive` [fun
 
 **Note**: Two important security measures are applied:
 
-- `_ccipReceive` is called by the `ccipReceive` [function](/ccip/evm/api-reference/v2.0.0/ccip-receiver#ccipreceive), which ensures that only the router can deliver CCIP messages to the receiver contract. See the `onlyRouter` [modifier](/ccip/evm/api-reference/v2.0.0/ccip-receiver#onlyrouter) for more information.
+- `_ccipReceive` is called by the `ccipReceive` [function](/ccip/evm/api-reference/v2.0.0/ccip-receiver#ccipreceive), which ensures that only the router can deliver CCIP messages to the receiver contract. See the `onlyRouter` [modifier](/ccip/evm/api-reference/v2.0.0/ccip-receiver#onlyrouter-modifier) for more information.
 - The modifier `onlyAllowlisted` ensures that only a call from an allowlisted source chain and sender pair is accepted.
 
 ```solidity filename="_ccipReceive"
diff --git a/src/content/ccip/v2/evm/tutorials/application-developers/send-arbitrary-data.mdx b/src/content/ccip/v2/evm/tutorials/application-developers/send-arbitrary-data.mdx
index 4f5b5fd9586..2fba47bbe61 100644
--- a/src/content/ccip/v2/evm/tutorials/application-developers/send-arbitrary-data.mdx
+++ b/src/content/ccip/v2/evm/tutorials/application-developers/send-arbitrary-data.mdx
@@ -235,7 +235,7 @@ On the destination blockchain, the router calls the inherited `ccipReceive` [fun
 
 **Note**: Two important security measures are applied:
 
-- `_ccipReceive` is called by the `ccipReceive` [function](/ccip/evm/api-reference/v2.0.0/ccip-receiver#ccipreceive), which ensures that only the router can deliver CCIP messages to the receiver contract. See the `onlyRouter` [modifier](/ccip/evm/api-reference/v2.0.0/ccip-receiver#onlyrouter) for more information.
+- `_ccipReceive` is called by the `ccipReceive` [function](/ccip/evm/api-reference/v2.0.0/ccip-receiver#ccipreceive), which ensures that only the router can deliver CCIP messages to the receiver contract. See the `onlyRouter` [modifier](/ccip/evm/api-reference/v2.0.0/ccip-receiver#onlyrouter-modifier) for more information.
 - The modifier `onlyAllowlisted` ensures that only a call from an allowlisted source chain and sender pair is accepted.
 
 ```solidity filename="_ccipReceive"
diff --git a/src/content/ccip/v2/evm/tutorials/cross-chain-tokens/update-rate-limiters-foundry.mdx b/src/content/ccip/v2/evm/tutorials/cross-chain-tokens/update-rate-limiters-foundry.mdx
index a5d8afee641..e33399874b2 100644
--- a/src/content/ccip/v2/evm/tutorials/cross-chain-tokens/update-rate-limiters-foundry.mdx
+++ b/src/content/ccip/v2/evm/tutorials/cross-chain-tokens/update-rate-limiters-foundry.mdx
@@ -783,7 +783,7 @@ This section applies to [`TokenPool`](https://github.com/smartcontractkit/chainl
       registration tutorial: