diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index f0122066f..1f51157ed 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -248,7 +248,8 @@ module.exports = {
collapsable: true,
children: [
'/how-to/address-ipfs-on-web',
- '/how-to/browser-tools-frameworks'
+ '/how-to/browser-tools-frameworks',
+ '/how-to/detect-ipfs-on-web',
]
},
{
@@ -512,7 +513,25 @@ module.exports = {
],
'vuepress-plugin-chunkload-redirect',
'vuepress-plugin-ipfs',
- 'vuepress-plugin-mermaidjs',
+ [
+ 'vuepress-plugin-mermaidjs',
+ {
+ securityLevel: 'loose', // safe as we dont allow mermaid in user content. allows for additional interactivity
+ theme: 'base',
+ themeVariables: { // values from 'IPFS brand sheet' at https://github.com/ipfs/ipfs-gui#resources
+ primaryColor: '#D7EDF1',
+ edgeLabelBackground:'#edf0f4',
+ tertiaryColor: '#edf0f4'
+ },
+ deterministicIds: true,
+ deterministicIDSeed: DEPLOY_DOMAIN,
+ flowchart: {
+ htmlLabels: true,
+ curve: 'basis',
+ useMaxWidth: false
+ }
+ }
+ ],
'tabs'
],
extraWatchFiles: ['.vuepress/nav/en.js']
diff --git a/docs/how-to/detect-ipfs-on-web.md b/docs/how-to/detect-ipfs-on-web.md
new file mode 100644
index 000000000..310925fdb
--- /dev/null
+++ b/docs/how-to/detect-ipfs-on-web.md
@@ -0,0 +1,131 @@
+---
+title: Discover IPFS content from Web2
+description: Learn how to add support for content-addressed IPFS resources in web browsers and other user agents.
+---
+
+# Discover IPFS content from Web2
+
+The goal of this page is to provide some suggestions and best practices for Web 2 web browsers and other [user agents](https://en.wikipedia.org/wiki/User_agent) that are interested in adding support for [content-addressed resources](./address-ipfs-on-web.md).
+
+## Detecting content-addressed resources
+
+In many cases, IPFS resources can be detected just by looking at the URI, especially if it is an HTTP URL pointed at a public gateway. This allows a browser to upgrade the transport protocol to IPFS, and removes the need to send an HTTP request to a remote server.
+
+### Methodology
+
+To determine if a resource is an IPFS resource, answer the following questions in order:
+
+1. Does the `URL` follow [path or subdomain gateway](./address-ipfs-on-web.md) convention?
+1. If not, does [DNSLink](../concepts/dnslink.md) with an IPFS path exist for `URL.hostname`?
+
+If you answered yes to either of the above questions, a user agent should be able to find a content path that can be used for data retrieval over IPFS, as described in the illustration below:
+
+```mermaid
+flowchart TD
+ Start[Top-level navigation event]
+ IsGateway{Is it a Gateway URL?
foo.tld/ipxs/id/..
id.ipxs.foo.com/..
}
+
+ Start -->|new URL in address bar| IsGateway
+ IsGateway ==>|YES| IsPathOrSubdomain
+ IsPathOrSubdomain -->|Path Gateway| ExtractFromPath
+ IsPathOrSubdomain -->|Subdomain Gateway| ExtractFromSubdomain
+
+ subgraph GwURLToPath [Convert Gateway URL to a Content Path]
+ IsPathOrSubdomain{Is the Gateway URL 'path'
or 'subdomain' based?}
+ ExtractFromPath[Extract
URL.pathname
]
+ ExtractFromSubdomain[Read namespace
and
identifier from
URL.hostname
and
prepend to URL.pathname
.
E.g., turn
id.ipxs.foo.com/pathname
into /ipxs/id/pathname
]
+ end
+
+ PotentialContentPath[Found a Potential Content Path]
+
+ ExtractFromPath --> PotentialContentPath
+ ExtractFromSubdomain --> PotentialContentPath
+ PotentialContentPath -->|/ipxs/id/sub/path..| IsIpfsOrIpns
+
+ subgraph PathValidation [Is the Content Path valid?]
+ IsIpfsOrIpns{Is it /ipfs/
or /ipns/
?}
+ ValidateRootCID{Is id
a valid CID?}
+ ValidateIPNSKey{Is id
a valid CID
with libp2p-key
codec?}
+ ValidateDNSLink{Is id
a DNSLink name
with TXT record:
dnslink=/ipfs/
or =/ipns/
}
+
+ IsIpfsOrIpns --->|/ipfs/id/..| ValidateRootCID
+ IsIpfsOrIpns -->|/ipns/id/..| ValidateIPNSKey
+ ValidateIPNSKey -->|NO| ValidateDNSLink
+ end
+
+ subgraph FoundValidIPFSContent [Confirmed we've found a Valid IPFS Resource]
+ style FoundValidIPFSContent margin-top: 50
+ ValidIPFSCID[Valid /ipfs/cid/..
Content Path]
+ ValidIPNSKey[Valid /ipns/key/..
Content Path]
+ ValidDNSLink[Valid /ipns/dnslink/..
Content Path]
+
+ ValidateRootCID ===>|YES, /ipfs/cid/..| ValidIPFSCID
+ ValidateIPNSKey ===>|YES, /ipns/key/..| ValidIPNSKey
+ ValidateDNSLink ===>|YES, /ipfs/dnslink/..| ValidDNSLink
+ end
+
+ subgraph NonGwURLToPath [See if non-Gateway URL has a Content Path]
+ IsCachedDNSLink{Does
URL.hostname
match a cached
DNSLink name?}
+ IsHeaderPresent{Is X-Ipfs-Path
header present?}
+ IsError{Did request fail?
HTTP error>500
or network error}
+ IsDNSLinkAtHostname{Does DNSLink exists
for URL.hostname
?
}
+ PathFromHeader[Read value from X-Ipfs-Path
]
+ end
+
+ IsGateway -->|NO| IsCachedDNSLink
+ IsCachedDNSLink ==>|YES| ValidDNSLink
+ IsCachedDNSLink -->|NO| IsHeaderPresent
+ IsHeaderPresent ==>|YES| IsDNSLinkAtHostname
+ IsHeaderPresent -->|NO| IsError
+ IsError ==>|YES| IsDNSLinkAtHostname
+ IsDNSLinkAtHostname ==>|YES| ValidDNSLink
+ IsDNSLinkAtHostname -->|NO| PathFromHeader
+ PathFromHeader --> PotentialContentPath
+```
+
+
+
+## What to do with detected paths
+
+What you do with the detected IPFS resource path depends on the type of path.
+
+### Immutable `/ipfs/cid/..`
+
+- Display "Open via IPFS" button in UI
+ - Clicking it should open `ipfs://cid/path?query#hash` (preserving any `?query` or `#hash` from the original HTTP URL)
+- If "IPFS Gateway Redirect / Protocol Upgrade" feature is enabled, and the HTTP URL was a gateway one, redirect automatically to `ipfs://cid/path?query#hash`
+
+### Mutable `/ipns/key/..`
+- Display "Open via IPFS" button in UI
+ - Clicking it should open `ipns://key/path?query#hash` (preserving any `?query` or `#hash` from the original HTTP URL)
+- If "IPFS Gateway Redirect / Protocol Upgrade" is enabled, and the original HTTP URL was a gateway one, redirect automatically to `ipns://dnslink/path?query#hash`
+
+### Mutable `/ipns/dnslink/..`
+
+- Display "Open via IPFS" button in UI
+ - Clicking it should open `ipns://dnslink/path?query#hash` (preserving `?query` or `#hash` from the original HTTP URL)
+- If "DNSLink Website Redirect / Protocol Upgrade" is enabled, redirect automatically to `ipns://dnslink/path?query#hash`
+- It is a good practice to internally cache the fact that domain has a valid DNSLink.
+ - TTL from TXT record can be used as a hint when to expire cache entry.
+ - Performance can be improved further by using cached flag and revalidating it asynchronously, without blocking browser navigation.
+
+## Implementation examples
+
+### Brave
+
+[Brave has supported IPFS since 2021](https://brave.com/brave-integrates-ipfs/). Current features include `ipfs://` and `ipns://` URI support, ability to resolve this type of address using a public / local gateway, opt-in Gateway and/or DNSLink redirects, and an **Open via IPFS** button in the address bar:
+
+> 
+
+### IPFS Companion
+
+Firefox and Chromium-based browsers such as Google Chrome or Microsoft Edge can access IPFS with the [IPFS Companion](../install/ipfs-companion.md) browser extension, which allows them to detect IPFS content.
+
+
+## FAQ
+
+**What if a browser does not support `ipfs://` and `ipns://` natively?** Implementations can use an [HTTP Gateway](../reference/http/gateway.md) as a fallback, convert the path to `//gatewayhost/ipxs/id/..`-type paths, or leverage the built-in URI router at `//gatewayhost/ipfs/?uri=%s`
+
+**Why should `?query` or `#hash` from the original HTTP URL be preserved?** The link could point at specific `#section` of a longer article. It is also common for JavaScript running on a page to use the `?query` and `#hash` for navigation and ad-hoc storage of some state.
+
+**Should a user agent redirect when the URL does not match gateway convention, `URL.hostname` does not have a valid DNSLink, but `X-Ipfs-Path` is present in HTTP response AND points at an immutable `/ipfs/cid`?** This is an edge case, and we've seen that it is often a misconfiguration caused by an invalid or missing DNSLink that could lead to bad UX when automatic redirect is involved. The user ends up on an immutable copy of a website, bookmarks it or keeps tabs open, and misses updates when DNSLink setup is fixed. It is suggested to not redirect this edge case, or provide a setting that controls this type of redirect. Usually, showing "Open via IPFS" in the user interface is enough for this case.