diff --git a/docs/website/docusaurus.config.js b/docs/website/docusaurus.config.js
index e0a63bf113b..a160d5ba863 100644
--- a/docs/website/docusaurus.config.js
+++ b/docs/website/docusaurus.config.js
@@ -15,7 +15,7 @@ const config = {
baseUrl: "/doc/",
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
- favicon: "img/logo.svg",
+ favicon: "img/mithril-logo.svg",
organizationName: "Input Output Global",
projectName: "Mithril",
@@ -88,6 +88,17 @@ const config = {
],
plugins: [
+ async function myPlugin(context, options) {
+ return {
+ name: "docusaurus-tailwindcss",
+ configurePostCss(postcssOptions) {
+ // Appends TailwindCSS and AutoPrefixer.
+ postcssOptions.plugins.push(require("tailwindcss"));
+ postcssOptions.plugins.push(require("autoprefixer"));
+ return postcssOptions;
+ },
+ };
+ },
[
"@docusaurus/plugin-content-blog",
{
@@ -200,15 +211,20 @@ const config = {
id: "announcement",
content:
'Participate in Mithril Protocol’s Mainnet Beta! Follow our SPO on-boarding guide here !',
- backgroundColor: "#2e8555",
+ backgroundColor: "#2A598E",
textColor: "#f1f1f1",
isCloseable: true,
},
+ colorMode: {
+ defaultMode: "light",
+ disableSwitch: true,
+ respectPrefersColorScheme: false,
+ },
navbar: {
- title: "Mithril",
logo: {
alt: "Mithril. A complete guide.",
- src: "img/logo.svg",
+
+ src: "img/mithril-logo-text.svg",
},
items: [
{
@@ -238,23 +254,21 @@ const config = {
label: "Glossary",
position: "right",
},
- { to: "/dev-blog", label: "Dev blog", position: "right" },
+ { to: "/dev-blog", label: "Blog", position: "right" },
{ to: "/adr", label: "ADRs", position: "right" },
- {
- className: "header-github-link",
- href: "https://github.com/input-output-hk/mithril/",
- position: "right",
- },
],
},
footer: {
- style: "dark",
+ logo: {
+ alt: "Mithril. A complete guide.",
+ src: "img/mithril-logo-dark.svg",
+ },
links: [
{
title: "Contributing",
items: [
{
- label: "Contributing Guidelines",
+ label: "Contributing guidelines",
href: "https://github.com/input-output-hk/mithril/blob/main/CONTRIBUTING.md",
},
{
@@ -271,7 +285,7 @@ const config = {
href: "https://discord.gg/5kaErDKDRq",
},
{
- label: "GitHub Discussions",
+ label: "GitHub discussions",
href: "https://github.com/input-output-hk/mithril/discussions",
},
{
@@ -284,11 +298,11 @@ const config = {
title: "More",
items: [
{
- label: "Mithril Networks Status",
+ label: "Mithril networks status",
href: "https://mithril.cronitorstatus.com/",
},
{
- label: "Mithril Protocol Insights",
+ label: "Mithril protocol insights",
href: "https://lookerstudio.google.com/s/mbL23-8gibI",
},
{
@@ -301,8 +315,21 @@ const config = {
},
],
},
+ {
+ title: "Legal",
+ items: [
+ {
+ label: "Privacy policy",
+ href: "https://static.iohk.io/terms/iog-privacy-policy.pdf",
+ },
+ {
+ label: "Terms and conditions",
+ href: "https://static.iohk.io/terms/iog-terms-and-conditions.pdf",
+ },
+ ],
+ },
],
- copyright: `Copyright © ${new Date().getFullYear()} Input Output Global | Built with Docusaurus `,
+ copyright: `Copyright © ${new Date().getFullYear()} IOG, Inc.`,
},
prism: {
theme: lightCodeTheme,
diff --git a/docs/website/helpers/media-queries.ts b/docs/website/helpers/media-queries.ts
new file mode 100644
index 00000000000..6d602709527
--- /dev/null
+++ b/docs/website/helpers/media-queries.ts
@@ -0,0 +1,11 @@
+export const not = (query: string) => "not screen and " + query;
+
+export const forPhablet = "(min-width: 640px)";
+
+export const forTablet = "(min-width: 768px)";
+
+export const forLaptop = "(min-width: 1024px)";
+
+export const forDesktop = "(min-width: 1280px)";
+
+export const forTabletOnly = `${forTablet} and (max-width: 1024px)`;
diff --git a/docs/website/homepage-content/features.tsx b/docs/website/homepage-content/features.tsx
new file mode 100644
index 00000000000..de6b5d9bbb8
--- /dev/null
+++ b/docs/website/homepage-content/features.tsx
@@ -0,0 +1,57 @@
+import React from "react";
+import { translate } from "@docusaurus/Translate";
+import Security from "../src/components/icons/Security";
+import Speed from "../src/components/icons/Speed";
+import Verification from "../src/components/icons/Verification";
+import Scalability from "../src/components/icons/Scalability";
+
+export const FeatureList = [
+ {
+ title: translate({
+ id: "homepage.featureList.security.title",
+ message: "Secure data exchange",
+ }),
+ icon: ,
+ description: translate({
+ id: "homepage.featureList.security.description",
+ message:
+ "Fast and secure data synchronization with layer 2 solutions – including bridges, sidechains, and rollups – as well as applications like light wallets.",
+ }),
+ },
+ {
+ title: translate({
+ id: "homepage.featureList.speed.title",
+ message: "Faster node bootstrapping",
+ }),
+ icon: ,
+ description: translate({
+ id: "homepage.featureList.speed.description",
+ message:
+ "Mithril's certified snapshots allow nodes to bootstrap quickly while maintaining the same level of security.",
+ }),
+ },
+ {
+ title: translate({
+ id: "homepage.featureList.verification.title",
+ message: "Trustless state verification",
+ }),
+ icon: ,
+ description: translate({
+ id: "homepage.featureList.verification.description",
+ message:
+ "Blockchain data is validated and certified by a minimum share of the stake, enabling secure data exchange between decentralized applications.",
+ }),
+ },
+ {
+ title: translate({
+ id: "homepage.featureList.scalability.title",
+ message: "Scalability",
+ }),
+ icon: ,
+ description: translate({
+ id: "homepage.featureList.scalability.description",
+ message:
+ "Stake-based threshold multi-signatures efficiently aggregate individual signatures, ensuring scalability even as the number of participants grows.",
+ }),
+ },
+];
diff --git a/docs/website/homepage-content/hero.ts b/docs/website/homepage-content/hero.ts
new file mode 100644
index 00000000000..9ba206a1168
--- /dev/null
+++ b/docs/website/homepage-content/hero.ts
@@ -0,0 +1,12 @@
+import { translate } from "@docusaurus/Translate";
+
+export const hero = {
+ title: translate({
+ id: "homepage.hero.title",
+ message: "Mithril documentation",
+ }),
+ standfirst: translate({
+ id: "homepage.hero.standfirst",
+ message: `Mithril is a protocol and network designed for proof-of-stake blockchains. It aims to provide lightweight access to blockchain data with a high degree of security and decentralization.`,
+ }),
+};
diff --git a/docs/website/homepage-content/use-cases.ts b/docs/website/homepage-content/use-cases.ts
new file mode 100644
index 00000000000..3b500371737
--- /dev/null
+++ b/docs/website/homepage-content/use-cases.ts
@@ -0,0 +1,21 @@
+import { translate } from "@docusaurus/Translate";
+
+export const useCases = {
+ nonScrollingText: translate({
+ id: "homepage.useCases.nonScrollingText",
+ message: "Use cases include:",
+ }),
+ scrollingText: {
+ id: "homepage.useCases.scrollingText",
+ items: [
+ "Full node clients",
+ "Light clients",
+ "Light wallets",
+ "Mobile applications",
+ "Sidechains",
+ "Bridges",
+ "Rollups",
+ "State channels",
+ ],
+ },
+};
diff --git a/docs/website/homepage-content/why-mithril.tsx b/docs/website/homepage-content/why-mithril.tsx
new file mode 100644
index 00000000000..04c476a50f6
--- /dev/null
+++ b/docs/website/homepage-content/why-mithril.tsx
@@ -0,0 +1,27 @@
+import React from "react";
+import { translate } from "@docusaurus/Translate";
+
+export const WhyMithrilContents = {
+ title: translate({
+ id: "homepage.whyMithril.title",
+ message: "WHY MITHRIL?",
+ }),
+ descriptionParagraph: {
+ id: "homepage.whyMithril.paragraphs",
+ message: (
+
+
+ The Cardano blockchain offers robust security, but starting up a new
+ node, syncing it with the network, or exchanging data can be slow and
+ resource intensive (24GB of RAM, 150GB (and growing) of storage, and
+ over 24 hours for initial synchronization.)
+
+
+ Mithril was developed for Cardano as part of the Basho development
+ phase to support optimization, scalability, and interoperability.
+
+
+ ),
+ },
+ timeline: ["Byron", "Shelley", "Goguen", "Basho", "Voltaire"],
+};
diff --git a/docs/website/package-lock.json b/docs/website/package-lock.json
index 5907dbb1329..8d72ba61554 100644
--- a/docs/website/package-lock.json
+++ b/docs/website/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "mithril-doc",
- "version": "0.1.55",
+ "version": "0.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mithril-doc",
- "version": "0.1.55",
+ "version": "0.2.0",
"dependencies": {
"@docusaurus/core": "^3.8.0",
"@docusaurus/plugin-client-redirects": "^3.8.0",
@@ -14,6 +14,8 @@
"@docusaurus/preset-classic": "^3.8.0",
"@docusaurus/theme-mermaid": "^3.8.0",
"clsx": "^2.1.1",
+ "cva": "^1.0.0-beta.4",
+ "framer-motion": "^11.3.19",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"redocusaurus": "^2.5.0",
@@ -21,7 +23,9 @@
"remark-math": "^6.0.0"
},
"devDependencies": {
- "prettier": "3.3.2"
+ "autoprefixer": "^10.4.19",
+ "prettier": "3.3.2",
+ "tailwindcss": "^3.4.7"
}
},
"node_modules/@algolia/autocomplete-core": {
@@ -237,6 +241,18 @@
"node": ">= 14.0.0"
}
},
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -3785,6 +3801,50 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
"node_modules/@jest/schemas": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
@@ -3953,6 +4013,16 @@
"node": ">= 8"
}
},
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@pnpm/config.env-replace": {
"version": "1.1.0",
"license": "MIT",
@@ -5273,6 +5343,12 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"license": "ISC",
@@ -5708,6 +5784,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/camelize": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
@@ -6839,6 +6924,25 @@
"version": "3.1.3",
"license": "MIT"
},
+ "node_modules/cva": {
+ "version": "1.0.0-beta.4",
+ "resolved": "https://registry.npmjs.org/cva/-/cva-1.0.0-beta.4.tgz",
+ "integrity": "sha512-F/JS9hScapq4DBVQXcK85l9U91M6ePeXoBMSp7vypzShoefUBxjQTo3g3935PUHgQd+IW77DjbPRIxugy4/GCQ==",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ },
+ "peerDependencies": {
+ "typescript": ">= 4.5.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/cytoscape": {
"version": "3.32.0",
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.0.tgz",
@@ -7499,6 +7603,12 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "dev": true
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -7510,6 +7620,12 @@
"node": ">=8"
}
},
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "dev": true
+ },
"node_modules/dns-packet": {
"version": "5.6.1",
"license": "MIT",
@@ -8433,6 +8549,34 @@
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz",
"integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg=="
},
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/form-data-encoder": {
"version": "2.1.4",
"license": "MIT",
@@ -8467,6 +8611,32 @@
"url": "https://github.com/sponsors/rawify"
}
},
+ "node_modules/framer-motion": {
+ "version": "11.18.2",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz",
+ "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==",
+ "dependencies": {
+ "motion-dom": "^11.18.1",
+ "motion-utils": "^11.18.1",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -9738,6 +9908,21 @@
"node": ">=0.10.0"
}
},
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
"node_modules/jest-util": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
@@ -12448,6 +12633,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
"node_modules/mlly": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
@@ -12531,6 +12725,19 @@
}
}
},
+ "node_modules/motion-dom": {
+ "version": "11.18.1",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz",
+ "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==",
+ "dependencies": {
+ "motion-utils": "^11.18.1"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "11.18.1",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz",
+ "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA=="
+ },
"node_modules/mrmime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
@@ -12555,6 +12762,17 @@
"multicast-dns": "cli.js"
}
},
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@@ -12831,6 +13049,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -13054,6 +13281,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true
+ },
"node_modules/package-manager-detector": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz",
@@ -13201,6 +13434,28 @@
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true
+ },
"node_modules/path-to-regexp": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz",
@@ -13242,6 +13497,24 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/pkg-dir": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz",
@@ -13841,6 +14114,42 @@
"postcss": "^8.4"
}
},
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dev": true,
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
"node_modules/postcss-lab-function": {
"version": "7.0.10",
"resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-7.0.10.tgz",
@@ -13869,6 +14178,53 @@
"postcss": "^8.4"
}
},
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-load-config/node_modules/yaml": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
+ "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
+ "dev": true,
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
+ },
"node_modules/postcss-loader": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz",
@@ -14100,6 +14456,31 @@
"postcss": "^8.1.0"
}
},
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
"node_modules/postcss-nesting": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz",
@@ -15068,6 +15449,15 @@
"react": "^18.0.0 || ^19.0.0"
}
},
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
"node_modules/readable-stream": {
"version": "3.6.2",
"license": "MIT",
@@ -16445,6 +16835,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
"node_modules/string-width/node_modules/ansi-regex": {
"version": "6.0.1",
"license": "MIT",
@@ -16504,6 +16915,19 @@
"node": ">=8"
}
},
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-bom-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
@@ -16636,6 +17060,81 @@
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
"integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="
},
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"license": "MIT",
@@ -16720,6 +17219,55 @@
"url": "https://github.com/Mermade/oas-kit?sponsor=1"
}
},
+ "node_modules/tailwindcss": {
+ "version": "3.4.17",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
+ "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
+ "dev": true,
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.6",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.1",
"license": "MIT",
@@ -16845,6 +17393,27 @@
"version": "2.20.3",
"license": "MIT"
},
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/thunky": {
"version": "1.1.0",
"license": "MIT"
@@ -16927,6 +17496,12 @@
"node": ">=6.10"
}
},
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "dev": true
+ },
"node_modules/tslib": {
"version": "2.6.2",
"license": "0BSD"
@@ -17973,6 +18548,44 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/wrap-ansi/node_modules/ansi-regex": {
"version": "6.0.1",
"license": "MIT",
diff --git a/docs/website/package.json b/docs/website/package.json
index 015700826fa..3b1a800cb03 100644
--- a/docs/website/package.json
+++ b/docs/website/package.json
@@ -1,6 +1,6 @@
{
"name": "mithril-doc",
- "version": "0.1.55",
+ "version": "0.2.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -26,7 +26,9 @@
"react-dom": "^18.3.1",
"redocusaurus": "^2.5.0",
"rehype-katex": "^7.0.1",
- "remark-math": "^6.0.0"
+ "remark-math": "^6.0.0",
+ "framer-motion": "^11.3.19",
+ "cva": "^1.0.0-beta.4"
},
"browserslist": {
"production": [
@@ -41,6 +43,8 @@
]
},
"devDependencies": {
- "prettier": "3.3.2"
+ "prettier": "3.3.2",
+ "tailwindcss": "^3.4.7",
+ "autoprefixer": "^10.4.19"
}
}
diff --git a/docs/website/src/components/AnimatedText.tsx b/docs/website/src/components/AnimatedText.tsx
new file mode 100644
index 00000000000..6a268bc1a3d
--- /dev/null
+++ b/docs/website/src/components/AnimatedText.tsx
@@ -0,0 +1,74 @@
+import React, { FC } from "react";
+import { motion } from "framer-motion";
+
+const processText = (children: React.ReactNode): React.ReactNode =>
+ React.Children.map(children, (child) => {
+ if (typeof child === "string") {
+ return child.split(" ").map((word, index) => (
+
+ {word.split("").map((char, charIndex) => (
+
+ {char}
+ {charIndex === word.length - 1 && (
+
+ )}
+
+ ))}
+
+ ));
+ }
+
+ if (React.isValidElement(child)) {
+ //@ts-ignore
+ const processedText = processText(child.props.children);
+ //@ts-ignore
+ return React.cloneElement(child, child.props, processedText);
+ }
+ });
+
+const AnimatedText: FC = () => {
+ return (
+
+
+ {processText(
+
+ Choosing Mithril means opting for a scalable, secure, and versatile
+ enhancement to the Cardano blockchain
+ ,
+ )}
+
+
+ );
+};
+
+export default AnimatedText;
diff --git a/docs/website/src/components/Features.tsx b/docs/website/src/components/Features.tsx
new file mode 100644
index 00000000000..1573dbaaea5
--- /dev/null
+++ b/docs/website/src/components/Features.tsx
@@ -0,0 +1,67 @@
+import React, { FC } from "react";
+import { motion } from "framer-motion";
+import { FeatureList } from "../../homepage-content/features";
+import useMediaQuery from "../hooks/useMediaQuery";
+import { forTablet } from "../../helpers/media-queries";
+
+type Props = {
+ icon: React.JSX.Element;
+ title: string;
+ description: string;
+ index: number;
+};
+
+const Feature: FC = ({ icon, title, description, index }) => {
+ const isTabletUp = useMediaQuery(forTablet);
+
+ return (
+
+
+ {icon}
+
+ {title}
+
+
+ {description}
+
+ );
+};
+
+const Features: FC = () => {
+ return (
+
+
+
+ FEATURES
+
+
+ {FeatureList.map((props, idx) => (
+
+ ))}
+
+
+
+ );
+};
+
+export default Features;
diff --git a/docs/website/src/components/HomepageFeatures/index.js b/docs/website/src/components/HomepageFeatures/index.js
deleted file mode 100644
index a8f3b681e74..00000000000
--- a/docs/website/src/components/HomepageFeatures/index.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import React from "react";
-import clsx from "clsx";
-import styles from "./styles.module.css";
-
-const FeatureList = [
- {
- title: "User manual",
- Svg: require("@site/static/img/card-get-started.svg").default,
- description: (
- <>
- Read about how to get started and explore guides, installation instructions, and developer
- docs.
- >
- ),
- link: "/doc/manual/welcome",
- },
- {
- title: "The Mithril protocol",
- Svg: require("@site/static/img/card-native-tokens.svg").default,
- description: (
- <>Discover how the Mithril protocol works and find more about the Mithril multi signature.>
- ),
- link: "/doc/mithril/mithril-protocol/protocol",
- },
- {
- title: "The Mithril network",
- Svg: require("@site/static/img/card-operate-a-stake-pool.svg").default,
- description: (
- <>Learn about the Mithril network and find more about its nodes and architecture.>
- ),
- link: "/doc/mithril/mithril-network/architecture",
- },
-];
-
-function Feature({ Svg, title, description, link }) {
- return (
-
- );
-}
-
-export default function HomepageFeatures() {
- return (
-
-
-
- {FeatureList.map((props, idx) => (
-
- ))}
-
-
-
- );
-}
diff --git a/docs/website/src/components/HomepageFeatures/styles.module.css b/docs/website/src/components/HomepageFeatures/styles.module.css
deleted file mode 100644
index b248eb2e5de..00000000000
--- a/docs/website/src/components/HomepageFeatures/styles.module.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.features {
- display: flex;
- align-items: center;
- padding: 2rem 0;
- width: 100%;
-}
-
-.featureSvg {
- height: 200px;
- width: 200px;
-}
diff --git a/docs/website/src/components/HomepageHero.tsx b/docs/website/src/components/HomepageHero.tsx
new file mode 100644
index 00000000000..b0d751f8be4
--- /dev/null
+++ b/docs/website/src/components/HomepageHero.tsx
@@ -0,0 +1,73 @@
+import React, { FC } from "react";
+import Link from "@docusaurus/Link";
+import { forTablet } from "../../helpers/media-queries";
+import { motion } from "framer-motion";
+import { hero } from "../../homepage-content/hero";
+
+const HomepageHero: FC = () => {
+ return (
+
+
{
+ (e.target as HTMLVideoElement).style.opacity = "1";
+ }}
+ aria-label="Video background"
+ className="absolute top-0 left-0 right-0 bottom-0 object-cover -z-10 w-full h-full opacity-0 transition-opacity"
+ >
+
+
+
+
+
+
+
+ {hero.title}
+
+
+ {hero.standfirst}
+
+
+
+
+ Learn more
+
+
+
+
+
+ );
+};
+
+export default HomepageHero;
diff --git a/docs/website/src/components/UseCases.tsx b/docs/website/src/components/UseCases.tsx
new file mode 100644
index 00000000000..2aba2dbc4e2
--- /dev/null
+++ b/docs/website/src/components/UseCases.tsx
@@ -0,0 +1,80 @@
+import React, { FC, useEffect, useState } from "react";
+import { AnimatePresence, motion } from "framer-motion";
+import Link from "@docusaurus/Link";
+import { useCases } from "../../homepage-content/use-cases";
+
+const processItems = (items: string[]): React.ReactNode => {
+ const [index, setIndex] = useState(0);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setIndex((prev) => (prev + 1) % items.length);
+ }, 2500);
+
+ return () => clearInterval(interval);
+ }, []);
+ return (
+
+
+ {items[index]}
+
+
+ );
+};
+const UseCases: FC = () => {
+ return (
+
+
+
+ {useCases.nonScrollingText}
+ {processItems(useCases.scrollingText.items)}
+
+
+ Learn more
+
+
+
+ );
+};
+
+export default UseCases;
diff --git a/docs/website/src/components/WhyMithril.tsx b/docs/website/src/components/WhyMithril.tsx
new file mode 100644
index 00000000000..32289bca881
--- /dev/null
+++ b/docs/website/src/components/WhyMithril.tsx
@@ -0,0 +1,131 @@
+import React, { FC, useRef } from "react";
+import {
+ motion,
+ useScroll,
+ useTransform,
+ useSpring,
+ useMotionTemplate,
+} from "framer-motion";
+import { WhyMithrilContents } from "../../homepage-content/why-mithril";
+import { cx } from "cva";
+import Link from "@docusaurus/Link";
+
+const WhyMithril: FC = () => {
+ const containerRef = useRef(null);
+
+ const { scrollYProgress } = useScroll({
+ target: containerRef,
+ offset: ["start end", "end start"],
+ });
+
+ return (
+
+
+
+ {WhyMithrilContents.title}
+
+
+
+
+ {WhyMithrilContents.timeline.map((item, index) => {
+ const start = 0.07 + index * 0.07;
+ const end = start + 0.3;
+
+ const z = useTransform(
+ scrollYProgress,
+ [start, (start + end) / 2, end],
+ [-200, 0, 200],
+ );
+ const opacity = useTransform(
+ scrollYProgress,
+ [start, (start + end) / 2, end],
+ [0, 1, 0],
+ );
+ const blur = useTransform(
+ scrollYProgress,
+ [start, (start + end) / 1.8, end],
+ [5, 0, 100],
+ );
+
+ const springZ = useSpring(z, { stiffness: 100, damping: 30 });
+ const springOpacity = useSpring(opacity, {
+ stiffness: 100,
+ damping: 30,
+ });
+ const springBlur = useSpring(blur, {
+ stiffness: 100,
+ damping: 30,
+ });
+
+ const transform = useMotionTemplate`translateZ(${springZ}px)`;
+ const filter = useMotionTemplate`blur(${springBlur}px)`;
+
+ const alignments = [
+ "flex-start",
+ "flex-end",
+ "flex-start",
+ "center",
+ "flex-end",
+ ];
+
+ return (
+
+ {item}
+
+ );
+ })}
+
+
+
+ {WhyMithrilContents.descriptionParagraph.message}
+
+ Learn more
+
+
+
+
+
+ );
+};
+
+export default WhyMithril;
diff --git a/docs/website/src/components/icons/Discord.tsx b/docs/website/src/components/icons/Discord.tsx
new file mode 100644
index 00000000000..9a34d431cee
--- /dev/null
+++ b/docs/website/src/components/icons/Discord.tsx
@@ -0,0 +1,18 @@
+import * as React from "react";
+import { SVGProps } from "react";
+const Discord = (props: SVGProps) => (
+
+
+
+);
+
+export default Discord;
diff --git a/docs/website/src/components/icons/Github.tsx b/docs/website/src/components/icons/Github.tsx
new file mode 100644
index 00000000000..252be9b0f95
--- /dev/null
+++ b/docs/website/src/components/icons/Github.tsx
@@ -0,0 +1,20 @@
+import * as React from "react";
+import { SVGProps } from "react";
+const Github = (props: SVGProps) => (
+
+
+
+);
+
+export default Github;
diff --git a/docs/website/src/components/icons/Scalability.tsx b/docs/website/src/components/icons/Scalability.tsx
new file mode 100644
index 00000000000..843a8b6602a
--- /dev/null
+++ b/docs/website/src/components/icons/Scalability.tsx
@@ -0,0 +1,52 @@
+import * as React from "react";
+import { SVGProps } from "react";
+const Scalability = (props: SVGProps) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+export default Scalability;
diff --git a/docs/website/src/components/icons/Security.tsx b/docs/website/src/components/icons/Security.tsx
new file mode 100644
index 00000000000..1ec8ab95298
--- /dev/null
+++ b/docs/website/src/components/icons/Security.tsx
@@ -0,0 +1,41 @@
+import * as React from "react";
+import { SVGProps } from "react";
+const Security = (props: SVGProps) => (
+
+
+
+
+
+
+
+
+
+);
+
+export default Security;
diff --git a/docs/website/src/components/icons/Speed.tsx b/docs/website/src/components/icons/Speed.tsx
new file mode 100644
index 00000000000..cb47318f1b8
--- /dev/null
+++ b/docs/website/src/components/icons/Speed.tsx
@@ -0,0 +1,40 @@
+import * as React from "react";
+import { SVGProps } from "react";
+const Speed = (props: SVGProps) => (
+
+
+
+
+
+
+
+
+
+);
+
+export default Speed;
diff --git a/docs/website/src/components/icons/Verification.tsx b/docs/website/src/components/icons/Verification.tsx
new file mode 100644
index 00000000000..107c6885424
--- /dev/null
+++ b/docs/website/src/components/icons/Verification.tsx
@@ -0,0 +1,40 @@
+import * as React from "react";
+import { SVGProps } from "react";
+const Verification = (props: SVGProps) => (
+
+
+
+
+
+
+
+
+
+);
+
+export default Verification;
diff --git a/docs/website/src/context/PageContext.ts b/docs/website/src/context/PageContext.ts
new file mode 100644
index 00000000000..ea895ba158f
--- /dev/null
+++ b/docs/website/src/context/PageContext.ts
@@ -0,0 +1,10 @@
+import { createContext } from "react";
+
+export enum PageType {
+ Landing = "Landing",
+ Default = "Default",
+}
+
+export const PageContext = createContext({
+ page: PageType.Default,
+});
diff --git a/docs/website/src/css/custom.css b/docs/website/src/css/custom.css
index 243344cd8b3..608a6deb3d3 100644
--- a/docs/website/src/css/custom.css
+++ b/docs/website/src/css/custom.css
@@ -11,19 +11,76 @@
* https://docusaurus.io/docs/styling-layout#styling-your-site-with-infima
*/
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@font-face {
+ font-family: "Lexend";
+ font-weight: 400;
+ src: url("/fonts/Lexend-VariableFont.ttf");
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Lexend";
+ font-weight: 500;
+ src: url("/fonts/Lexend-VariableFont.ttf");
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Lexend";
+ font-weight: 600;
+ src: url("/fonts/Lexend-VariableFont.ttf");
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Inter";
+ font-weight: 400;
+ src: url("/fonts/Inter-VariableFont.ttf");
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Inter";
+ font-weight: 400;
+ font-style: italic;
+ src: url("/fonts/Inter-Italic-VariableFont.ttf");
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Inter";
+ font-weight: 700;
+ src: url("/fonts/Inter-VariableFont.ttf");
+ font-display: swap;
+}
+
:root {
- --ifm-color-primary: #0969da;
- --ifm-color-primary-dark: #085ec4;
- --ifm-color-primary-darker: #0859b9;
- --ifm-color-primary-darkest: #064999;
- --ifm-color-primary-light: #0a73f0;
- --ifm-color-primary-lighter: #1079f5;
- --ifm-color-primary-lightest: #318cf6;
+ --ifm-color-primary: #397589;
+ --ifm-color-primary-dark: #397589;
+ --ifm-color-primary-darker: #397589;
+ --ifm-color-primary-darkest: #397589;
+ --ifm-color-primary-light: #65cfe1;
+ --ifm-color-primary-lighter: #65cfe1;
+ --ifm-color-primary-lightest: #65cfe1;
--ifm-code-font-size: 95%;
+
+ --ifm-navbar-height: 60px;
+
+ font-family: "Inter";
+}
+
+@media (min-width: 768px) {
+ :root {
+ --ifm-navbar-height: 96px;
+ }
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
-[data-theme="dark"] {
+/* [data-theme="dark"] {
--ifm-color-primary: #669fe1;
--ifm-color-primary-dark: #4b8edc;
--ifm-color-primary-darker: #3d85d9;
@@ -31,6 +88,79 @@
--ifm-color-primary-light: #81b0e6;
--ifm-color-primary-lighter: #8fb9e9;
--ifm-color-primary-lightest: #b8d2f1;
+} */
+
+h1,
+h2,
+h3,
+h4 {
+ font-family: "Lexend";
+}
+
+h5,
+h6 {
+ font-family: "Inter";
+}
+
+h1 {
+ font-size: 2.5rem;
+ font-weight: 500;
+}
+
+h2 {
+ font-size: 2rem;
+}
+
+h3 {
+ font-size: 1.5rem;
+}
+
+.pageContainer {
+ max-width: 1280px;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ padding-left: 24px;
+ padding-right: 24px;
+}
+
+@media (min-width: 768px) {
+ .pageContainer {
+ padding-left: 48px;
+ padding-right: 48px;
+ }
+}
+
+.component {
+ padding-top: 72px;
+ padding-bottom: 72px;
+}
+
+.teal-gradient {
+ background: linear-gradient(to right, #397589, #65cfe1);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ color: transparent;
+}
+
+.use-case-text {
+ background: #01193c;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ color: transparent;
+}
+
+.navbar__item {
+ font-weight: 600;
+ font-size: 1rem;
+ line-height: 2rem;
+}
+
+.navbar__items {
+ display: flex !important;
+ font-family: "Lexend";
}
.docusaurus-highlight-code-line {
@@ -44,19 +174,6 @@
background-color: rgba(0, 0, 0, 0.3);
}
-.header-github-link:before {
- background: url("/static/img/GitHub-Mark-32px.png") no-repeat;
- background-size: cover;
- display: flex;
- content: "";
- height: 24px;
- width: 24px;
-}
-
-[data-theme="dark"] .header-github-link {
- filter: invert(1);
-}
-
@media screen and (max-width: 996px) {
.footer {
text-align: center;
@@ -75,3 +192,113 @@ div[role="banner"] {
div[role="banner"] div {
font-size: 90%;
}
+
+.announcementBarClose_gvF7 {
+ color: var(--ifm-color-white);
+}
+
+.announcementBarClose_gvF7 > svg {
+ width: 12px;
+}
+
+.announcementBarClose_gvF7 > svg > g {
+ stroke-width: 2;
+}
+
+.announcementBar_mb4j {
+ border-bottom: 0px !important;
+}
+
+@media (min-width: 768px) {
+ .theme-doc-version-badge {
+ margin-bottom: 16px !important;
+ }
+}
+
+.col--7 .markdown {
+ padding: 0 !important;
+}
+
+.breadcrumbHomeIcon_src-theme-DocBreadcrumbs-Items-Home-styles-module {
+ height: 100% !important;
+ width: 100% !important;
+}
+
+.breadcrumbs__link {
+ margin-bottom: -8px !important;
+}
+
+.menu__link--active {
+ font-weight: 700;
+}
+
+a.menu__link {
+ text-decoration: none !important;
+ -webkit-text-decoration: none !important;
+}
+
+.markdown ul,
+.markdown ol {
+ padding-left: 2rem;
+ margin: 1rem 0;
+}
+
+.markdown ul {
+ list-style-type: disc;
+}
+
+.markdown ol {
+ list-style-type: decimal;
+}
+
+.markdown li {
+ margin: 0.25rem 0;
+}
+
+.markdown p {
+ margin-bottom: 1.5rem;
+}
+
+.markdown a {
+ text-decoration: underline;
+ text-underline-offset: 2px;
+}
+
+.markdown h1,
+.markdown h2,
+.markdown h3,
+.markdown h4 {
+ margin-bottom: 1rem;
+ font-weight: 700;
+}
+
+.title_f1Hy {
+ font-weight: 700;
+}
+
+.markdown h3 {
+ font-size: 1.5rem !important;
+}
+
+.admonitionHeading_Gvgb {
+ display: flex;
+ align-items: center;
+}
+
+.card {
+ text-decoration: none !important;
+}
+
+.markdown table a {
+ text-decoration: none !important;
+}
+
+.theme-edit-this-page {
+ display: flex;
+ align-items: center;
+}
+
+.stuck-grid {
+ perspective: 500px;
+ transform-style: preserve-3d;
+}
diff --git a/docs/website/src/hooks/useIsLandingPage.ts b/docs/website/src/hooks/useIsLandingPage.ts
new file mode 100644
index 00000000000..9235d597aa6
--- /dev/null
+++ b/docs/website/src/hooks/useIsLandingPage.ts
@@ -0,0 +1,8 @@
+import { useContext } from "react";
+import { PageContext, PageType } from "../context/PageContext";
+
+export function useIsLandingPage() {
+ const context = useContext(PageContext);
+
+ return context && context.page === PageType.Landing;
+}
diff --git a/docs/website/src/hooks/useMediaQuery.ts b/docs/website/src/hooks/useMediaQuery.ts
new file mode 100644
index 00000000000..b0c47c5dcd9
--- /dev/null
+++ b/docs/website/src/hooks/useMediaQuery.ts
@@ -0,0 +1,19 @@
+import { useEffect, useState } from "react";
+
+export default function useMediaQuery(query: string) {
+ const [match, setMatch] = useState(false);
+
+ useEffect(() => {
+ const matchMedia = window.matchMedia(query);
+ const listener = (e: MediaQueryListEvent) => {
+ if (process.env.NODE_ENV !== "production") {
+ console.info(`Media query change: ${query}`, e.matches);
+ }
+ setMatch(e.matches);
+ };
+ matchMedia.addEventListener("change", listener);
+ setMatch(matchMedia.matches);
+ return () => matchMedia.removeEventListener("change", listener);
+ }, [query]);
+ return match;
+}
diff --git a/docs/website/src/pages/index.js b/docs/website/src/pages/index.js
deleted file mode 100644
index 20efa4c6be1..00000000000
--- a/docs/website/src/pages/index.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from "react";
-import clsx from "clsx";
-import Layout from "@theme/Layout";
-import Link from "@docusaurus/Link";
-import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
-import styles from "./index.module.css";
-import HomepageFeatures from "@site/src/components/HomepageFeatures";
-
-function HomepageHeader() {
- const { siteConfig } = useDocusaurusContext();
- return (
-
- );
-}
-
-export default function Home() {
- const { siteConfig } = useDocusaurusContext();
- return (
-
-
-
-
-
-
- );
-}
diff --git a/docs/website/src/pages/index.tsx b/docs/website/src/pages/index.tsx
new file mode 100644
index 00000000000..2f886200810
--- /dev/null
+++ b/docs/website/src/pages/index.tsx
@@ -0,0 +1,28 @@
+import React from "react";
+import Layout from "@theme/Layout";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import { PageContext, PageType } from "../context/PageContext";
+import HomepageHero from "../components/HomepageHero";
+import Features from "../components/Features";
+import WhyMithril from "../components/WhyMithril";
+import AnimatedText from "../components/AnimatedText";
+import UseCases from "../components/UseCases";
+
+export default function Home() {
+ const { siteConfig } = useDocusaurusContext();
+ return (
+
+
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Copyright/index.tsx b/docs/website/src/theme/Footer/Copyright/index.tsx
new file mode 100644
index 00000000000..508da70acb0
--- /dev/null
+++ b/docs/website/src/theme/Footer/Copyright/index.tsx
@@ -0,0 +1,13 @@
+import React, { type ReactNode } from "react";
+import type { Props } from "@theme/Footer/Copyright";
+
+export default function FooterCopyright({ copyright }: Props): ReactNode {
+ return (
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Layout/index.tsx b/docs/website/src/theme/Footer/Layout/index.tsx
new file mode 100644
index 00000000000..dbf8df940e8
--- /dev/null
+++ b/docs/website/src/theme/Footer/Layout/index.tsx
@@ -0,0 +1,23 @@
+import React, { type ReactNode } from "react";
+import type { Props } from "@theme/Footer/Layout";
+import clsx from "clsx";
+
+export default function FooterLayout({
+ links,
+ logo,
+ copyright,
+}: Props): ReactNode {
+ return (
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/LinkItem/index.tsx b/docs/website/src/theme/Footer/LinkItem/index.tsx
new file mode 100644
index 00000000000..5aedc324ba6
--- /dev/null
+++ b/docs/website/src/theme/Footer/LinkItem/index.tsx
@@ -0,0 +1,28 @@
+import React, { type ReactNode } from "react";
+import clsx from "clsx";
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+
+import type { Props } from "@theme/Footer/LinkItem";
+
+export default function FooterLinkItem({ item }: Props): ReactNode {
+ const { to, href, label, prependBaseUrlToHref, className, ...props } = item;
+ const toUrl = useBaseUrl(to);
+ const normalizedHref = useBaseUrl(href, { forcePrependBaseUrl: true });
+
+ return (
+
+ {label}
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Links/MultiColumn/index.tsx b/docs/website/src/theme/Footer/Links/MultiColumn/index.tsx
new file mode 100644
index 00000000000..dec1797ad7e
--- /dev/null
+++ b/docs/website/src/theme/Footer/Links/MultiColumn/index.tsx
@@ -0,0 +1,45 @@
+import React, { type ReactNode } from "react";
+import clsx from "clsx";
+import LinkItem from "@theme/Footer/LinkItem";
+import type { Props } from "@theme/Footer/Links/MultiColumn";
+
+type ColumnType = Props["columns"][number];
+type ColumnItemType = ColumnType["items"][number];
+
+function ColumnLinkItem({ item }: { item: ColumnItemType }) {
+ return item.html ? (
+
+ ) : (
+
+
+
+ );
+}
+
+function Column({ column }: { column: ColumnType }) {
+ return (
+
+
{column.title}
+
+ {column.items.map((item, i) => (
+
+ ))}
+
+
+ );
+}
+
+export default function FooterLinksMultiColumn({ columns }: Props): ReactNode {
+ return (
+
+ {columns.map((column, i) => (
+
+ ))}
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Links/Simple/index.tsx b/docs/website/src/theme/Footer/Links/Simple/index.tsx
new file mode 100644
index 00000000000..fc4f2ec25be
--- /dev/null
+++ b/docs/website/src/theme/Footer/Links/Simple/index.tsx
@@ -0,0 +1,36 @@
+import React, { type ReactNode } from "react";
+import clsx from "clsx";
+import LinkItem from "@theme/Footer/LinkItem";
+import type { Props } from "@theme/Footer/Links/Simple";
+
+function Separator() {
+ return · ;
+}
+
+function SimpleLinkItem({ item }: { item: Props["links"][number] }) {
+ return item.html ? (
+
+ ) : (
+
+ );
+}
+
+export default function FooterLinksSimple({ links }: Props): ReactNode {
+ return (
+
+
+ {links.map((item, i) => (
+
+
+ {links.length !== i + 1 && }
+
+ ))}
+
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Links/index.tsx b/docs/website/src/theme/Footer/Links/index.tsx
new file mode 100644
index 00000000000..76bd9f47bfd
--- /dev/null
+++ b/docs/website/src/theme/Footer/Links/index.tsx
@@ -0,0 +1,14 @@
+import React, { type ReactNode } from "react";
+
+import { isMultiColumnFooterLinks } from "@docusaurus/theme-common";
+import FooterLinksMultiColumn from "@theme/Footer/Links/MultiColumn";
+import FooterLinksSimple from "@theme/Footer/Links/Simple";
+import type { Props } from "@theme/Footer/Links";
+
+export default function FooterLinks({ links }: Props): ReactNode {
+ return isMultiColumnFooterLinks(links) ? (
+
+ ) : (
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Logo/index.tsx b/docs/website/src/theme/Footer/Logo/index.tsx
new file mode 100644
index 00000000000..e7427e7320d
--- /dev/null
+++ b/docs/website/src/theme/Footer/Logo/index.tsx
@@ -0,0 +1,43 @@
+import React, { type ReactNode } from "react";
+import clsx from "clsx";
+import Link from "@docusaurus/Link";
+import { useBaseUrlUtils } from "@docusaurus/useBaseUrl";
+import ThemedImage from "@theme/ThemedImage";
+import type { Props } from "@theme/Footer/Logo";
+
+import styles from "./styles.module.css";
+
+function LogoImage({ logo }: Props) {
+ const { withBaseUrl } = useBaseUrlUtils();
+ const sources = {
+ light: withBaseUrl(logo.src),
+ dark: withBaseUrl(logo.srcDark ?? logo.src),
+ };
+ return (
+
+ );
+}
+
+export default function FooterLogo({ logo }: Props): ReactNode {
+ return logo.href ? (
+
+
+
+ ) : (
+
+
+
Mithril
+
+ );
+}
diff --git a/docs/website/src/theme/Footer/Logo/styles.module.css b/docs/website/src/theme/Footer/Logo/styles.module.css
new file mode 100644
index 00000000000..faf0e60f3e1
--- /dev/null
+++ b/docs/website/src/theme/Footer/Logo/styles.module.css
@@ -0,0 +1,9 @@
+.footerLogoLink {
+ opacity: 0.5;
+ transition: opacity var(--ifm-transition-fast)
+ var(--ifm-transition-timing-default);
+}
+
+.footerLogoLink:hover {
+ opacity: 1;
+}
diff --git a/docs/website/src/theme/Footer/index.tsx b/docs/website/src/theme/Footer/index.tsx
new file mode 100644
index 00000000000..a7862df9410
--- /dev/null
+++ b/docs/website/src/theme/Footer/index.tsx
@@ -0,0 +1,26 @@
+import React, { type ReactNode } from "react";
+
+import { useThemeConfig } from "@docusaurus/theme-common";
+import FooterLinks from "@theme/Footer/Links";
+import FooterLogo from "@theme/Footer/Logo";
+import FooterCopyright from "@theme/Footer/Copyright";
+import FooterLayout from "@theme/Footer/Layout";
+
+function Footer(): ReactNode {
+ const { footer } = useThemeConfig();
+ if (!footer) {
+ return null;
+ }
+ const { copyright, links, logo, style } = footer;
+
+ return (
+ 0 && }
+ logo={logo && }
+ copyright={copyright && }
+ />
+ );
+}
+
+export default React.memo(Footer);
diff --git a/docs/website/src/theme/Navbar/Content/index.tsx b/docs/website/src/theme/Navbar/Content/index.tsx
new file mode 100644
index 00000000000..2c98c10ac46
--- /dev/null
+++ b/docs/website/src/theme/Navbar/Content/index.tsx
@@ -0,0 +1,93 @@
+import React from "react";
+import { useThemeConfig, ErrorCauseBoundary } from "@docusaurus/theme-common";
+import {
+ splitNavbarItems,
+ useNavbarMobileSidebar,
+} from "@docusaurus/theme-common/internal";
+import NavbarItem from "@theme/NavbarItem";
+import NavbarColorModeToggle from "@theme/Navbar/ColorModeToggle";
+import SearchBar from "@theme/SearchBar";
+import NavbarMobileSidebarToggle from "@theme/Navbar/MobileSidebar/Toggle";
+import NavbarLogo from "@theme/Navbar/Logo";
+import NavbarSearch from "@theme/Navbar/Search";
+import styles from "./styles.module.css";
+import Discord from "../../../components/icons/Discord";
+import Github from "../../../components/icons/Github";
+
+function useNavbarItems() {
+ // TODO temporary casting until ThemeConfig type is improved
+ return useThemeConfig().navbar.items;
+}
+function NavbarItems({ items }) {
+ return (
+ <>
+ {items.map((item, i) => (
+
+ new Error(
+ `A theme navbar item failed to render.
+Please double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:
+${JSON.stringify(item, null, 2)}`,
+ { cause: error },
+ )
+ }
+ >
+
+
+ ))}
+ >
+ );
+}
+function NavbarContentLayout({ left, right }) {
+ return (
+
+ );
+}
+export default function NavbarContent() {
+ const mobileSidebar = useNavbarMobileSidebar();
+ const items = useNavbarItems();
+ const [leftItems, rightItems] = splitNavbarItems(items);
+ const searchBarItem = items.find((item) => item.type === "search");
+ return (
+
+
+
+ >
+ }
+ right={
+ <>
+
+
+ {!searchBarItem && (
+
+
+
+ )}
+
+
+
+
+
+
+ {!mobileSidebar.disabled && }
+ >
+ }
+ />
+ );
+}
diff --git a/docs/website/src/theme/Navbar/Content/styles.module.css b/docs/website/src/theme/Navbar/Content/styles.module.css
new file mode 100644
index 00000000000..4c9471e1098
--- /dev/null
+++ b/docs/website/src/theme/Navbar/Content/styles.module.css
@@ -0,0 +1,8 @@
+/*
+Hide color mode toggle in small viewports
+ */
+@media (max-width: 996px) {
+ .colorModeToggle {
+ display: none;
+ }
+}
diff --git a/docs/website/src/theme/Navbar/Layout/index.tsx b/docs/website/src/theme/Navbar/Layout/index.tsx
new file mode 100644
index 00000000000..7072c3c07d8
--- /dev/null
+++ b/docs/website/src/theme/Navbar/Layout/index.tsx
@@ -0,0 +1,77 @@
+import React from "react";
+import clsx from "clsx";
+import { useThemeConfig } from "@docusaurus/theme-common";
+import {
+ useHideableNavbar,
+ useNavbarMobileSidebar,
+} from "@docusaurus/theme-common/internal";
+import { translate } from "@docusaurus/Translate";
+import NavbarMobileSidebar from "@theme/Navbar/MobileSidebar";
+import styles from "./styles.module.css";
+
+import { useScroll, motion, useTransform } from "framer-motion";
+import { useIsLandingPage } from "../../../hooks/useIsLandingPage";
+
+function NavbarBackdrop(props) {
+ return (
+
+ );
+}
+export default function NavbarLayout({ children }) {
+ const { scrollY } = useScroll();
+ const y = useTransform(
+ scrollY,
+ [0, 70],
+ ["rgba(255, 255, 255, 0)", "rgba(255, 255, 255, 0.96)"],
+ );
+ const isLandingPage = useIsLandingPage();
+ const {
+ navbar: { hideOnScroll },
+ } = useThemeConfig();
+ const mobileSidebar = useNavbarMobileSidebar();
+ const { navbarRef, isNavbarVisible } = useHideableNavbar(hideOnScroll);
+ return (
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/docs/website/src/theme/Navbar/Layout/styles.module.css b/docs/website/src/theme/Navbar/Layout/styles.module.css
new file mode 100644
index 00000000000..e72891a44ff
--- /dev/null
+++ b/docs/website/src/theme/Navbar/Layout/styles.module.css
@@ -0,0 +1,7 @@
+.navbarHideable {
+ transition: transform var(--ifm-transition-fast) ease;
+}
+
+.navbarHidden {
+ transform: translate3d(0, calc(-100% - 2px), 0);
+}
diff --git a/docs/website/src/theme/Navbar/MobileSidebar/Header/index.tsx b/docs/website/src/theme/Navbar/MobileSidebar/Header/index.tsx
new file mode 100644
index 00000000000..b2af39a48a7
--- /dev/null
+++ b/docs/website/src/theme/Navbar/MobileSidebar/Header/index.tsx
@@ -0,0 +1,34 @@
+import React, { type ReactNode } from "react";
+import { useNavbarMobileSidebar } from "@docusaurus/theme-common/internal";
+import { translate } from "@docusaurus/Translate";
+import NavbarColorModeToggle from "@theme/Navbar/ColorModeToggle";
+import IconClose from "@theme/Icon/Close";
+import NavbarLogo from "@theme/Navbar/Logo";
+
+function CloseButton() {
+ const mobileSidebar = useNavbarMobileSidebar();
+ return (
+ mobileSidebar.toggle()}
+ >
+
+
+ );
+}
+
+export default function NavbarMobileSidebarHeader(): ReactNode {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/docs/website/src/theme/Navbar/MobileSidebar/Layout/index.tsx b/docs/website/src/theme/Navbar/MobileSidebar/Layout/index.tsx
new file mode 100644
index 00000000000..18659aa1846
--- /dev/null
+++ b/docs/website/src/theme/Navbar/MobileSidebar/Layout/index.tsx
@@ -0,0 +1,25 @@
+import React, { type ReactNode } from "react";
+import clsx from "clsx";
+import { useNavbarSecondaryMenu } from "@docusaurus/theme-common/internal";
+import type { Props } from "@theme/Navbar/MobileSidebar/Layout";
+
+export default function NavbarMobileSidebarLayout({
+ header,
+ primaryMenu,
+ secondaryMenu,
+}: Props): ReactNode {
+ const { shown: secondaryMenuShown } = useNavbarSecondaryMenu();
+ return (
+
+ {header}
+
+
{primaryMenu}
+
{secondaryMenu}
+
+
+ );
+}
diff --git a/docs/website/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx b/docs/website/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx
new file mode 100644
index 00000000000..4e8f3d918c6
--- /dev/null
+++ b/docs/website/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsx
@@ -0,0 +1,40 @@
+import React, { type ReactNode } from "react";
+import { useThemeConfig } from "@docusaurus/theme-common";
+import { useNavbarMobileSidebar } from "@docusaurus/theme-common/internal";
+import NavbarItem, { type Props as NavbarItemConfig } from "@theme/NavbarItem";
+import Discord from "../../../../components/icons/Discord";
+
+function useNavbarItems() {
+ // TODO temporary casting until ThemeConfig type is improved
+ return useThemeConfig().navbar.items as NavbarItemConfig[];
+}
+
+// The primary menu displays the navbar items
+export default function NavbarMobilePrimaryMenu(): ReactNode {
+ const mobileSidebar = useNavbarMobileSidebar();
+
+ // TODO how can the order be defined for mobile?
+ // Should we allow providing a different list of items?
+ const items = useNavbarItems();
+
+ return (
+
+ {items.map((item, i) => (
+ mobileSidebar.toggle()}
+ key={i}
+ />
+ ))}
+
+
+
+
+ );
+}
diff --git a/docs/website/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.tsx b/docs/website/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.tsx
new file mode 100644
index 00000000000..cc9aa9eea34
--- /dev/null
+++ b/docs/website/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.tsx
@@ -0,0 +1,33 @@
+import React, { type ComponentProps, type ReactNode } from "react";
+import { useThemeConfig } from "@docusaurus/theme-common";
+import { useNavbarSecondaryMenu } from "@docusaurus/theme-common/internal";
+import Translate from "@docusaurus/Translate";
+
+function SecondaryMenuBackButton(props: ComponentProps<"button">) {
+ return (
+
+
+
+ );
+}
+
+// The secondary menu slides from the right and shows contextual information
+// such as the docs sidebar
+export default function NavbarMobileSidebarSecondaryMenu(): ReactNode {
+ const isPrimaryMenuEmpty = useThemeConfig().navbar.items.length === 0;
+ const secondaryMenu = useNavbarSecondaryMenu();
+ return (
+ <>
+ {/* edge-case: prevent returning to the primaryMenu when it's empty */}
+ {!isPrimaryMenuEmpty && (
+ secondaryMenu.hide()} />
+ )}
+ {secondaryMenu.content}
+ >
+ );
+}
diff --git a/docs/website/src/theme/Navbar/MobileSidebar/Toggle/index.tsx b/docs/website/src/theme/Navbar/MobileSidebar/Toggle/index.tsx
new file mode 100644
index 00000000000..89237cf77ef
--- /dev/null
+++ b/docs/website/src/theme/Navbar/MobileSidebar/Toggle/index.tsx
@@ -0,0 +1,24 @@
+import React, { type ReactNode } from "react";
+import { useNavbarMobileSidebar } from "@docusaurus/theme-common/internal";
+import { translate } from "@docusaurus/Translate";
+import IconMenu from "@theme/Icon/Menu";
+
+export default function MobileSidebarToggle(): ReactNode {
+ const { toggle, shown } = useNavbarMobileSidebar();
+ return (
+
+
+
+ );
+}
diff --git a/docs/website/src/theme/Navbar/MobileSidebar/index.tsx b/docs/website/src/theme/Navbar/MobileSidebar/index.tsx
new file mode 100644
index 00000000000..50bf4c629fd
--- /dev/null
+++ b/docs/website/src/theme/Navbar/MobileSidebar/index.tsx
@@ -0,0 +1,26 @@
+import React, { type ReactNode } from "react";
+import {
+ useLockBodyScroll,
+ useNavbarMobileSidebar,
+} from "@docusaurus/theme-common/internal";
+import NavbarMobileSidebarLayout from "@theme/Navbar/MobileSidebar/Layout";
+import NavbarMobileSidebarHeader from "@theme/Navbar/MobileSidebar/Header";
+import NavbarMobileSidebarPrimaryMenu from "@theme/Navbar/MobileSidebar/PrimaryMenu";
+import NavbarMobileSidebarSecondaryMenu from "@theme/Navbar/MobileSidebar/SecondaryMenu";
+
+export default function NavbarMobileSidebar(): ReactNode {
+ const mobileSidebar = useNavbarMobileSidebar();
+ useLockBodyScroll(mobileSidebar.shown);
+
+ if (!mobileSidebar.shouldRender) {
+ return null;
+ }
+
+ return (
+ }
+ primaryMenu={ }
+ secondaryMenu={ }
+ />
+ );
+}
diff --git a/docs/website/src/theme/Navbar/Search/index.tsx b/docs/website/src/theme/Navbar/Search/index.tsx
new file mode 100644
index 00000000000..ea6d3d7d325
--- /dev/null
+++ b/docs/website/src/theme/Navbar/Search/index.tsx
@@ -0,0 +1,16 @@
+import React, { type ReactNode } from "react";
+import clsx from "clsx";
+import type { Props } from "@theme/Navbar/Search";
+
+import styles from "./styles.module.css";
+
+export default function NavbarSearch({
+ children,
+ className,
+}: Props): ReactNode {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/docs/website/src/theme/Navbar/Search/styles.module.css b/docs/website/src/theme/Navbar/Search/styles.module.css
new file mode 100644
index 00000000000..9eeb2934d46
--- /dev/null
+++ b/docs/website/src/theme/Navbar/Search/styles.module.css
@@ -0,0 +1,21 @@
+/*
+Workaround to avoid rendering empty search container
+See https://github.com/facebook/docusaurus/pull/9385
+*/
+.navbarSearchContainer:empty {
+ display: none;
+}
+
+@media (max-width: 996px) {
+ .navbarSearchContainer {
+ position: absolute;
+ right: var(--ifm-navbar-padding-horizontal);
+ }
+}
+
+@media (min-width: 997px) {
+ .navbarSearchContainer {
+ padding: var(--ifm-navbar-item-padding-vertical)
+ var(--ifm-navbar-item-padding-horizontal);
+ }
+}
diff --git a/docs/website/src/theme/Navbar/index.tsx b/docs/website/src/theme/Navbar/index.tsx
new file mode 100644
index 00000000000..ecae8f8d1c0
--- /dev/null
+++ b/docs/website/src/theme/Navbar/index.tsx
@@ -0,0 +1,11 @@
+import React, { type ReactNode } from "react";
+import NavbarLayout from "@theme/Navbar/Layout";
+import NavbarContent from "@theme/Navbar/Content";
+
+export default function Navbar(): ReactNode {
+ return (
+
+
+
+ );
+}
diff --git a/docs/website/static/desktop-mithril-hero-original.mp4 b/docs/website/static/desktop-mithril-hero-original.mp4
new file mode 100644
index 00000000000..d472a162724
Binary files /dev/null and b/docs/website/static/desktop-mithril-hero-original.mp4 differ
diff --git a/docs/website/static/desktop-mithril-hero-thumbnail.jpg b/docs/website/static/desktop-mithril-hero-thumbnail.jpg
new file mode 100644
index 00000000000..087d1dbe140
Binary files /dev/null and b/docs/website/static/desktop-mithril-hero-thumbnail.jpg differ
diff --git a/docs/website/static/fonts/Inter-Italic-VariableFont.ttf b/docs/website/static/fonts/Inter-Italic-VariableFont.ttf
new file mode 100644
index 00000000000..43ed4f5ee6c
Binary files /dev/null and b/docs/website/static/fonts/Inter-Italic-VariableFont.ttf differ
diff --git a/docs/website/static/fonts/Inter-VariableFont.ttf b/docs/website/static/fonts/Inter-VariableFont.ttf
new file mode 100644
index 00000000000..e31b51e3e93
Binary files /dev/null and b/docs/website/static/fonts/Inter-VariableFont.ttf differ
diff --git a/docs/website/static/fonts/Lexend-VariableFont.ttf b/docs/website/static/fonts/Lexend-VariableFont.ttf
new file mode 100644
index 00000000000..b294dc840ff
Binary files /dev/null and b/docs/website/static/fonts/Lexend-VariableFont.ttf differ
diff --git a/docs/website/static/img/mithril-logo-dark.svg b/docs/website/static/img/mithril-logo-dark.svg
new file mode 100644
index 00000000000..3dcbb30b3b9
--- /dev/null
+++ b/docs/website/static/img/mithril-logo-dark.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/website/static/img/mithril-logo-text.svg b/docs/website/static/img/mithril-logo-text.svg
new file mode 100644
index 00000000000..576b049936e
--- /dev/null
+++ b/docs/website/static/img/mithril-logo-text.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/website/static/img/logo.svg b/docs/website/static/img/mithril-logo.svg
similarity index 100%
rename from docs/website/static/img/logo.svg
rename to docs/website/static/img/mithril-logo.svg
diff --git a/docs/website/static/mobile-mithril-hero-original.mp4 b/docs/website/static/mobile-mithril-hero-original.mp4
new file mode 100644
index 00000000000..f079e42cd69
Binary files /dev/null and b/docs/website/static/mobile-mithril-hero-original.mp4 differ
diff --git a/docs/website/static/mobile-mithril-hero-thumbnail.jpg b/docs/website/static/mobile-mithril-hero-thumbnail.jpg
new file mode 100644
index 00000000000..12fd64c1385
Binary files /dev/null and b/docs/website/static/mobile-mithril-hero-thumbnail.jpg differ
diff --git a/docs/website/tailwind.config.ts b/docs/website/tailwind.config.ts
new file mode 100644
index 00000000000..8e9ba679955
--- /dev/null
+++ b/docs/website/tailwind.config.ts
@@ -0,0 +1,68 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ content: ["./src/**/*.{js,jsx,ts,tsx}"],
+ theme: {
+ backgroundImage: {},
+ screens: {
+ phablet: "640px",
+ // => @media (min-width: 640px) { ... }
+
+ tablet: "768px",
+ // => @media (min-width: 768px) { ... }
+
+ laptop: "996px",
+ // => @media (min-width: 996px) { ... }
+
+ desktop: "1280px",
+ // => @media (min-width: 1280px) { ... }
+ },
+ fontFamily: {
+ display: [
+ "Bw Gradual",
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ '"Apple Color Emoji"',
+ '"Segoe UI Emoji"',
+ '"Segoe UI Symbol"',
+ '"Noto Color Emoji"',
+ ],
+ body: [
+ "var(--font-lexend)",
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ '"Apple Color Emoji"',
+ '"Segoe UI Emoji"',
+ '"Segoe UI Symbol"',
+ '"Noto Color Emoji"',
+ ],
+ },
+ colors: {
+ transparent: "transparent",
+ current: "currentColor",
+ blue: {
+ DEFAULT: "#01193C",
+ light: "#ECF9FD",
+ highlight: "#2634AD",
+ },
+ secondary: "#3c9ec8",
+ black: "#000000",
+ gray: {
+ DEFAULT: "#7C8080",
+ dark: "#99a3b1",
+ light: "#808C9D",
+ "extra-light": "#F3F4F4",
+ border: "#B3BAC5",
+ },
+ white: "#FFFFFF",
+ cyan: {
+ DEFAULT: "#65CFE1",
+ dark: "#397589",
+ },
+ },
+ },
+ plugins: [],
+};
+export default config;