diff --git a/.gitignore b/.gitignore
index 440f7ecbbc..c3f3e38c93 100644
--- a/.gitignore
+++ b/.gitignore
@@ -94,4 +94,4 @@ apps/stats-dapp/graphql.schema.json
.direnv
# Generated by json files
-/**/generated/**/*.json
+/**/generated/**/*.json
\ No newline at end of file
diff --git a/apps/hubble-stats/.eslintrc.json b/apps/hubble-stats/.eslintrc.json
new file mode 100644
index 0000000000..af23ce730f
--- /dev/null
+++ b/apps/hubble-stats/.eslintrc.json
@@ -0,0 +1,34 @@
+{
+ "extends": [
+ "plugin:@nx/react-typescript",
+ "next",
+ "next/core-web-vitals",
+ "../../.eslintrc.json"
+ ],
+ "ignorePatterns": ["!**/*", ".next/**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {
+ "@next/next/no-html-link-for-pages": [
+ "error",
+ "apps/hubble-stats/pages"
+ ]
+ }
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ],
+ "rules": {
+ "@next/next/no-html-link-for-pages": "off"
+ },
+ "env": {
+ "jest": true
+ }
+}
diff --git a/apps/hubble-stats/.vscode/settings.json b/apps/hubble-stats/.vscode/settings.json
new file mode 100644
index 0000000000..d3fdae9a69
--- /dev/null
+++ b/apps/hubble-stats/.vscode/settings.json
@@ -0,0 +1,4 @@
+{
+ "typescript.tsdk": "../../node_modules/typescript/lib",
+ "typescript.enablePromptUseWorkspaceTsdk": true
+}
\ No newline at end of file
diff --git a/apps/hubble-stats/app/api/hello/route.ts b/apps/hubble-stats/app/api/hello/route.ts
new file mode 100644
index 0000000000..de70bac64e
--- /dev/null
+++ b/apps/hubble-stats/app/api/hello/route.ts
@@ -0,0 +1,3 @@
+export async function GET(request: Request) {
+ return new Response('Hello, from API!');
+}
diff --git a/apps/hubble-stats/app/layout.tsx b/apps/hubble-stats/app/layout.tsx
new file mode 100644
index 0000000000..d1918a032c
--- /dev/null
+++ b/apps/hubble-stats/app/layout.tsx
@@ -0,0 +1,36 @@
+'use client';
+
+import { useEffect } from 'react';
+import Head from 'next/head';
+import {
+ WebbUIProvider,
+ useDarkMode,
+ Footer,
+} from '@webb-tools/webb-ui-components';
+import '@webb-tools/webb-ui-components/tailwind.css';
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ const [, setIsDarkMode] = useDarkMode();
+
+ useEffect(() => {
+ setIsDarkMode('light');
+ }, [setIsDarkMode]);
+
+ return (
+
+
+
+ Welcome to Hubble Stats!
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/apps/hubble-stats/app/page.tsx b/apps/hubble-stats/app/page.tsx
new file mode 100644
index 0000000000..74d30483eb
--- /dev/null
+++ b/apps/hubble-stats/app/page.tsx
@@ -0,0 +1,3 @@
+export default async function Index() {
+ return
;
+}
diff --git a/apps/hubble-stats/index.d.ts b/apps/hubble-stats/index.d.ts
new file mode 100644
index 0000000000..7ba08fa17c
--- /dev/null
+++ b/apps/hubble-stats/index.d.ts
@@ -0,0 +1,6 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+declare module '*.svg' {
+ const content: any;
+ export const ReactComponent: any;
+ export default content;
+}
diff --git a/apps/hubble-stats/jest.config.ts b/apps/hubble-stats/jest.config.ts
new file mode 100644
index 0000000000..12df35a939
--- /dev/null
+++ b/apps/hubble-stats/jest.config.ts
@@ -0,0 +1,11 @@
+/* eslint-disable */
+export default {
+ displayName: 'hubble-stats',
+ preset: '../../jest.preset.js',
+ transform: {
+ '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest',
+ '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/next/babel'] }],
+ },
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
+ coverageDirectory: '../../coverage/apps/hubble-stats',
+};
diff --git a/apps/hubble-stats/next-env.d.ts b/apps/hubble-stats/next-env.d.ts
new file mode 100644
index 0000000000..4f11a03dc6
--- /dev/null
+++ b/apps/hubble-stats/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/apps/hubble-stats/next.config.js b/apps/hubble-stats/next.config.js
new file mode 100644
index 0000000000..937828ba70
--- /dev/null
+++ b/apps/hubble-stats/next.config.js
@@ -0,0 +1,26 @@
+//@ts-check
+
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const { composePlugins, withNx } = require('@nx/next');
+
+/**
+ * @type {import('@nx/next/plugins/with-nx').WithNxOptions}
+ **/
+const nextConfig = {
+ nx: {
+ // Set this to true if you would like to use SVGR
+ // See: https://github.com/gregberge/svgr
+ svgr: false,
+ },
+
+ experimental: {
+ appDir: true,
+ },
+};
+
+const plugins = [
+ // Add more Next.js plugins to this list if needed.
+ withNx,
+];
+
+module.exports = composePlugins(...plugins)(nextConfig);
diff --git a/apps/hubble-stats/postcss.config.js b/apps/hubble-stats/postcss.config.js
new file mode 100644
index 0000000000..15d89344f9
--- /dev/null
+++ b/apps/hubble-stats/postcss.config.js
@@ -0,0 +1,17 @@
+const { join } = require('path');
+
+// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build
+// option from your application's configuration (i.e. project.json).
+//
+// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries
+
+module.exports = {
+ plugins: {
+ 'postcss-import': {},
+ 'tailwindcss/nesting': {},
+ tailwindcss: {
+ config: join(__dirname, 'tailwind.config.js'),
+ },
+ autoprefixer: {},
+ },
+};
diff --git a/apps/hubble-stats/project.json b/apps/hubble-stats/project.json
new file mode 100644
index 0000000000..c49c004565
--- /dev/null
+++ b/apps/hubble-stats/project.json
@@ -0,0 +1,69 @@
+{
+ "name": "hubble-stats",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "apps/hubble-stats",
+ "projectType": "application",
+ "targets": {
+ "build": {
+ "executor": "@nx/next:build",
+ "outputs": ["{options.outputPath}"],
+ "defaultConfiguration": "production",
+ "options": {
+ "root": "apps/hubble-stats",
+ "outputPath": "dist/apps/hubble-stats"
+ },
+ "configurations": {
+ "development": {
+ "outputPath": "apps/hubble-stats"
+ },
+ "production": {}
+ }
+ },
+ "serve": {
+ "executor": "@nx/next:server",
+ "defaultConfiguration": "development",
+ "options": {
+ "buildTarget": "hubble-stats:build",
+ "dev": true
+ },
+ "configurations": {
+ "development": {
+ "buildTarget": "hubble-stats:build:development",
+ "dev": true
+ },
+ "production": {
+ "buildTarget": "hubble-stats:build:production",
+ "dev": false
+ }
+ }
+ },
+ "export": {
+ "executor": "@nx/next:export",
+ "options": {
+ "buildTarget": "hubble-stats:build:production"
+ }
+ },
+ "test": {
+ "executor": "@nx/jest:jest",
+ "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+ "options": {
+ "jestConfig": "apps/hubble-stats/jest.config.ts",
+ "passWithNoTests": true
+ },
+ "configurations": {
+ "ci": {
+ "ci": true,
+ "codeCoverage": true
+ }
+ }
+ },
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["apps/hubble-stats/**/*.{ts,tsx,js,jsx}"]
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/apps/hubble-stats/public/.gitkeep b/apps/hubble-stats/public/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/apps/hubble-stats/public/favicon.ico b/apps/hubble-stats/public/favicon.ico
new file mode 100644
index 0000000000..317ebcb233
Binary files /dev/null and b/apps/hubble-stats/public/favicon.ico differ
diff --git a/apps/hubble-stats/tailwind.config.js b/apps/hubble-stats/tailwind.config.js
new file mode 100644
index 0000000000..4a5e920aea
--- /dev/null
+++ b/apps/hubble-stats/tailwind.config.js
@@ -0,0 +1,25 @@
+const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
+const { join } = require('path');
+
+const preset = require('@webb-tools/tailwind-preset');
+
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ presets: [preset],
+ content: [
+ join(
+ __dirname,
+ '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}'
+ ),
+ join(
+ __dirname,
+ '../../libs/webb-ui-components',
+ 'src/{pages,components}/**/*!(*.stories|*.spec).{ts,tsx,html}'
+ ),
+ ...createGlobPatternsForDependencies(__dirname),
+ ],
+ theme: {
+ extend: {},
+ },
+ plugins: [],
+};
diff --git a/apps/hubble-stats/tsconfig.json b/apps/hubble-stats/tsconfig.json
new file mode 100644
index 0000000000..7138e84825
--- /dev/null
+++ b/apps/hubble-stats/tsconfig.json
@@ -0,0 +1,38 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "jsx": "preserve",
+ "allowJs": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "types": [
+ "jest",
+ "node"
+ ]
+ },
+ "include": [
+ "**/*.ts",
+ "**/*.tsx",
+ "**/*.js",
+ "**/*.jsx",
+ "next-env.d.ts",
+ "../../apps/hubble-stats/.next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules",
+ "jest.config.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.test.ts"
+ ]
+}
diff --git a/apps/hubble-stats/tsconfig.spec.json b/apps/hubble-stats/tsconfig.spec.json
new file mode 100644
index 0000000000..214b2cc208
--- /dev/null
+++ b/apps/hubble-stats/tsconfig.spec.json
@@ -0,0 +1,21 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["jest", "node"],
+ "jsx": "react"
+ },
+ "include": [
+ "jest.config.ts",
+ "src/**/*.test.ts",
+ "src/**/*.spec.ts",
+ "src/**/*.test.tsx",
+ "src/**/*.spec.tsx",
+ "src/**/*.test.js",
+ "src/**/*.spec.js",
+ "src/**/*.test.jsx",
+ "src/**/*.spec.jsx",
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/libs/webb-ui-components/src/css/layer-components.css b/libs/webb-ui-components/src/css/layer-components.css
index c41142ab92..31f5f5ea1f 100644
--- a/libs/webb-ui-components/src/css/layer-components.css
+++ b/libs/webb-ui-components/src/css/layer-components.css
@@ -117,7 +117,8 @@
}
.mkt-monospace {
- @apply text-[14px] leading-[20px] md:text-[16px] md:leading-[24px] font-satoshi-var;
+ @apply text-[14px] leading-[20px] md:text-[16px] md:leading-[24px];
+ fontfamily: 'Satoshi Variable';
}
@media screen and (max-width: 800px) {
diff --git a/nx.json b/nx.json
index 14cb67e7a5..913eaa9ff7 100644
--- a/nx.json
+++ b/nx.json
@@ -23,6 +23,7 @@
"{workspaceRoot}/dist/apps/bridge-dapp",
"{workspaceRoot}/dist/apps/stats-dapp",
"{workspaceRoot}/dist/apps/faucet/.next",
+ "{workspaceRoot}/dist/apps/hubble-stats/.next",
"{workspaceRoot}/dist/apps/tangle-website/.next",
"{workspaceRoot}/dist/apps/webbsite/.next"
]
diff --git a/package.json b/package.json
index 177ae7d99e..1cfc697d91 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"build:stats": "yarn gql:codegen && yarn nx build stats-dapp",
"build:webbsite": "nx build webbsite",
"build:tangle-website": "nx build tangle-website",
+ "build:hubble-stats": "nx build hubble-stats",
"build:storybook": "nx build-storybook webb-ui-components",
"build:faucet": "nx build faucet",
"export:faucet": "nx export faucet",
@@ -24,6 +25,7 @@
"start:stats": "yarn gql:codegen && yarn nx serve stats-dapp",
"start:webbsite": "nx serve webbsite",
"start:tangle-website": "nx serve tangle-website",
+ "start:hubble-stats": "nx serve hubble-stats",
"start:storybook": "nx storybook webb-ui-components",
"start:faucet": "nx serve faucet",
"format": "prettier --write \"{libs,apps,tools}/**/*.{ts,js,jsx,tsx,svg}\" ",
@@ -132,6 +134,7 @@
"rxjs": "7.8.1",
"snarkjs": "0.6.11",
"swiper": "^9.3.2",
+ "tslib": "^2.3.0",
"twitter-api-v2": "^1.14.2",
"use-local-storage-state": "^18.3.0",
"viem": "^0.3.41",
@@ -259,6 +262,7 @@
"prettier": "^2.8.8",
"process": "^0.11.10",
"react-refresh": "0.14.0",
+ "react-test-renderer": "18.2.0",
"readline": "^1.3.0",
"rollup": "^3.21.8",
"rollup-plugin-copy": "3.4.0",
diff --git a/yarn.lock b/yarn.lock
index b41965d4fe..835e1d953e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -21651,16 +21651,16 @@ react-is@^16.10.2, react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
react-is@^17.0.1:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
-react-is@^18.0.0:
- version "18.2.0"
- resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
- integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
-
react-lazy-images@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/react-lazy-images/-/react-lazy-images-1.1.0.tgz#c865445c96e568a6249db03a2bb2dccd49cb6f50"
@@ -21807,6 +21807,14 @@ react-router@6.11.1:
dependencies:
"@remix-run/router" "1.6.1"
+react-shallow-renderer@^16.15.0:
+ version "16.15.0"
+ resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457"
+ integrity sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==
+ dependencies:
+ object-assign "^4.1.1"
+ react-is "^16.12.0 || ^17.0.0 || ^18.0.0"
+
react-smooth@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.3.tgz#2845fa8f22914f2e4445856d5688fb8a7d72f3ae"
@@ -21824,6 +21832,15 @@ react-style-singleton@^2.2.1:
invariant "^2.2.4"
tslib "^2.0.0"
+react-test-renderer@18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.2.0.tgz#1dd912bd908ff26da5b9fca4fd1c489b9523d37e"
+ integrity sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==
+ dependencies:
+ react-is "^18.2.0"
+ react-shallow-renderer "^16.15.0"
+ scheduler "^0.23.0"
+
react-transition-group@2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"