diff --git a/utils/website/src/theme/Footer/Copyright/index.js b/utils/website/src/theme/Footer/Copyright/index.js
new file mode 100644
index 000000000..d239a7a26
--- /dev/null
+++ b/utils/website/src/theme/Footer/Copyright/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+export default function FooterCopyright({copyright}) {
+ return (
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/Layout/index.js b/utils/website/src/theme/Footer/Layout/index.js
new file mode 100644
index 000000000..6eca7177e
--- /dev/null
+++ b/utils/website/src/theme/Footer/Layout/index.js
@@ -0,0 +1,26 @@
+import React from "react";
+import clsx from "clsx";
+import styles from "../index.module.css";
+export default function FooterLayout({ style, links, logo, copyright }) {
+ return (
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/LinkItem/index.js b/utils/website/src/theme/Footer/LinkItem/index.js
new file mode 100644
index 000000000..f1a6e84e5
--- /dev/null
+++ b/utils/website/src/theme/Footer/LinkItem/index.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import Link from '@docusaurus/Link';
+import useBaseUrl from '@docusaurus/useBaseUrl';
+import isInternalUrl from '@docusaurus/isInternalUrl';
+import IconExternalLink from '@theme/Icon/ExternalLink';
+export default function FooterLinkItem({item}) {
+ const {to, href, label, prependBaseUrlToHref, ...props} = item;
+ const toUrl = useBaseUrl(to);
+ const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
+ return (
+
+ {label}
+ {href && !isInternalUrl(href) && }
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/Links/MultiColumn/index.js b/utils/website/src/theme/Footer/Links/MultiColumn/index.js
new file mode 100644
index 000000000..79ff51db9
--- /dev/null
+++ b/utils/website/src/theme/Footer/Links/MultiColumn/index.js
@@ -0,0 +1,37 @@
+import React from 'react';
+import LinkItem from '@theme/Footer/LinkItem';
+function ColumnLinkItem({item}) {
+ return item.html ? (
+
+ ) : (
+
+
+
+ );
+}
+function Column({column}) {
+ return (
+
+
{column.title}
+
+ {column.items.map((item, i) => (
+
+ ))}
+
+
+ );
+}
+export default function FooterLinksMultiColumn({columns}) {
+ return (
+
+ {columns.map((column, i) => (
+
+ ))}
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/Links/Simple/index.js b/utils/website/src/theme/Footer/Links/Simple/index.js
new file mode 100644
index 000000000..8b34d9b7b
--- /dev/null
+++ b/utils/website/src/theme/Footer/Links/Simple/index.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import LinkItem from '@theme/Footer/LinkItem';
+function Separator() {
+ return ·;
+}
+function SimpleLinkItem({item}) {
+ return item.html ? (
+
+ ) : (
+
+ );
+}
+export default function FooterLinksSimple({links}) {
+ return (
+
+
+ {links.map((item, i) => (
+
+
+ {links.length !== i + 1 && }
+
+ ))}
+
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/Links/index.js b/utils/website/src/theme/Footer/Links/index.js
new file mode 100644
index 000000000..5da2258b8
--- /dev/null
+++ b/utils/website/src/theme/Footer/Links/index.js
@@ -0,0 +1,11 @@
+import React from 'react';
+import {isMultiColumnFooterLinks} from '@docusaurus/theme-common';
+import FooterLinksMultiColumn from '@theme/Footer/Links/MultiColumn';
+import FooterLinksSimple from '@theme/Footer/Links/Simple';
+export default function FooterLinks({links}) {
+ return isMultiColumnFooterLinks(links) ? (
+
+ ) : (
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/Logo/index.js b/utils/website/src/theme/Footer/Logo/index.js
new file mode 100644
index 000000000..2fdd1ab6a
--- /dev/null
+++ b/utils/website/src/theme/Footer/Logo/index.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import clsx from 'clsx';
+import Link from '@docusaurus/Link';
+import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
+import ThemedImage from '@theme/ThemedImage';
+import styles from './styles.module.css';
+function LogoImage({logo}) {
+ const {withBaseUrl} = useBaseUrlUtils();
+ const sources = {
+ light: withBaseUrl(logo.src),
+ dark: withBaseUrl(logo.srcDark ?? logo.src),
+ };
+ return (
+
+ );
+}
+export default function FooterLogo({logo}) {
+ return logo.href ? (
+
+
+
+ ) : (
+
+ );
+}
diff --git a/utils/website/src/theme/Footer/Logo/styles.module.css b/utils/website/src/theme/Footer/Logo/styles.module.css
new file mode 100644
index 000000000..faf0e60f3
--- /dev/null
+++ b/utils/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/utils/website/src/theme/Footer/index.js b/utils/website/src/theme/Footer/index.js
new file mode 100644
index 000000000..0b91cc918
--- /dev/null
+++ b/utils/website/src/theme/Footer/index.js
@@ -0,0 +1,22 @@
+import React 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() {
+ 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/utils/website/src/theme/Footer/index.module.css b/utils/website/src/theme/Footer/index.module.css
new file mode 100644
index 000000000..c93f04655
--- /dev/null
+++ b/utils/website/src/theme/Footer/index.module.css
@@ -0,0 +1,10 @@
+/**
+ * CSS files with the .module.css suffix will be treated as CSS modules
+ * and scoped locally.
+ */
+.footerImage {
+ background-position: center center;
+ background-repeat: repeat;
+ background-image: url("/img/trees.svg");
+ height: 200px;
+}
diff --git a/utils/website/static/img/graphile-star.svg b/utils/website/static/img/graphile-star.svg
new file mode 100644
index 000000000..06725b50b
--- /dev/null
+++ b/utils/website/static/img/graphile-star.svg
@@ -0,0 +1,211 @@
+
+
+
+
diff --git a/utils/website/static/img/sky-light.svg b/utils/website/static/img/sky-light.svg
new file mode 100644
index 000000000..7f83c823f
--- /dev/null
+++ b/utils/website/static/img/sky-light.svg
@@ -0,0 +1,33212 @@
+
+
+
+
diff --git a/utils/website/static/img/trees.svg b/utils/website/static/img/trees.svg
new file mode 100644
index 000000000..795126751
--- /dev/null
+++ b/utils/website/static/img/trees.svg
@@ -0,0 +1,92796 @@
+
+
+
+