diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6e87a00 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d280f69 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +permissions: + actions: read + contents: read + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + + # This enables task distribution via Nx Cloud + # Run this command as early as possible, before dependencies are installed + # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun + # Uncomment this line to enable task distribution + # - run: bunx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e-ci" + + - run: bun install --no-cache + - run: bun playwright install --with-deps + - uses: nrwl/nx-set-shas@v4 + + # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud + # - run: bun nx-cloud record -- echo Hello World + # Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected + # When you enable task distribution, run the e2e-ci task instead of e2e + - run: bun nx affected -t lint test build e2e diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89c6946 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +dist +tmp +out-tsc + +# dependencies +node_modules + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db + +.nx/cache +.nx/workspace-data + +# Next.js +.next +out diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e26f0b3 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +# Add files here to ignore them from prettier formatting +/dist +/coverage +/.nx/cache +/.nx/workspace-data \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..544138b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..c647399 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "nrwl.angular-console", + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "ms-playwright.playwright", + "firsttris.vscode-jest-runner" + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..1dd4cbf --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# HashRateGame + + + +✨ Your new, shiny [Nx workspace](https://nx.dev) is almost ready ✨. + +[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/next?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run `npx nx graph` to visually explore what was created. Now, let's get you up to speed! + +## Finish your CI setup + +[Click here to finish setting up your workspace!](https://cloud.nx.app/connect/WYPLMp8I1k) + + +## Run tasks + +To run the dev server for your app, use: + +```sh +npx nx dev HashRateGame +``` + +To create a production bundle: + +```sh +npx nx build HashRateGame +``` + +To see all available targets to run for a project, run: + +```sh +npx nx show project HashRateGame +``` + +These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the `project.json` or `package.json` files. + +[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Add new projects + +While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature. + +Use the plugin's generator to create new projects. + +To generate a new application, use: + +```sh +npx nx g @nx/next:app demo +``` + +To generate a new library, use: + +```sh +npx nx g @nx/react:lib mylib +``` + +You can use `npx nx list` to get a list of installed plugins. Then, run `npx nx list ` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE. + +[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + + +[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Install Nx Console + +Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ. + +[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +## Useful links + +Learn more: + +- [Learn more about this workspace setup](https://nx.dev/nx-api/next?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) + +And join the Nx community: +- [Discord](https://go.nx.dev/community) +- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl) +- [Our Youtube channel](https://www.youtube.com/@nxdevtools) +- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) diff --git a/apps/HashRateGame-e2e/eslint.config.js b/apps/HashRateGame-e2e/eslint.config.js new file mode 100644 index 0000000..4e73819 --- /dev/null +++ b/apps/HashRateGame-e2e/eslint.config.js @@ -0,0 +1,13 @@ +const playwright = require('eslint-plugin-playwright'); +const baseConfig = require('../../eslint.config.js'); + +module.exports = [ + playwright.configs['flat/recommended'], + + ...baseConfig, + { + files: ['**/*.ts', '**/*.js'], + // Override or add rules here + rules: {}, + }, +]; diff --git a/apps/HashRateGame-e2e/playwright.config.ts b/apps/HashRateGame-e2e/playwright.config.ts new file mode 100644 index 0000000..1bb5439 --- /dev/null +++ b/apps/HashRateGame-e2e/playwright.config.ts @@ -0,0 +1,69 @@ +import { defineConfig, devices } from '@playwright/test'; +import { nxE2EPreset } from '@nx/playwright/preset'; + +import { workspaceRoot } from '@nx/devkit'; + +// For CI, you may want to set BASE_URL to the deployed application. +const baseURL = process.env['BASE_URL'] || 'http://localhost:3000'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + ...nxE2EPreset(__filename, { testDir: './src' }), + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + baseURL, + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + /* Run your local dev server before starting the tests */ + webServer: { + command: 'bun nx run HashRateGame:serve-static', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI, + cwd: workspaceRoot, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + // Uncomment for mobile browsers support + /* { + name: 'Mobile Chrome', + use: { ...devices['Pixel 5'] }, + }, + { + name: 'Mobile Safari', + use: { ...devices['iPhone 12'] }, + }, */ + + // Uncomment for branded browsers + /* { + name: 'Microsoft Edge', + use: { ...devices['Desktop Edge'], channel: 'msedge' }, + }, + { + name: 'Google Chrome', + use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + } */ + ], +}); diff --git a/apps/HashRateGame-e2e/project.json b/apps/HashRateGame-e2e/project.json new file mode 100644 index 0000000..230216e --- /dev/null +++ b/apps/HashRateGame-e2e/project.json @@ -0,0 +1,10 @@ +{ + "name": "HashRateGame-e2e", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "sourceRoot": "apps/HashRateGame-e2e/src", + "tags": [], + "implicitDependencies": ["HashRateGame"], + "// targets": "to see all targets run: nx show project HashRateGame-e2e --web", + "targets": {} +} diff --git a/apps/HashRateGame-e2e/src/example.spec.ts b/apps/HashRateGame-e2e/src/example.spec.ts new file mode 100644 index 0000000..fa8f1f3 --- /dev/null +++ b/apps/HashRateGame-e2e/src/example.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('/'); + + // Expect h1 to contain a substring. + expect(await page.locator('h1').innerText()).toContain('Welcome'); +}); diff --git a/apps/HashRateGame-e2e/tsconfig.json b/apps/HashRateGame-e2e/tsconfig.json new file mode 100644 index 0000000..d983df4 --- /dev/null +++ b/apps/HashRateGame-e2e/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "allowJs": true, + "outDir": "../../dist/out-tsc", + "sourceMap": false, + "module": "commonjs" + }, + "include": [ + "**/*.ts", + "**/*.js", + "playwright.config.ts", + "src/**/*.spec.ts", + "src/**/*.spec.js", + "src/**/*.test.ts", + "src/**/*.test.js", + "src/**/*.d.ts" + ] +} diff --git a/apps/HashRateGame/eslint.config.js b/apps/HashRateGame/eslint.config.js new file mode 100644 index 0000000..cdaa917 --- /dev/null +++ b/apps/HashRateGame/eslint.config.js @@ -0,0 +1,22 @@ +const { FlatCompat } = require('@eslint/eslintrc'); +const js = require('@eslint/js'); +const { fixupConfigRules } = require('@eslint/compat'); +const nx = require('@nx/eslint-plugin'); +const baseConfig = require('../../eslint.config.js'); + +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, +}); + +module.exports = [ + ...fixupConfigRules(compat.extends('next')), + + ...fixupConfigRules(compat.extends('next/core-web-vitals')), + + ...baseConfig, + ...nx.configs['flat/react-typescript'], + { + ignores: ['.next/**/*'], + }, +]; diff --git a/apps/HashRateGame/index.d.ts b/apps/HashRateGame/index.d.ts new file mode 100644 index 0000000..7ba08fa --- /dev/null +++ b/apps/HashRateGame/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/HashRateGame/jest.config.ts b/apps/HashRateGame/jest.config.ts new file mode 100644 index 0000000..cfa109a --- /dev/null +++ b/apps/HashRateGame/jest.config.ts @@ -0,0 +1,10 @@ +export default { + displayName: 'HashRateGame', + 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/HashRateGame', +}; diff --git a/apps/HashRateGame/next-env.d.ts b/apps/HashRateGame/next-env.d.ts new file mode 100644 index 0000000..40c3d68 --- /dev/null +++ b/apps/HashRateGame/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/apps/HashRateGame/next.config.js b/apps/HashRateGame/next.config.js new file mode 100644 index 0000000..007b2aa --- /dev/null +++ b/apps/HashRateGame/next.config.js @@ -0,0 +1,22 @@ +//@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, + }, +}; + +const plugins = [ + // Add more Next.js plugins to this list if needed. + withNx, +]; + +module.exports = composePlugins(...plugins)(nextConfig); diff --git a/apps/HashRateGame/postcss.config.js b/apps/HashRateGame/postcss.config.js new file mode 100644 index 0000000..c72626d --- /dev/null +++ b/apps/HashRateGame/postcss.config.js @@ -0,0 +1,15 @@ +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: { + tailwindcss: { + config: join(__dirname, 'tailwind.config.js'), + }, + autoprefixer: {}, + }, +}; diff --git a/apps/HashRateGame/project.json b/apps/HashRateGame/project.json new file mode 100644 index 0000000..0d62367 --- /dev/null +++ b/apps/HashRateGame/project.json @@ -0,0 +1,9 @@ +{ + "name": "HashRateGame", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/HashRateGame", + "projectType": "application", + "tags": [], + "// targets": "to see all targets run: nx show project HashRateGame --web", + "targets": {} +} diff --git a/apps/HashRateGame/public/.gitkeep b/apps/HashRateGame/public/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/HashRateGame/public/favicon.ico b/apps/HashRateGame/public/favicon.ico new file mode 100644 index 0000000..317ebcb Binary files /dev/null and b/apps/HashRateGame/public/favicon.ico differ diff --git a/apps/HashRateGame/specs/index.spec.tsx b/apps/HashRateGame/specs/index.spec.tsx new file mode 100644 index 0000000..b544e83 --- /dev/null +++ b/apps/HashRateGame/specs/index.spec.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import Page from '../src/app/page'; + +describe('Page', () => { + it('should render successfully', () => { + const { baseElement } = render(); + expect(baseElement).toBeTruthy(); + }); +}); diff --git a/apps/HashRateGame/src/app/api/hello/route.ts b/apps/HashRateGame/src/app/api/hello/route.ts new file mode 100644 index 0000000..de70bac --- /dev/null +++ b/apps/HashRateGame/src/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/HashRateGame/src/app/global.css b/apps/HashRateGame/src/app/global.css new file mode 100644 index 0000000..1d6827b --- /dev/null +++ b/apps/HashRateGame/src/app/global.css @@ -0,0 +1,413 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html { + -webkit-text-size-adjust: 100%; + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, + Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, + Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji; + line-height: 1.5; + tab-size: 4; + scroll-behavior: smooth; +} +body { + font-family: inherit; + line-height: inherit; + margin: 0; +} +h1, +h2, +p, +pre { + margin: 0; +} +*, +::before, +::after { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: currentColor; +} +h1, +h2 { + font-size: inherit; + font-weight: inherit; +} +a { + color: inherit; + text-decoration: inherit; +} +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + Liberation Mono, Courier New, monospace; +} +svg { + display: block; + vertical-align: middle; + shape-rendering: auto; + text-rendering: optimizeLegibility; +} +pre { + background-color: rgba(55, 65, 81, 1); + border-radius: 0.25rem; + color: rgba(229, 231, 235, 1); + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + Liberation Mono, Courier New, monospace; + overflow: scroll; + padding: 0.5rem 0.75rem; +} + +.shadow { + box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} +.rounded { + border-radius: 1.5rem; +} +.wrapper { + width: 100%; +} +.container { + margin-left: auto; + margin-right: auto; + max-width: 768px; + padding-bottom: 3rem; + padding-left: 1rem; + padding-right: 1rem; + color: rgba(55, 65, 81, 1); + width: 100%; +} +#welcome { + margin-top: 2.5rem; +} +#welcome h1 { + font-size: 3rem; + font-weight: 500; + letter-spacing: -0.025em; + line-height: 1; +} +#welcome span { + display: block; + font-size: 1.875rem; + font-weight: 300; + line-height: 2.25rem; + margin-bottom: 0.5rem; +} +#hero { + align-items: center; + background-color: hsla(214, 62%, 21%, 1); + border: none; + box-sizing: border-box; + color: rgba(55, 65, 81, 1); + display: grid; + grid-template-columns: 1fr; + margin-top: 3.5rem; +} +#hero .text-container { + color: rgba(255, 255, 255, 1); + padding: 3rem 2rem; +} +#hero .text-container h2 { + font-size: 1.5rem; + line-height: 2rem; + position: relative; +} +#hero .text-container h2 svg { + color: hsla(162, 47%, 50%, 1); + height: 2rem; + left: -0.25rem; + position: absolute; + top: 0; + width: 2rem; +} +#hero .text-container h2 span { + margin-left: 2.5rem; +} +#hero .text-container a { + background-color: rgba(255, 255, 255, 1); + border-radius: 0.75rem; + color: rgba(55, 65, 81, 1); + display: inline-block; + margin-top: 1.5rem; + padding: 1rem 2rem; + text-decoration: inherit; +} +#hero .logo-container { + display: none; + justify-content: center; + padding-left: 2rem; + padding-right: 2rem; +} +#hero .logo-container svg { + color: rgba(255, 255, 255, 1); + width: 66.666667%; +} +#middle-content { + align-items: flex-start; + display: grid; + gap: 4rem; + grid-template-columns: 1fr; + margin-top: 3.5rem; +} +#learning-materials { + padding: 2.5rem 2rem; +} +#learning-materials h2 { + font-weight: 500; + font-size: 1.25rem; + letter-spacing: -0.025em; + line-height: 1.75rem; + padding-left: 1rem; + padding-right: 1rem; +} +.list-item-link { + align-items: center; + border-radius: 0.75rem; + display: flex; + margin-top: 1rem; + padding: 1rem; + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + width: 100%; +} +.list-item-link svg:first-child { + margin-right: 1rem; + height: 1.5rem; + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + width: 1.5rem; +} +.list-item-link > span { + flex-grow: 1; + font-weight: 400; + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.list-item-link > span > span { + color: rgba(107, 114, 128, 1); + display: block; + flex-grow: 1; + font-size: 0.75rem; + font-weight: 300; + line-height: 1rem; + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +.list-item-link svg:last-child { + height: 1rem; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + width: 1rem; +} +.list-item-link:hover { + color: rgba(255, 255, 255, 1); + background-color: hsla(162, 47%, 50%, 1); +} +.list-item-link:hover > span { +} +.list-item-link:hover > span > span { + color: rgba(243, 244, 246, 1); +} +.list-item-link:hover svg:last-child { + transform: translateX(0.25rem); +} +#other-links { +} +.button-pill { + padding: 1.5rem 2rem; + transition-duration: 300ms; + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + align-items: center; + display: flex; +} +.button-pill svg { + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + flex-shrink: 0; + width: 3rem; +} +.button-pill > span { + letter-spacing: -0.025em; + font-weight: 400; + font-size: 1.125rem; + line-height: 1.75rem; + padding-left: 1rem; + padding-right: 1rem; +} +.button-pill span span { + display: block; + font-size: 0.875rem; + font-weight: 300; + line-height: 1.25rem; +} +.button-pill:hover svg, +.button-pill:hover { + color: rgba(255, 255, 255, 1) !important; +} +#nx-console:hover { + background-color: rgba(0, 122, 204, 1); +} +#nx-console svg { + color: rgba(0, 122, 204, 1); +} +#nx-console-jetbrains { + margin-top: 2rem; +} +#nx-console-jetbrains:hover { + background-color: rgba(255, 49, 140, 1); +} +#nx-console-jetbrains svg { + color: rgba(255, 49, 140, 1); +} +#nx-repo:hover { + background-color: rgba(24, 23, 23, 1); +} +#nx-repo svg { + color: rgba(24, 23, 23, 1); +} +#nx-cloud { + margin-bottom: 2rem; + margin-top: 2rem; + padding: 2.5rem 2rem; +} +#nx-cloud > div { + align-items: center; + display: flex; +} +#nx-cloud > div svg { + border-radius: 0.375rem; + flex-shrink: 0; + width: 3rem; +} +#nx-cloud > div h2 { + font-size: 1.125rem; + font-weight: 400; + letter-spacing: -0.025em; + line-height: 1.75rem; + padding-left: 1rem; + padding-right: 1rem; +} +#nx-cloud > div h2 span { + display: block; + font-size: 0.875rem; + font-weight: 300; + line-height: 1.25rem; +} +#nx-cloud p { + font-size: 1rem; + line-height: 1.5rem; + margin-top: 1rem; +} +#nx-cloud pre { + margin-top: 1rem; +} +#nx-cloud a { + color: rgba(107, 114, 128, 1); + display: block; + font-size: 0.875rem; + line-height: 1.25rem; + margin-top: 1.5rem; + text-align: right; +} +#nx-cloud a:hover { + text-decoration: underline; +} +#commands { + padding: 2.5rem 2rem; + margin-top: 3.5rem; +} +#commands h2 { + font-size: 1.25rem; + font-weight: 400; + letter-spacing: -0.025em; + line-height: 1.75rem; + padding-left: 1rem; + padding-right: 1rem; +} +#commands p { + font-size: 1rem; + font-weight: 300; + line-height: 1.5rem; + margin-top: 1rem; + padding-left: 1rem; + padding-right: 1rem; +} +details { + align-items: center; + display: flex; + margin-top: 1rem; + padding-left: 1rem; + padding-right: 1rem; + width: 100%; +} +details pre > span { + color: rgba(181, 181, 181, 1); + display: block; +} +summary { + border-radius: 0.5rem; + display: flex; + font-weight: 400; + padding: 0.5rem; + cursor: pointer; + transition-property: background-color, border-color, color, fill, stroke, + opacity, box-shadow, transform, filter, backdrop-filter, + -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} +summary:hover { + background-color: rgba(243, 244, 246, 1); +} +summary svg { + height: 1.5rem; + margin-right: 1rem; + width: 1.5rem; +} +#love { + color: rgba(107, 114, 128, 1); + font-size: 0.875rem; + line-height: 1.25rem; + margin-top: 3.5rem; + opacity: 0.6; + text-align: center; +} +#love svg { + color: rgba(252, 165, 165, 1); + width: 1.25rem; + height: 1.25rem; + display: inline; + margin-top: -0.25rem; +} +@media screen and (min-width: 768px) { + #hero { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + #hero .logo-container { + display: flex; + } + #middle-content { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} diff --git a/apps/HashRateGame/src/app/layout.tsx b/apps/HashRateGame/src/app/layout.tsx new file mode 100644 index 0000000..21f8d04 --- /dev/null +++ b/apps/HashRateGame/src/app/layout.tsx @@ -0,0 +1,18 @@ +import './global.css'; + +export const metadata = { + title: 'Welcome to hash-rate-game', + description: 'Generated by create-nx-workspace', +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/apps/HashRateGame/src/app/page.tsx b/apps/HashRateGame/src/app/page.tsx new file mode 100644 index 0000000..d38bff3 --- /dev/null +++ b/apps/HashRateGame/src/app/page.tsx @@ -0,0 +1,467 @@ +export default function Index() { + /* + * Replace the elements below with your own. + * + * Note: The corresponding styles are in the ./index.tailwind file. + */ + return ( +
+
+
+
+

+ Hello there, + Welcome HashRateGame 👋 +

+
+ +
+
+

+ + + + You're up and running +

+ What's next? +
+
+ + + +
+
+ + + +
+

Next steps

+

Here are some things you can do with Nx:

+
+ + + + + Add UI library + +
+                # Generate UI lib
+                nx g @nx/next:library ui
+                # Add a component
+                nx g @nx/next:component ui/src/lib/button
+              
+
+
+ + + + + View project details + +
nx show project HashRateGame --web
+
+
+ + + + + View interactive project graph + +
nx graph
+
+
+ + + + + Run affected commands + +
+                # see what's been affected by changes
+                nx affected:graph
+                # run tests for current changes
+                nx affected:test
+                # run e2e tests for current changes
+                nx affected:e2e
+              
+
+
+ +

+ Carefully crafted with + + + +

+
+
+
+ ); +} diff --git a/apps/HashRateGame/tailwind.config.js b/apps/HashRateGame/tailwind.config.js new file mode 100644 index 0000000..e1cf7ce --- /dev/null +++ b/apps/HashRateGame/tailwind.config.js @@ -0,0 +1,17 @@ +const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join( + __dirname, + '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' + ), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/HashRateGame/tsconfig.json b/apps/HashRateGame/tsconfig.json new file mode 100644 index 0000000..e441c99 --- /dev/null +++ b/apps/HashRateGame/tsconfig.json @@ -0,0 +1,34 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "preserve", + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "types": ["jest", "node"] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + "**/*.js", + "**/*.jsx", + "../../apps/HashRateGame/.next/types/**/*.ts", + "../../dist/apps/HashRateGame/.next/types/**/*.ts", + "next-env.d.ts" + ], + "exclude": ["node_modules", "jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] +} diff --git a/apps/HashRateGame/tsconfig.spec.json b/apps/HashRateGame/tsconfig.spec.json new file mode 100644 index 0000000..9111206 --- /dev/null +++ b/apps/HashRateGame/tsconfig.spec.json @@ -0,0 +1,22 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "moduleResolution": "node10", + "jsx": "react", + "types": ["jest", "node"] + }, + "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/bun.lockb b/bun.lockb new file mode 100644 index 0000000..1a5166b Binary files /dev/null and b/bun.lockb differ diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..46a8005 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,33 @@ +const nx = require('@nx/eslint-plugin'); + +module.exports = [ + ...nx.configs['flat/base'], + ...nx.configs['flat/typescript'], + ...nx.configs['flat/javascript'], + { + ignores: ['**/dist'], + }, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + rules: { + '@nx/enforce-module-boundaries': [ + 'error', + { + enforceBuildableLibDependency: true, + allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'], + depConstraints: [ + { + sourceTag: '*', + onlyDependOnLibsWithTags: ['*'], + }, + ], + }, + ], + }, + }, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + // Override or add rules here + rules: {}, + }, +]; diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..6b3f2d6 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,5 @@ +import { getJestProjectsAsync } from '@nx/jest'; + +export default async () => ({ + projects: await getJestProjectsAsync(), +}); diff --git a/jest.preset.js b/jest.preset.js new file mode 100644 index 0000000..f078ddc --- /dev/null +++ b/jest.preset.js @@ -0,0 +1,3 @@ +const nxPreset = require('@nx/jest/preset').default; + +module.exports = { ...nxPreset }; diff --git a/nx.json b/nx.json new file mode 100644 index 0000000..03309be --- /dev/null +++ b/nx.json @@ -0,0 +1,61 @@ +{ + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "defaultBase": "master", + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "production": [ + "default", + "!{projectRoot}/.eslintrc.json", + "!{projectRoot}/eslint.config.js", + "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", + "!{projectRoot}/tsconfig.spec.json", + "!{projectRoot}/jest.config.[jt]s", + "!{projectRoot}/src/test-setup.[jt]s", + "!{projectRoot}/test-setup.[jt]s" + ], + "sharedGlobals": ["{workspaceRoot}/.github/workflows/ci.yml"] + }, + "nxCloudId": "675f06a84bbe36106b58b28f", + "plugins": [ + { + "plugin": "@nx/next/plugin", + "options": { + "startTargetName": "start", + "buildTargetName": "build", + "devTargetName": "dev", + "serveStaticTargetName": "serve-static" + } + }, + { + "plugin": "@nx/playwright/plugin", + "options": { + "targetName": "e2e" + } + }, + { + "plugin": "@nx/eslint/plugin", + "options": { + "targetName": "lint" + } + }, + { + "plugin": "@nx/jest/plugin", + "options": { + "targetName": "test" + } + } + ], + "targetDefaults": { + "e2e-ci--**/*": { + "dependsOn": ["^build"] + } + }, + "generators": { + "@nx/next": { + "application": { + "style": "tailwind", + "linter": "eslint" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7fce619 --- /dev/null +++ b/package.json @@ -0,0 +1,54 @@ +{ + "name": "@hash-rate-game/source", + "version": "0.0.0", + "license": "MIT", + "scripts": {}, + "private": true, + "dependencies": { + "next": "14.2.16", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "@eslint/compat": "^1.1.1", + "@eslint/js": "^9.8.0", + "@nx/devkit": "20.2.2", + "@nx/eslint": "20.2.2", + "@nx/eslint-plugin": "20.2.2", + "@nx/jest": "20.2.2", + "@nx/js": "20.2.2", + "@nx/next": "20.2.2", + "@nx/playwright": "20.2.2", + "@nx/workspace": "20.2.2", + "@playwright/test": "^1.36.0", + "@swc-node/register": "~1.9.1", + "@swc/core": "~1.5.7", + "@swc/helpers": "~0.5.11", + "@testing-library/react": "15.0.6", + "@types/jest": "^29.5.12", + "@types/node": "18.16.9", + "@types/react": "18.3.1", + "@types/react-dom": "18.3.0", + "autoprefixer": "10.4.13", + "babel-jest": "^29.7.0", + "eslint": "^9.8.0", + "eslint-config-next": "14.2.16", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "2.31.0", + "eslint-plugin-jsx-a11y": "6.10.1", + "eslint-plugin-playwright": "^1.6.2", + "eslint-plugin-react": "7.35.0", + "eslint-plugin-react-hooks": "5.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "nx": "20.2.2", + "postcss": "8.4.38", + "prettier": "^2.6.2", + "tailwindcss": "3.4.3", + "ts-jest": "^29.1.0", + "ts-node": "10.9.1", + "tslib": "^2.3.0", + "typescript": "~5.6.2", + "typescript-eslint": "^8.13.0" + } +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..b73cce6 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,20 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "rootDir": ".", + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "es2015", + "module": "esnext", + "lib": ["es2020", "dom"], + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "baseUrl": ".", + "paths": {} + }, + "exclude": ["node_modules", "tmp"] +}