diff --git a/.eslintrc b/.eslintrc index 60b08f65..c8f5f29c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -42,6 +42,22 @@ "react/jsx-uses-react": "off", "react/react-in-jsx-scope": "off" } + }, + { + // TODO: add https://github.com/francoismassart/eslint-plugin-tailwindcss + "files": ["./apps/website/"], + "extends": [ + // "next" + "next/core-web-vitals" + ] + // "settings": { + // "import/resolver": { + // "typescript": { + // "extensions": [".js", ".jsx", ".ts", ".tsx"], + // "project": ["tsconfig.json", "apps/website/tsconfig.json"] + // } + // } + // } } ], "rules": { @@ -84,13 +100,23 @@ "import/resolver": { "node": { "extensions": [".js", ".jsx", ".ts", ".tsx"], - "project": ["tsconfig.base.json", "packages/*/tsconfig.json"] + "project": [ + "tsconfig.base.json", + "packages/*/tsconfig.json", + "apps/*/tsconfig.json" + ] }, "typescript": { "alwaysTryTypes": true, - "project": ["tsconfig.base.json", "packages/*/tsconfig.json"] + "project": [ + "tsconfig.base.json", + "packages/*/tsconfig.json", + "apps/*/tsconfig.json" + ] } }, "import/ignore": ["react-native"] } } + +// appp/website; extend eslint-config-next diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5820a53e..a2677bae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: 'yarn' - name: Install dependencies diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 6998f632..72e5c2a9 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,6 +5,7 @@ "zxh404.vscode-proto3", "ms-vscode.hexeditor", "zixuanchen.vitest-explorer", - "mikestead.dotenv" + "mikestead.dotenv", + "bradlc.vscode-tailwindcss" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 8d758622..af463338 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -59,6 +59,44 @@ "smartStep": true, "console": "integratedTerminal", "sourceMaps": true + }, + { + "name": "Next.js: debug server-side", + "type": "node-terminal", + "request": "launch", + "command": "yarn dev" + }, + { + "name": "Next.js: debug client-side", + "type": "chrome", + "request": "launch", + "url": "http://localhost:3000", + "skipFiles": [ + ".next/**", + "${workspaceFolder}/node_modules/**", + "/**", + "**/webpack-internal://**" + ], + "runtimeArgs": ["--auto-open-devtools-for-tabs"] + }, + // todo: consider https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations instead + // todo: consider client+prelaunch as full stack + { + "name": "Next.js: debug full stack", + "type": "node-terminal", + "request": "launch", + "command": "yarn dev -p 3000", + "serverReadyAction": { + "pattern": "started server on .+, url: (https?://.+)", + "action": "startDebugging", + "name": "Next.js: debug client-side", + "killOnServerStop": false + }, + "skipFiles": [ + ".next/**", + "${workspaceFolder}/node_modules/**", + "/**" + ] } ] } diff --git a/apps/web/package.json b/apps/web/package.json index 93875e78..9e32d2fc 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -7,7 +7,8 @@ "build": "tsc && vite build", "preview": "vite preview", "lint": "eslint src", - "typecheck": "tsc" + "typecheck": "tsc", + "clean": "rimraf node_modules .turbo" }, "dependencies": { "@status-im/components": "*", diff --git a/apps/website/.gitignore b/apps/website/.gitignore new file mode 100644 index 00000000..93cf48e0 --- /dev/null +++ b/apps/website/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# Tamagui +.tamagui diff --git a/apps/website/next.config.js b/apps/website/next.config.js new file mode 100644 index 00000000..835598aa --- /dev/null +++ b/apps/website/next.config.js @@ -0,0 +1,74 @@ +/* eslint-disable eslint-comments/disable-enable-pair */ +/* eslint-disable @typescript-eslint/no-var-requires */ + +/** @type {import('next').NextConfig} */ +const { withTamagui } = require('@tamagui/next-plugin') +const { join } = require('path') + +process.env.IGNORE_TS_CONFIG_PATHS = 'true' +process.env.TAMAGUI_TARGET = 'web' +process.env.TAMAGUI_DISABLE_WARN_DYNAMIC_LOAD = '1' + +/** @type {import('next').NextConfig} */ +let config = { + reactStrictMode: true, + typescript: { + ignoreBuildErrors: true, + }, + images: { + disableStaticImages: true, + }, + transpilePackages: [ + // 'react-native', + 'react-native-web', + // 'expo-modules-core', + 'expo-blur', + // '@status-im/components', + // '@status-im/js', + ], + experimental: { + legacyBrowsers: false, + // esmExternals: 'loose', + }, +} + +const plugins = [ + withTamagui({ + config: './tamagui.config.ts', + components: [ + // fixme?: works without it + // '@status-im/icons', + '@status-im/components', + // './node_modules/@status-im/components/packages/components/dist', + ], + importsWhitelist: ['constants.js', 'colors.js'], + logTimings: true, + disableExtraction: true, + // experiment - reduced bundle size react-native-web + useReactNativeWebLite: false, + shouldExtract: path => { + if (path.includes(join('packages', 'app'))) { + return true + } + }, + excludeReactNativeWebExports: [ + 'Switch', + 'ProgressBar', + 'Picker', + 'CheckBox', + 'Touchable', + 'Modal', + ], + }), +] + +module.exports = () => { + for (const plugin of plugins) { + config = { + ...config, + ...plugin(config), + } + } + + return config +} diff --git a/apps/website/package.json b/apps/website/package.json new file mode 100644 index 00000000..29a84ac5 --- /dev/null +++ b/apps/website/package.json @@ -0,0 +1,40 @@ +{ + "name": "website", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "TAMAGUI_TARGET='web' next dev", + "build": "TAMAGUI_TARGET='web' next build", + "start": "TAMAGUI_TARGET='web' next start", + "lint": "next lint", + "typecheck": "tsc", + "clean": "rimraf .next .tamagui .vercel/output node_modules", + "serve": "TAMAGUI_TARGET='web' NODE_ENV=production next start --port 8151" + }, + "dependencies": { + "@radix-ui/react-dialog": "^1.0.3", + "@scure/base": "^1.1.1", + "@status-im/components": "*", + "@status-im/icons": "*", + "@status-im/js": "*", + "@tamagui/next-theme": "1.11.1", + "next": "13.2.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-native-web": "^0.18.12" + }, + "devDependencies": { + "@achingbrain/ssdp": "^4.0.1", + "@tamagui/next-plugin": "1.11.1", + "@types/node": "^18.11.11", + "@types/react": "^18.0.33", + "@types/react-dom": "^18.0.11", + "autoprefixer": "^10.4.14", + "postcss": "^8.4.21", + "tailwindcss": "^3.3.1", + "typescript": "^5.0.3" + }, + "engines": { + "node": "^18.x" + } +} diff --git a/apps/website/pages/_app.tsx b/apps/website/pages/_app.tsx new file mode 100644 index 00000000..d8c0bf1d --- /dev/null +++ b/apps/website/pages/_app.tsx @@ -0,0 +1,23 @@ +import '@/styles/app.css' +import '@/styles/reset.css' + +import { Provider } from '@status-im/components' +import { Inter } from 'next/font/google' + +import type { AppProps } from 'next/app' + +const inter = Inter({ + variable: '--font-sans', + weight: ['400', '500', '600'], + subsets: ['latin'], +}) + +export default function App({ Component, pageProps }: AppProps) { + return ( +
+ + + +
+ ) +} diff --git a/apps/website/pages/_document.tsx b/apps/website/pages/_document.tsx new file mode 100644 index 00000000..d2cb1aec --- /dev/null +++ b/apps/website/pages/_document.tsx @@ -0,0 +1,40 @@ +import { Children } from 'react' + +import NextDocument, { Head, Html, Main, NextScript } from 'next/document' +import { AppRegistry } from 'react-native' + +import Tamagui from '../tamagui.config' + +import type { DocumentContext } from 'next/document' + +export default class Document extends NextDocument { + static async getInitialProps({ renderPage }: DocumentContext) { + AppRegistry.registerComponent('app', () => Main) + // @ts-expect-error todo + const { getStyleElement } = AppRegistry.getApplication('app') + + const page = await renderPage() + + const styles = [getStyleElement()] + + return { ...page, styles: Children.toArray(styles) } + } + + render() { + return ( + + + +