├── .eslintrc.js
├── .github
├── ISSUE_TEMPLATE
│ ├── generic-bug-report.md
│ └── react-bug-report.md
├── actions
│ └── setup-env
│ │ └── action.yml
├── dependabot.yml
├── pull_request_template.md
└── workflows
│ ├── release.yml
│ └── triage.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── .vscode
├── extensions.json
└── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps
├── docs
│ ├── next-env.d.ts
│ ├── next-sitemap.config.js
│ ├── next.config.js
│ ├── package.json
│ ├── pages
│ │ ├── _document.tsx
│ │ ├── _meta.json
│ │ ├── api-docs.mdx
│ │ ├── guides
│ │ │ ├── _meta.json
│ │ │ ├── mpa.mdx
│ │ │ ├── policy.mdx
│ │ │ └── spa.mdx
│ │ ├── index.mdx
│ │ └── migrations
│ │ │ ├── _meta.json
│ │ │ └── v2.mdx
│ ├── public
│ │ └── logo.png
│ ├── theme.config.jsx
│ └── tsconfig.json
├── emotion
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.css
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ └── StyledExample.tsx
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── less
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.less
│ │ │ ├── App.tsx
│ │ │ ├── Button.tsx
│ │ │ ├── button.module.less
│ │ │ └── variables.less
│ │ ├── index.less
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── mui
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── main.tsx
│ │ ├── theme.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── preact-app
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── app.css
│ │ ├── app.tsx
│ │ ├── assets
│ │ │ └── preact.svg
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── react
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.css
│ │ │ ├── App.tsx
│ │ │ ├── Home.tsx
│ │ │ └── Injector.tsx
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── remix-spa
│ ├── .eslintrc.cjs
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ ├── routes
│ │ │ └── _index.tsx
│ │ └── tailwind.css
│ ├── package.json
│ ├── postcss.config.js
│ ├── public
│ │ └── favicon.ico
│ ├── tailwind.config.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── scss
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.scss
│ │ │ ├── App.tsx
│ │ │ ├── Button.tsx
│ │ │ ├── button.module.scss
│ │ │ └── variables.scss
│ │ ├── index.scss
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── solid-app
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.css
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── solid.svg
│ │ ├── index.css
│ │ ├── index.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── stylus
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.styl
│ │ │ ├── App.tsx
│ │ │ ├── Button.tsx
│ │ │ ├── button.module.styl
│ │ │ └── variables.styl
│ │ ├── index.styl
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── svelte-app
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.svelte
│ │ ├── app.css
│ │ ├── assets
│ │ │ └── svelte.svg
│ │ ├── lib
│ │ │ └── Counter.svelte
│ │ ├── main.ts
│ │ └── vite-env.d.ts
│ ├── svelte.config.js
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── tailwind
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tailwind.config.js
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── tailwind4
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── main.tsx
│ │ ├── style.css
│ │ └── vite-env.d.ts
│ ├── tailwind.config.js
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── vite4
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.css
│ │ │ ├── App.tsx
│ │ │ ├── Home.tsx
│ │ │ └── Injector.tsx
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── vite5
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.css
│ │ │ ├── App.tsx
│ │ │ ├── Home.tsx
│ │ │ └── Injector.tsx
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── vite6
│ ├── .eslintrc.cjs
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── components
│ │ │ ├── App.css
│ │ │ ├── App.tsx
│ │ │ ├── Home.tsx
│ │ │ └── Injector.tsx
│ │ ├── index.css
│ │ ├── main.tsx
│ │ └── vite-env.d.ts
│ ├── tests
│ │ └── main.spec.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── vue-app
│ ├── .vscode
│ │ └── extensions.json
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.vue
│ │ ├── assets
│ │ │ └── vue.svg
│ │ ├── components
│ │ │ └── HelloWorld.vue
│ │ ├── main.ts
│ │ ├── style.css
│ │ └── vite-env.d.ts
│ ├── tests
│ │ ├── main.spec.ts
│ │ └── preview-only
│ │ │ └── main.spec.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
└── vue-router
│ ├── .vscode
│ └── extensions.json
│ ├── index.html
│ ├── package.json
│ ├── public
│ └── vite.svg
│ ├── src
│ ├── App.vue
│ ├── Bye.vue
│ ├── Four.vue
│ ├── Hello.vue
│ ├── assets
│ │ └── vue.svg
│ ├── components
│ │ └── HelloWorld.vue
│ ├── main.ts
│ ├── router
│ │ └── index.ts
│ ├── style.css
│ └── vite-env.d.ts
│ ├── tests
│ ├── main.spec.ts
│ └── preview-only
│ │ └── main.spec.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ ├── tsconfig.tsbuildinfo
│ └── vite.config.ts
├── package.json
├── packages
├── eslint-config
│ ├── library.js
│ ├── next.js
│ ├── package.json
│ └── vite-react.js
├── testing
│ ├── package.json
│ ├── rollup.config.mjs
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── typescript-config
│ ├── base.json
│ ├── nextjs.json
│ ├── node.json
│ ├── package.json
│ └── vite.json
└── vite-plugin-csp-guard
│ ├── LICENSE
│ ├── README.md
│ ├── mocks
│ ├── css.ts
│ └── post.ts
│ ├── package.json
│ ├── rollup.config.mjs
│ ├── src
│ ├── constants.ts
│ ├── css
│ │ ├── extraction.ts
│ │ └── index.ts
│ ├── index.ts
│ ├── policy
│ │ ├── constants.ts
│ │ ├── core.ts
│ │ └── createPolicy.ts
│ ├── transform
│ │ ├── constants.ts
│ │ ├── handleIndexHtml.ts
│ │ ├── index.ts
│ │ └── lazy.ts
│ ├── types.ts
│ └── utils.ts
│ ├── tests
│ ├── extraction.test.ts
│ └── hashing.test.ts
│ └── tsconfig.json
├── playwright.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── scripts
├── cleanup-modules.sh
├── get-package-path.sh
├── hash-file-content.js
├── hash-file-content.sh
├── packages-to-release.sh
├── release.sh
└── version-has-changed.sh
├── turbo.json
└── turbo
└── generators
└── config.ts
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // This configuration only applies to the package manager root.
2 | /** @type {import("eslint").Linter.Config} */
3 | module.exports = {
4 | ignorePatterns: ["apps/**", "packages/**", "scripts/playground/**"],
5 | extends: ["@repo/eslint-config/library.js"],
6 | parser: "@typescript-eslint/parser",
7 | parserOptions: {
8 | project: true,
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/generic-bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Generic Bug Report
3 | about: A non framework/library specific bug report
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: tsotimus
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **Expected behaviour**
14 | A clear and concise description of what you expected to happen.
15 |
16 | **Screenshots**
17 | If applicable, add screenshots to help explain your problem.
18 |
19 | **Your setup**
20 | - Vite Version: [e.g. 5.0]
21 | - Frameworks/Librarys [e.g. React, Vue]
22 | - CSS libraries, etc [MUI, SCSS]
23 |
24 | **Additional context**
25 | Add any other context about the problem here.
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/react-bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: React Bug Report
3 | about: React specific bug report
4 | title: "[BUG]"
5 | labels: bug, react
6 | assignees: tsotimus
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **Expected behaviour**
14 | A clear and concise description of what you expected to happen.
15 |
16 | **Screenshots**
17 | If applicable, add screenshots to help explain your problem.
18 |
19 | **Your setup**
20 | - Vite Version: [e.g. 5.0]
21 | - React with/without remix
22 | - CSS libraries, etc [MUI, SCSS]
23 |
24 | **Additional context**
25 | Add any other context about the problem here.
26 |
--------------------------------------------------------------------------------
/.github/actions/setup-env/action.yml:
--------------------------------------------------------------------------------
1 | name: "Setup Environment"
2 | description: "Sets up Node.js, PNPM, JQ, and TurboRepo"
3 |
4 | inputs:
5 | node-version:
6 | description: "Node.js version"
7 | required: true
8 | default: "20"
9 |
10 | runs:
11 | using: "composite"
12 | steps:
13 | # - name: Checkout code
14 | # uses: actions/checkout@v4
15 |
16 | - name: Setup Node.js
17 | uses: actions/setup-node@v4
18 | with:
19 | node-version: ${{ inputs.node-version }}
20 |
21 | - name: Enable Corepack
22 | run: corepack enable
23 | shell: bash
24 |
25 | - name: Install PNPM
26 | run: pnpm install
27 | shell: bash
28 |
29 | - name: Install JQ
30 | run: sudo apt-get install -y jq
31 | shell: bash
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "npm"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | open-pull-requests-limit: 5
8 | commit-message:
9 | include: scope
10 | prefix: "chore(root-deps)"
11 | prefix-development: "chore"
12 |
13 | - package-ecosystem: "npm"
14 | directories:
15 | - "/apps/*"
16 | schedule:
17 | interval: "weekly"
18 | open-pull-requests-limit: 2
19 | commit-message:
20 | include: scope
21 | prefix: "chore(app-deps)"
22 | prefix-development: "chore"
23 | ignore:
24 | - dependency-name: "typescript"
25 | - dependency-name: "vite"
26 |
27 | - package-ecosystem: "npm"
28 | directories:
29 | - "/packages/*"
30 | schedule:
31 | interval: "weekly"
32 | open-pull-requests-limit: 5
33 | commit-message:
34 | include: scope
35 | prefix: "chore(pkg-deps)"
36 | prefix-development: "chore"
37 | ignore:
38 | - dependency-name: "typescript"
39 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Key Changes
2 |
3 | - Change 1
4 |
5 | ## Approach
6 |
7 | ## Checklist
8 |
9 | - [ ] Tests
10 | - [ ] Documentation
11 |
--------------------------------------------------------------------------------
/.github/workflows/triage.yml:
--------------------------------------------------------------------------------
1 | name: PR Workflow
2 |
3 | on:
4 | pull_request:
5 | types: [opened, reopened, synchronize, ready_for_review]
6 | branches:
7 | - main
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | if: github.event.pull_request.draft == false
13 | steps:
14 | - name: Checkout code
15 | uses: actions/checkout@v4
16 | - uses: actions/setup-node@v4
17 | with:
18 | node-version: "23"
19 | - run: node -v
20 | - run: corepack enable
21 | - run: corepack --version
22 |
23 | - run: pnpm install
24 |
25 | - name: Build All Publishable Packages
26 | run: pnpm p:build
27 |
28 | - name: Run Unit Tests
29 | run: pnpm p:test
30 |
31 | - name: Build Apps
32 | run: pnpm build
33 |
34 | - name: Install Playwright Browsers
35 | run: npx playwright install --with-deps chromium
36 |
37 | - name: Run tests
38 | run: pnpm test
39 | - uses: actions/upload-artifact@v4
40 | if: always()
41 | with:
42 | name: playwright-report
43 | path: playwright-report/
44 | retention-days: 5
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # Dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # Local env files
9 | .env
10 | .env.local
11 | .env.development.local
12 | .env.test.local
13 | .env.production.local
14 |
15 | # Testing
16 | coverage
17 |
18 | # Turbo
19 | .turbo
20 |
21 | # Vercel
22 | .vercel
23 |
24 | # Build Outputs
25 | .next/
26 | out/
27 | build
28 | dist
29 |
30 |
31 | # Debug
32 | npm-debug.log*
33 | yarn-debug.log*
34 | yarn-error.log*
35 |
36 | # Misc
37 | .DS_Store
38 | *.pem
39 | test-results/
40 | playwright-report/
41 | /blob-report/
42 | /playwright/.cache/
43 |
44 |
45 | # Ignore scripts playground
46 | scripts/playground/*
47 |
48 | # Temp debug files
49 | apps/**/temp-original-*.js
50 | apps/**/temp-transformed-*.js
51 |
52 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | public-hoist-pattern=@types/stylus
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | scripts/playground/**
2 |
3 | # Ignore artifacts:
4 | build
5 | coverage
6 | dist
7 |
8 | # Ignore all HTML files:
9 | **/*.html
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["svelte.svelte-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll.eslint": true
5 | },
6 | "editor.defaultFormatter": "esbenp.prettier-vscode",
7 | "typescript.tsdk": "node_modules/typescript/lib",
8 | "typescript.enablePromptUseWorkspaceTsdk": true,
9 | "eslint.workingDirectories": [
10 | {
11 | "mode": "auto"
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to CSP
2 |
3 | Thank you for your interest in contributing! We welcome all contributions, from bug reports and feature requests to documentation improvements and code enhancements. This guide will help you get started.
4 |
5 | ## Getting Started
6 |
7 | ### Prerequisites
8 |
9 | Make sure you have the following tools installed:
10 | - Node.js
11 | - pnpm (via corepack)
12 |
13 | Run `pnpm install` and you should be good to go!
14 |
15 | ## General Info
16 | All the CSP packages are under `/packages` and these are used inside the vite apps that are housed in `apps`
17 | For development I'd recommend using `pnpm r:dev` which starts up a normal ts-react vite application
18 |
19 | Bear in mind playwright tests run across these applications, so there are some parts of these applications that are crucial to these tests passing.
20 |
21 | ## Submitting your work
22 | - Be on a new branch with a relevent name e.g `fix/react-type-issues`
23 | - Submit your PR filling out the PR Template and linking to any issues you can
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/apps/docs/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
6 |
--------------------------------------------------------------------------------
/apps/docs/next-sitemap.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next-sitemap').IConfig} */
2 | module.exports = {
3 | siteUrl: "https://vite-csp.tsotne.co.uk",
4 | generateRobotsTxt: true, // (optional)
5 | generateIndexSitemap: false,
6 | sitemapSize: 100,
7 | output: "export",
8 | additionalPaths: async () => [
9 | {
10 | loc: "/",
11 | priority: "1.0",
12 | },
13 | {
14 | loc: "/guides/spa",
15 | priority: 0.9,
16 | },
17 | {
18 | loc: "/guides/mpa",
19 | priority: 0.9,
20 | },
21 | {
22 | loc: "/guides/policy",
23 | priority: 0.9,
24 | },
25 | {
26 | loc: "/api-docs",
27 | priority: 0.6,
28 | },
29 | {
30 | loc: "/migrations/v2",
31 | priority: 0.6,
32 | },
33 | ],
34 | };
35 |
--------------------------------------------------------------------------------
/apps/docs/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const withNextra = require("nextra")({
3 | theme: "nextra-theme-docs",
4 | themeConfig: "./theme.config.jsx",
5 | });
6 |
7 | module.exports = withNextra({
8 | reactStrictMode: true,
9 | output: "export",
10 | images: {
11 | unoptimized: true,
12 | },
13 | });
14 |
15 | // If you have other Next.js configurations, you can pass them as the parameter:
16 | // module.exports = withNextra({ /* other next.js config */ })
17 |
--------------------------------------------------------------------------------
/apps/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "postbuild": "next-sitemap",
9 | "preview": "npx serve out -p 3000",
10 | "lint": "next lint"
11 | },
12 | "dependencies": {
13 | "copy-to-clipboard": "^3.3.3",
14 | "framer-motion": "^11.15.0",
15 | "next": "^14.0.0",
16 | "next-sitemap": "^4.2.3",
17 | "nextra": "^2.13.3",
18 | "nextra-theme-docs": "^2.13.3",
19 | "react": "^18.0.2",
20 | "react-dom": "^18.0.2"
21 | },
22 | "devDependencies": {
23 | "@types/node": "latest",
24 | "@types/react": "latest",
25 | "eslint": "^8.0.0",
26 | "eslint-config-next": "latest"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/apps/docs/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from "next/document";
2 |
3 | export default function MyDocument() {
4 | return (
5 |
6 |
7 | {/* PWA primary color */}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/apps/docs/pages/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Home",
4 | "href": "/"
5 | },
6 | "guides": {
7 | "title": "Guides",
8 | "href": "/guides"
9 | },
10 | "migrations": {
11 | "title": "Migrations",
12 | "href": "/migrations"
13 | },
14 | "api-docs": {
15 | "title": "API",
16 | "href": "/api-docs"
17 | }
18 | }
--------------------------------------------------------------------------------
/apps/docs/pages/guides/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "spa": {
3 | "title": "SPA",
4 | "href": "/guides/spa"
5 | },
6 | "mpa": {
7 | "title": "MPA",
8 | "href": "/guides/mpa"
9 | },
10 | "policy": {
11 | "title": "Creating your Policy",
12 | "href": "/guides/policy"
13 | }
14 | }
--------------------------------------------------------------------------------
/apps/docs/pages/guides/mpa.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from "nextra-theme-docs";
2 |
3 | # Multi-Page Applications (MPAs)
4 |
5 |
6 | Examples of MPA frameworks include Nuxt, Remix, and others.
7 |
8 |
9 | ## Current Status
10 |
11 | ### The Bad News
12 | The **Vite Plugin CSP Guard** package currently does not support Multi-Page Applications (MPAs). Unfortunately, this limitation is unlikely to change due to the inherent differences between how MPAs operate in Vite.
13 |
14 | ### The Good News
15 | You should be able to use the **CSP Toolkit** to generate a nonce & a CSP policy. Check out the [CSP Toolkit documentation](https://csp-toolkit.tsotne.co.uk) for more information. It has framework specific examples for popular frameworks.
16 |
17 |
--------------------------------------------------------------------------------
/apps/docs/pages/migrations/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "v2": {
3 | "title": "V2",
4 | "href": "/migrations/v2"
5 | }
6 | }
--------------------------------------------------------------------------------
/apps/docs/pages/migrations/v2.mdx:
--------------------------------------------------------------------------------
1 | # Upgrade to V2
2 |
3 | ## Key changes:
4 |
5 | - Support for Vite 6
6 | - Full support for [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)
7 |
8 |
9 | ## Required changes
10 |
11 | Stop using `build.hash` inside your `vite.config.ts` this has been removed.
12 | Its instead been replaced by `build.sri`
--------------------------------------------------------------------------------
/apps/docs/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tsotimus/vite-plugin-csp-guard/bd62ed2869dc736d045cb9e03d81968464c95896/apps/docs/public/logo.png
--------------------------------------------------------------------------------
/apps/docs/theme.config.jsx:
--------------------------------------------------------------------------------
1 | export default {
2 | logo:
,
3 | project: {
4 | link: "https://github.com/tsotimus/vite-plugin-csp-guard",
5 | },
6 | docsRepositoryBase: "https://github.com/tsotimus/vite-plugin-csp-guard/tree/main/apps/docs",
7 | useNextSeoProps() {
8 | return {
9 | logo:
,
10 | titleTemplate: "%s | Vite CSP Guard",
11 | description: "Vite CSP Guard",
12 | openGraph: {
13 | description: "A vite plugin to handle your CSP",
14 | siteName: "Vite CSP Guard",
15 | },
16 | twitter: {},
17 | };
18 | },
19 | head: <>>,
20 | feedback: {
21 | content: null,
22 | },
23 | footer: {
24 | text: (
25 |
26 | GPL-3.0 {new Date().getFullYear()} ©{" "}
27 |
28 | Vite CSP Guard{" - "}
29 |
30 | Created by Tsotne
31 |
32 |
33 | ),
34 | },
35 | darkMode: true,
36 | };
37 |
--------------------------------------------------------------------------------
/apps/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/nextjs.json",
3 | "compilerOptions": {
4 | "plugins": [
5 | {
6 | "name": "next"
7 | }
8 | ],
9 | "baseUrl": ".",
10 | "paths": {
11 | "@components/*": ["src/components/*"],
12 | "@styles/*": ["src/styles/*"],
13 | "@features/*": ["src/features/*"],
14 | }
15 | },
16 | "include": [
17 | "next-env.d.ts",
18 | "next.config.js",
19 | "**/*.ts",
20 | "**/*.tsx",
21 | ".next/types/**/*.ts"
22 | , "pages/index.mdx", ],
23 | "exclude": ["node_modules"]
24 | }
25 |
--------------------------------------------------------------------------------
/apps/emotion/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/emotion/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Emotion
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/emotion/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "emotion",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": " tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@emotion/cache": "^11.11.0",
14 | "@emotion/react": "^11.11.4",
15 | "@emotion/styled": "^11.11.5",
16 | "@repo/eslint-config": "workspace:^",
17 | "react": "^18.2.0",
18 | "react-dom": "^18.2.0"
19 | },
20 | "devDependencies": {
21 | "@repo/typescript-config": "workspace:^",
22 | "@repo/testing": "workspace:^",
23 | "@types/react": "^18.2.66",
24 | "@types/react-dom": "^18.2.22",
25 | "@typescript-eslint/eslint-plugin": "^7.2.0",
26 | "@typescript-eslint/parser": "^7.2.0",
27 | "@vitejs/plugin-react": "^4.3.4",
28 | "eslint": "^8.57.0",
29 | "eslint-plugin-react-hooks": "^4.6.0",
30 | "eslint-plugin-react-refresh": "^0.4.6",
31 | "vite-plugin-csp-guard": "workspace:^"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/apps/emotion/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/emotion/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/emotion/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import reactLogo from "./assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.css";
5 | import StyledExample from "./components/StyledExample";
6 |
7 | function App() {
8 | const [count, setCount] = useState(0);
9 |
10 | return (
11 | <>
12 |
20 | Vite + Emotion
21 |
22 |
setCount((count) => count + 1)}>
23 | count is {count}
24 |
25 |
26 | Edit src/App.tsx
and save to test HMR
27 |
28 |
29 |
30 | Click on the Vite and React logos to learn more
31 |
32 | >
33 | );
34 | }
35 |
36 | export default App;
37 |
--------------------------------------------------------------------------------
/apps/emotion/src/components/StyledExample.tsx:
--------------------------------------------------------------------------------
1 | import styled from "@emotion/styled";
2 | import { PropsWithChildren } from "react";
3 |
4 | const Button = styled.button`
5 | color: white;
6 | background-color: red;
7 | padding: 10px;
8 | border: 1px solid black;
9 | cursor: pointer;
10 | &:hover {
11 | color: white;
12 | }
13 | `;
14 | interface StyledExampleProps {
15 | onClick?: () => void
16 | }
17 | const StyledExample = ({children, onClick}:PropsWithChildren) => {
18 | return ;
19 | };
20 |
21 | export default StyledExample;
22 |
--------------------------------------------------------------------------------
/apps/emotion/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/emotion/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App.tsx";
4 | import "./index.css";
5 | import { CacheProvider } from "@emotion/react";
6 | import createCache from "@emotion/cache";
7 |
8 | const customCache = createCache({
9 | key: "custom",
10 | insertionPoint: document.getElementById("emotion-cache")!,
11 | });
12 |
13 | ReactDOM.createRoot(document.getElementById("root")!).render(
14 |
15 |
16 |
17 |
18 |
19 | );
20 |
--------------------------------------------------------------------------------
/apps/emotion/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/emotion/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, jQueryTest, viteLogoTest } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Emotion";
4 | const BTN_COLOUR = "rgb(255, 0, 0)"
5 | const HEADER_COLOUR = "rgb(33, 53, 71)"
6 |
7 | genericTests(TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | jQueryTest()
9 | viteLogoTest();
10 |
--------------------------------------------------------------------------------
/apps/emotion/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/emotion/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }]
5 | }
6 |
--------------------------------------------------------------------------------
/apps/emotion/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/emotion/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption,
9 | csp({
10 | algorithm: "sha256",
11 | dev: {
12 | run: true,
13 | },
14 | policy: {
15 | "style-src-elem": ["'self'", "'unsafe-inline'"],
16 | },
17 | build: {
18 | sri: true,
19 | },
20 | }),
21 | ],
22 | preview: {
23 | port: 4002,
24 | },
25 | server: {
26 | port: 3002,
27 | },
28 | });
29 |
--------------------------------------------------------------------------------
/apps/less/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/less/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Less
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/less/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "less",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.3.1",
14 | "react-dom": "^18.3.1"
15 | },
16 | "devDependencies": {
17 | "@repo/eslint-config": "workspace:^",
18 | "@repo/typescript-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.3.3",
21 | "@types/react-dom": "^18.3.0",
22 | "@typescript-eslint/eslint-plugin": "^7.13.1",
23 | "@typescript-eslint/parser": "^7.13.1",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.2",
27 | "eslint-plugin-react-refresh": "^0.4.7",
28 | "less": "^4.2.0",
29 | "vite-plugin-csp-guard": "workspace:^"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/apps/less/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/less/src/components/App.less:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/less/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.less";
5 | import Button from "./Button";
6 |
7 | function App() {
8 | const [count, setCount] = useState(0);
9 |
10 | return (
11 | <>
12 |
20 | Vite + Less
21 |
22 |
25 |
26 | Edit src/App.tsx
and save to test HMR
27 |
28 |
29 |
30 | Click on the Vite and React logos to learn more
31 |
32 | >
33 | );
34 | }
35 |
36 | export default App;
37 |
--------------------------------------------------------------------------------
/apps/less/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import { ButtonHTMLAttributes, PropsWithChildren } from "react";
2 | import s from "./button.module.less";
3 | type ButtonProps = ButtonHTMLAttributes;
4 |
5 | const Button = (props: PropsWithChildren) => {
6 | return (
7 |
10 | );
11 | };
12 |
13 | export default Button;
14 |
--------------------------------------------------------------------------------
/apps/less/src/components/button.module.less:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | .button {
4 | color: white;
5 | background-color: @color-primary;
6 | padding: 1em 2em;
7 | border: 1px solid @color-dark;
8 | }
--------------------------------------------------------------------------------
/apps/less/src/components/variables.less:
--------------------------------------------------------------------------------
1 | // Primary Palette
2 | @color-primary: #007bff;
3 | @color-secondary: #6c757d;
4 | @color-success: #28a745;
5 | @color-info: #17a2b8;
6 | @color-warning: #ffc107;
7 | @color-danger: #dc3545;
8 | @color-light: #f8f9fa;
9 | @color-dark: #343a40;
10 |
--------------------------------------------------------------------------------
/apps/less/src/index.less:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/less/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.js";
4 | import "./index.less";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/less/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/less/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Less";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)"
5 | const BTN_COLOUR = "rgb(0, 123, 255)"
6 |
7 | genericTests(TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | viteLogoTest();
9 |
--------------------------------------------------------------------------------
/apps/less/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/less/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/vite",
4 | "include": ["src"],
5 | "compilerOptions": {
6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
7 | },
8 | "references": [{ "path": "./tsconfig.node.json" }],
9 | }
10 |
--------------------------------------------------------------------------------
/apps/less/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/less/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption[], //This is a type assertion due to a monorepo issue regarding stylus, this is not needed in a normal project
9 | csp({
10 | dev: {
11 | run: true,
12 | outlierSupport: ["less"],
13 | },
14 | build: {
15 | sri: true,
16 | },
17 | })
18 | ],
19 | preview: {
20 | port: 4005,
21 | },
22 | server: {
23 | port: 3005,
24 | },
25 | });
26 |
--------------------------------------------------------------------------------
/apps/mui/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/mui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 | Vite + Material UI + TS
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apps/mui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mui",
3 | "private": true,
4 | "version": "5.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@emotion/react": "latest",
14 | "@emotion/styled": "latest",
15 | "@mui/icons-material": "next",
16 | "@mui/material": "next",
17 | "react": "^18.2.0",
18 | "react-dom": "^18.2.0"
19 | },
20 | "devDependencies": {
21 | "@types/react": "^18.2.66",
22 | "@types/react-dom": "^18.2.22",
23 | "@vitejs/plugin-react": "^4.3.4",
24 | "eslint": "^8.57.0",
25 | "eslint-plugin-react-hooks": "^4.6.0",
26 | "eslint-plugin-react-refresh": "^0.4.6",
27 | "vite-plugin-csp-guard": "workspace:^",
28 | "@repo/typescript-config": "workspace:^",
29 | "@repo/testing": "workspace:^",
30 | "@repo/eslint-config": "workspace:^"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/apps/mui/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/mui/src/App.tsx:
--------------------------------------------------------------------------------
1 | import Container from "@mui/material/Container";
2 | import Typography from "@mui/material/Typography";
3 | import Box from "@mui/material/Box";
4 | import { Button } from "@mui/material";
5 | import { useState } from "react";
6 | import viteLogo from "/vite.svg";
7 |
8 | export default function App() {
9 |
10 | const [count, setCount] = useState(0)
11 |
12 | return (
13 |
14 |
15 |
16 |
21 | Vite + Material UI + TS
22 |
23 |
24 |
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/apps/mui/src/main.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom/client';
3 | import { ThemeProvider } from '@emotion/react';
4 | import { CssBaseline } from '@mui/material';
5 | import theme from './theme';
6 | import App from './App';
7 |
8 | ReactDOM.createRoot(document.getElementById('root')!).render(
9 |
10 |
11 |
12 |
13 |
14 | ,
15 | );
16 |
--------------------------------------------------------------------------------
/apps/mui/src/theme.tsx:
--------------------------------------------------------------------------------
1 | import { createTheme } from '@mui/material/styles';
2 | import { red } from '@mui/material/colors';
3 |
4 | // A custom theme for this app
5 | const theme = createTheme({
6 | palette: {
7 | primary: {
8 | main: '#556cd6',
9 | },
10 | secondary: {
11 | main: '#19857b',
12 | },
13 | error: {
14 | main: red.A400,
15 | },
16 | },
17 | });
18 |
19 | export default theme;
20 |
--------------------------------------------------------------------------------
/apps/mui/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/mui/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from "@playwright/test";
2 | import { genericTests, jQueryTest, viteLogoTest } from '@repo/testing';
3 |
4 | const TITLE = "Vite + Material UI + TS";
5 | const HEADER_COLOUR = "rgb(63, 80, 181)"
6 | const BTN_COLOUR = "rgb(0, 0, 255)"
7 |
8 | genericTests(TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
9 | viteLogoTest();
10 | test("Roboto font is loaded", async ({ page }) => {
11 | await page.goto("/");
12 |
13 | const element = page.getByRole("heading", { name: TITLE });
14 | await expect(element).toBeVisible();
15 |
16 | const fontFamily = await element.evaluate(
17 | (el) => window.getComputedStyle(el).fontFamily
18 | );
19 |
20 | expect(fontFamily).toBe("Roboto, Helvetica, Arial, sans-serif");
21 | });
22 |
--------------------------------------------------------------------------------
/apps/mui/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/mui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }]
5 | }
6 |
--------------------------------------------------------------------------------
/apps/mui/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/mui/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption,
9 | csp({
10 | algorithm: "sha256",
11 | dev: {
12 | run: true,
13 | },
14 | policy: {
15 | "style-src-elem": [
16 | "'self'",
17 | "https://fonts.googleapis.com",
18 | "'unsafe-inline'",
19 | ],
20 | "font-src": ["'self'", "https://fonts.gstatic.com"],
21 | },
22 | build: {
23 | sri: true,
24 | },
25 | }),
26 | ],
27 | preview: {
28 | port: 4001,
29 | },
30 | server: {
31 | port: 3001,
32 | },
33 | });
34 |
--------------------------------------------------------------------------------
/apps/preact-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Preact
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/preact-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "preact-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "preact": "^10.22.1"
13 | },
14 | "devDependencies": {
15 | "@preact/preset-vite": "^2.8.3",
16 | "vite-plugin-csp-guard": "workspace:^",
17 | "@repo/testing": "workspace:^",
18 | "@repo/typescript-config": "workspace:^"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/apps/preact-app/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/preact-app/src/app.css:
--------------------------------------------------------------------------------
1 | #app {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | }
12 | .logo:hover {
13 | filter: drop-shadow(0 0 2em #646cffaa);
14 | }
15 | .logo.preact:hover {
16 | filter: drop-shadow(0 0 2em #673ab8aa);
17 | }
18 |
19 | .card {
20 | padding: 2em;
21 | }
22 |
23 | .read-the-docs {
24 | color: #888;
25 | }
26 |
27 | .button{
28 | background-color: #673ab8;
29 | color: white;
30 | padding: 1em 2em;
31 | border: none;
32 | border-radius: 0.5em;
33 | font-size: 1em;
34 | cursor: pointer;
35 | }
36 |
--------------------------------------------------------------------------------
/apps/preact-app/src/app.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "preact/hooks";
2 | import preactLogo from "./assets/preact.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./app.css";
5 |
6 | export function App() {
7 | const [count, setCount] = useState(0);
8 |
9 | return (
10 | <>
11 |
19 | Vite + Preact
20 |
21 |
27 |
28 | Edit src/app.tsx
and save to test HMR
29 |
30 |
31 |
32 | Check out{" "}
33 |
37 | create-preact
38 |
39 | , the official Preact + Vite starter
40 |
41 |
42 | Click on the Vite and Preact logos to learn more
43 |
44 | >
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/apps/preact-app/src/assets/preact.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/preact-app/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/preact-app/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { render } from 'preact'
2 | import { App } from './app.tsx'
3 | import './index.css'
4 |
5 | render(, document.getElementById('app')!)
6 |
--------------------------------------------------------------------------------
/apps/preact-app/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/preact-app/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Preact";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)"
5 | const BTN_COLOUR = "rgb(103, 58, 184)"
6 |
7 | genericTests(TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | viteLogoTest();
--------------------------------------------------------------------------------
/apps/preact-app/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/preact-app/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 | "target": "ES2020",
6 | "useDefineForClassFields": true,
7 | "module": "ESNext",
8 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
9 | "skipLibCheck": true,
10 | "paths": {
11 | "react": ["./node_modules/preact/compat/"],
12 | "react-dom": ["./node_modules/preact/compat/"]
13 | },
14 |
15 | /* Bundler mode */
16 | "moduleResolution": "bundler",
17 | "allowImportingTsExtensions": true,
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "moduleDetection": "force",
21 | "noEmit": true,
22 | "jsx": "react-jsx",
23 | "jsxImportSource": "preact",
24 |
25 | /* Linting */
26 | "strict": true,
27 | "noUnusedLocals": true,
28 | "noUnusedParameters": true,
29 | "noFallthroughCasesInSwitch": true
30 | },
31 | "include": ["src"]
32 | }
33 |
--------------------------------------------------------------------------------
/apps/preact-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | {
5 | "path": "./tsconfig.app.json"
6 | },
7 | {
8 | "path": "./tsconfig.node.json"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/apps/preact-app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "noEmit": true
11 | },
12 | "include": ["vite.config.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/preact-app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import preact from "@preact/preset-vite";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | preact() as PluginOption,
9 | csp({
10 | dev: {
11 | run: true,
12 | },
13 | build: {
14 | sri: true,
15 | },
16 | })
17 | ],
18 | preview: {
19 | port: 4009,
20 | },
21 | server: {
22 | port: 3009,
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/apps/react/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@repo/eslint-config": "workspace:^",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0"
16 | },
17 | "devDependencies": {
18 | "@repo/typescript-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.2.66",
21 | "@types/react-dom": "^18.2.22",
22 | "@typescript-eslint/eslint-plugin": "^7.2.0",
23 | "@typescript-eslint/parser": "^7.2.0",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.0",
27 | "eslint-plugin-react-refresh": "^0.4.6",
28 | "vite-plugin-csp-guard": "workspace:^"
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/apps/react/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/react/src/components/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/react/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState, lazy } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.css";
5 |
6 | const Home = lazy(() => import("./Home"));
7 |
8 | function App() {
9 | const [count, setCount] = useState(0);
10 |
11 | return (
12 | <>
13 |
21 | Vite + React
22 |
23 |
24 |
27 |
28 | Edit src/App.tsx
and save to test HMR
29 |
30 |
31 |
32 | Click on the Vite and React logos to learn more
33 |
34 | >
35 | );
36 | }
37 |
38 | export default App;
39 |
--------------------------------------------------------------------------------
/apps/react/src/components/Home.tsx:
--------------------------------------------------------------------------------
1 | import Injector from "./Injector";
2 |
3 | const Home = () => {
4 | return (
5 |
6 |
Home
7 |
8 |
9 | );
10 | };
11 |
12 | export default Home;
13 |
--------------------------------------------------------------------------------
/apps/react/src/components/Injector.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | const Injector = () => {
4 | const injectScript = (scriptContent: string) => {
5 | const script = document.createElement("script");
6 | script.textContent = scriptContent;
7 | script.async = true;
8 | document.body.appendChild(script);
9 | };
10 |
11 | useEffect(() => {
12 | const scriptContent = `
13 | // Your inline script code here
14 | console.log('Inline script executed');
15 | `;
16 | injectScript(scriptContent);
17 | }, []);
18 |
19 | return <>>;
20 | };
21 |
22 | export default Injector;
23 |
--------------------------------------------------------------------------------
/apps/react/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/react/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.tsx";
4 | import "./index.css";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/react/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/react/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, jQueryTest, inlineScriptBlockedTest, viteLogoTest } from '@repo/testing';
2 |
3 | const APP_TITLE = "Vite + React";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)"
5 | const BTN_COLOUR = "rgb(255, 0, 0)"
6 |
7 | genericTests(APP_TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | jQueryTest()
9 | viteLogoTest();
10 | inlineScriptBlockedTest(APP_TITLE)
11 |
12 |
--------------------------------------------------------------------------------
/apps/react/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }]
5 | }
6 |
--------------------------------------------------------------------------------
/apps/react/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts",]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption,
9 | csp({
10 | algorithm: "sha256",
11 | dev: {
12 | run: true,
13 | },
14 | policy: {
15 | "font-src": ["https://fonts.gstatic.com"],
16 | "connect-src": ["*"],
17 | "object-src": ["'none'"],
18 | },
19 | build: {
20 | sri: true
21 | },
22 | }),
23 | ],
24 | preview: {
25 | port: 4000,
26 | },
27 | server: {
28 | port: 3000,
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/apps/remix-spa/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/apps/remix-spa/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | Meta,
4 | Outlet,
5 | Scripts,
6 | ScrollRestoration,
7 | } from "@remix-run/react";
8 | import "./tailwind.css";
9 |
10 | export function Layout({ children }: { children: React.ReactNode }) {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | {children}
21 |
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default function App() {
29 | return ;
30 | }
31 |
--------------------------------------------------------------------------------
/apps/remix-spa/app/routes/_index.tsx:
--------------------------------------------------------------------------------
1 | import type { MetaFunction } from "@remix-run/node";
2 |
3 | export const meta: MetaFunction = () => {
4 | return [
5 | { title: "New Remix App" },
6 | { name: "description", content: "Welcome to Remix!" },
7 | ];
8 | };
9 |
10 | export default function Index() {
11 | return (
12 |
13 |
Welcome to Remix
14 |
46 |
47 | );
48 | }
49 |
--------------------------------------------------------------------------------
/apps/remix-spa/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/apps/remix-spa/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "remix-spa",
3 | "private": true,
4 | "sideEffects": false,
5 | "type": "module",
6 | "scripts": {
7 | "build": "remix vite:build",
8 | "dev": "remix vite:dev",
9 | "preview": "vite preview",
10 | "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
11 | "start": "remix-serve ./build/server/index.js",
12 | "typecheck": "tsc"
13 | },
14 | "dependencies": {
15 | "@remix-run/node": "^2.16.0",
16 | "@remix-run/react": "^2.16.0",
17 | "@remix-run/serve": "^2.16.0",
18 | "isbot": "^4.1.0",
19 | "react": "^18.2.0",
20 | "react-dom": "^18.2.0"
21 | },
22 | "devDependencies": {
23 | "@remix-run/dev": "^2.16.0",
24 | "@repo/testing": "workspace:^",
25 | "@repo/typescript-config": "workspace:^",
26 | "@types/react": "^18.2.20",
27 | "@types/react-dom": "^18.2.7",
28 | "@typescript-eslint/eslint-plugin": "^6.7.4",
29 | "@typescript-eslint/parser": "^6.7.4",
30 | "autoprefixer": "^10.4.19",
31 | "eslint": "^8.38.0",
32 | "eslint-import-resolver-typescript": "^3.6.1",
33 | "eslint-plugin-import": "^2.28.1",
34 | "eslint-plugin-jsx-a11y": "^6.7.1",
35 | "eslint-plugin-react": "^7.37.3",
36 | "eslint-plugin-react-hooks": "^4.6.0",
37 | "postcss": "^8.4.38",
38 | "tailwindcss": "^3.4.4",
39 | "vite": "^5.1.0",
40 | "vite-plugin-csp-guard": "workspace:^",
41 | "vite-tsconfig-paths": "^4.2.1"
42 | },
43 | "engines": {
44 | "node": ">=20.0.0"
45 | }
46 | }
--------------------------------------------------------------------------------
/apps/remix-spa/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/apps/remix-spa/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tsotimus/vite-plugin-csp-guard/bd62ed2869dc736d045cb9e03d81968464c95896/apps/remix-spa/public/favicon.ico
--------------------------------------------------------------------------------
/apps/remix-spa/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
5 | theme: {
6 | extend: {},
7 | },
8 | plugins: [],
9 | } satisfies Config;
10 |
--------------------------------------------------------------------------------
/apps/remix-spa/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "**/*.ts",
4 | "**/*.tsx",
5 | "**/.server/**/*.ts",
6 | "**/.server/**/*.tsx",
7 | "**/.client/**/*.ts",
8 | "**/.client/**/*.tsx"
9 | ],
10 | "compilerOptions": {
11 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
12 | "types": ["@remix-run/node", "vite/client"],
13 | "isolatedModules": true,
14 | "esModuleInterop": true,
15 | "jsx": "react-jsx",
16 | "module": "ESNext",
17 | "moduleResolution": "Bundler",
18 | "resolveJsonModule": true,
19 | "target": "ES2022",
20 | "strict": true,
21 | "allowJs": true,
22 | "skipLibCheck": true,
23 | "forceConsistentCasingInFileNames": true,
24 | "baseUrl": ".",
25 | "paths": {
26 | "~/*": ["./app/*"]
27 | },
28 |
29 | // Vite takes care of building everything, not tsc.
30 | "noEmit": true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/apps/remix-spa/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig, PluginOption } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 | import csp from "vite-plugin-csp-guard";
5 |
6 | export default defineConfig({
7 | plugins: [
8 | remix({
9 | future: {
10 | v3_fetcherPersist: true,
11 | v3_relativeSplatPath: true,
12 | v3_throwAbortReason: true,
13 | },
14 | ssr: false,
15 | }),
16 | tsconfigPaths() as PluginOption,
17 | csp({
18 | dev: {
19 | run: true,
20 | },
21 | features: {
22 | mpa: true,
23 | },
24 | }) as PluginOption,
25 | ],
26 | preview: {
27 | port: 4009,
28 | },
29 | server: {
30 | port: 3009,
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/apps/scss/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/scss/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Sass
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/scss/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scss",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.3.1",
14 | "react-dom": "^18.3.1"
15 | },
16 | "devDependencies": {
17 | "@repo/typescript-config": "workspace:^",
18 | "@repo/testing": "workspace:^",
19 | "@types/react": "^18.3.3",
20 | "@types/react-dom": "^18.3.0",
21 | "@typescript-eslint/eslint-plugin": "^7.13.1",
22 | "@typescript-eslint/parser": "^7.13.1",
23 | "@vitejs/plugin-react": "^4.3.4",
24 | "eslint": "^8.57.0",
25 | "eslint-plugin-react-hooks": "^4.6.2",
26 | "eslint-plugin-react-refresh": "^0.4.7",
27 | "sass": "^1.77.8",
28 | "vite-plugin-csp-guard": "workspace:^"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/apps/scss/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/scss/src/components/App.scss:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/scss/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.scss";
5 | import Button from "./Button";
6 |
7 | function App() {
8 | const [count, setCount] = useState(0);
9 |
10 | return (
11 | <>
12 |
20 | Vite + Sass
21 |
22 |
25 |
26 | Edit src/App.tsx
and save to test HMR
27 |
28 |
29 |
30 | Click on the Vite and React logos to learn more
31 |
32 | >
33 | );
34 | }
35 |
36 | export default App;
37 |
--------------------------------------------------------------------------------
/apps/scss/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import { ButtonHTMLAttributes, PropsWithChildren } from "react";
2 | import s from "./button.module.scss";
3 | type ButtonProps = ButtonHTMLAttributes;
4 |
5 | const Button = (props: PropsWithChildren) => {
6 | return (
7 |
10 | );
11 | };
12 |
13 | export default Button;
14 |
--------------------------------------------------------------------------------
/apps/scss/src/components/button.module.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | .button {
4 | color: "white";
5 | background-color: $color-primary;
6 | padding: 1em 2em;
7 | border: 1px solid $color-dark;
8 | }
9 |
--------------------------------------------------------------------------------
/apps/scss/src/components/variables.scss:
--------------------------------------------------------------------------------
1 | // Primary Palette
2 | $color-primary: #007bff;
3 | $color-secondary: #6c757d;
4 | $color-success: #28a745;
5 | $color-info: #17a2b8;
6 | $color-warning: #ffc107;
7 | $color-danger: #dc3545;
8 | $color-light: #f8f9fa;
9 | $color-dark: #343a40;
10 |
--------------------------------------------------------------------------------
/apps/scss/src/index.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/scss/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.js";
4 | import "./index.scss";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/scss/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/scss/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest} from '@repo/testing';
2 |
3 | const TITLE = "Vite + Sass";
4 | const BTN_COLOUR = "rgb(0, 123, 255)"
5 | const HEADER_COLOR = "rgb(33, 53, 71)"
6 |
7 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
8 | viteLogoTest();
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/scss/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/scss/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }],
5 | "compilerOptions": {
6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/scss/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/scss/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption[], //This is a type assertion due to a monorepo issue regarding stylus, this is not needed in a normal project
9 | csp({
10 | dev: {
11 | run: true,
12 | outlierSupport: ["sass"],
13 | },
14 | build: {
15 | sri: true,
16 | },
17 | })
18 | ],
19 | preview: {
20 | port: 4004,
21 | },
22 | server: {
23 | port: 3004,
24 | },
25 | });
26 |
--------------------------------------------------------------------------------
/apps/solid-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Solid
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/solid-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "solid-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "solid-js": "^1.8.18"
13 | },
14 | "devDependencies": {
15 | "vite-plugin-solid": "^2.10.2",
16 | "vite-plugin-csp-guard": "workspace:^",
17 | "@repo/typescript-config": "workspace:^",
18 | "@repo/testing": "workspace:^"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/apps/solid-app/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/solid-app/src/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.solid:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | .card {
22 | padding: 2em;
23 | }
24 |
25 | .read-the-docs {
26 | color: #888;
27 | }
28 |
--------------------------------------------------------------------------------
/apps/solid-app/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { createSignal } from 'solid-js'
2 | import solidLogo from './assets/solid.svg'
3 | import viteLogo from '/vite.svg'
4 | import './App.css'
5 |
6 | function App() {
7 | const [count, setCount] = createSignal(0)
8 |
9 | return (
10 | <>
11 |
19 | Vite + Solid
20 |
21 |
24 |
25 | Edit src/App.tsx
and save to test HMR
26 |
27 |
28 |
29 | Click on the Vite and Solid logos to learn more
30 |
31 | >
32 | )
33 | }
34 |
35 | export default App
36 |
--------------------------------------------------------------------------------
/apps/solid-app/src/assets/solid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/solid-app/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/solid-app/src/index.tsx:
--------------------------------------------------------------------------------
1 | /* @refresh reload */
2 | import { render } from 'solid-js/web'
3 |
4 | import './index.css'
5 | import App from './App'
6 |
7 | const root = document.getElementById('root')
8 |
9 | render(() => , root!)
10 |
--------------------------------------------------------------------------------
/apps/solid-app/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/solid-app/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Solid";
4 |
5 |
6 | const HEADER_COLOR = "rgb(33, 53, 71)"
7 | const BTN_COLOUR = "rgb(255, 0, 0)"
8 |
9 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
10 | viteLogoTest();
11 |
--------------------------------------------------------------------------------
/apps/solid-app/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/solid-app/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 | "target": "ES2020",
6 | "useDefineForClassFields": true,
7 | "module": "ESNext",
8 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
9 | "skipLibCheck": true,
10 |
11 | /* Bundler mode */
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "moduleDetection": "force",
17 | "noEmit": true,
18 | "jsx": "preserve",
19 | "jsxImportSource": "solid-js",
20 |
21 | /* Linting */
22 | "strict": true,
23 | "noUnusedLocals": true,
24 | "noUnusedParameters": true,
25 | "noFallthroughCasesInSwitch": true
26 | },
27 | "include": ["src"]
28 | }
29 |
--------------------------------------------------------------------------------
/apps/solid-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | {
5 | "path": "./tsconfig.app.json"
6 | },
7 | {
8 | "path": "./tsconfig.node.json"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/apps/solid-app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "noEmit": true
11 | },
12 | "include": ["vite.config.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/solid-app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import solid from "vite-plugin-solid";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | export default defineConfig({
6 | plugins: [
7 | solid() as PluginOption,
8 | csp({ dev: { run: true }, build: { sri: true } }) as PluginOption,
9 | ],
10 | preview: {
11 | port: 4010,
12 | },
13 | server: {
14 | port: 3010,
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/apps/stylus/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/stylus/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Stylus
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/stylus/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stylus",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@repo/eslint-config": "workspace:^",
14 | "react": "^18.3.1",
15 | "react-dom": "^18.3.1"
16 | },
17 | "devDependencies": {
18 | "@repo/typescript-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.3.3",
21 | "@types/react-dom": "^18.3.0",
22 | "@typescript-eslint/eslint-plugin": "^7.13.1",
23 | "@typescript-eslint/parser": "^7.13.1",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.2",
27 | "eslint-plugin-react-refresh": "^0.4.7",
28 | "stylus": "^0.63.0",
29 | "vite-plugin-csp-guard": "workspace:^"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/apps/stylus/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/stylus/src/components/App.styl:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/stylus/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.styl";
5 | import Button from "./Button";
6 |
7 | function App() {
8 | const [count, setCount] = useState(0);
9 |
10 | return (
11 | <>
12 |
20 | Vite + Stylus
21 |
22 |
25 |
26 | Edit src/App.tsx
and save to test HMR
27 |
28 |
29 |
30 | Click on the Vite and React logos to learn more
31 |
32 | >
33 | );
34 | }
35 |
36 | export default App;
37 |
--------------------------------------------------------------------------------
/apps/stylus/src/components/Button.tsx:
--------------------------------------------------------------------------------
1 | import { ButtonHTMLAttributes, PropsWithChildren } from "react";
2 | import s from "./button.module.styl";
3 | type ButtonProps = ButtonHTMLAttributes;
4 |
5 | const Button = (props: PropsWithChildren) => {
6 | return (
7 |
10 | );
11 | };
12 |
13 | export default Button;
14 |
--------------------------------------------------------------------------------
/apps/stylus/src/components/button.module.styl:
--------------------------------------------------------------------------------
1 | @import 'variables.styl'
2 |
3 | .button
4 | color: white
5 | background-color: color-primary
6 | padding: 1em 2em
7 | border: 1px solid color-dark
8 |
--------------------------------------------------------------------------------
/apps/stylus/src/components/variables.styl:
--------------------------------------------------------------------------------
1 | // Primary Palette
2 | color-primary = #007bff
3 | color-secondary = #6c757d
4 | color-success = #28a745
5 | color-info = #17a2b8
6 | color-warning = #ffc107
7 | color-danger = #dc3545
8 | color-light = #f8f9fa
9 | color-dark = #343a40
--------------------------------------------------------------------------------
/apps/stylus/src/index.styl:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/stylus/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.js";
4 | import "./index.styl";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/stylus/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/stylus/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Stylus";
4 | const BTN_COLOUR = "rgb(0, 123, 255)"
5 | const HEADER_COLOR = "rgb(33, 53, 71)"
6 |
7 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
8 | viteLogoTest();
--------------------------------------------------------------------------------
/apps/stylus/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/stylus/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }],
5 | "compilerOptions": {
6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/apps/stylus/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/stylus/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption[], //This is a type assertion due to a monorepo issue regarding stylus, this is not needed in a normal project
9 | csp({
10 | dev: {
11 | run: true,
12 | outlierSupport: ["stylus"],
13 | },
14 | build: {
15 | sri: true,
16 | },
17 | }),
18 | ],
19 | preview: {
20 | port: 4006,
21 | },
22 | server: {
23 | port: 3006,
24 | },
25 | });
26 |
--------------------------------------------------------------------------------
/apps/svelte-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Svelte
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/svelte-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svelte-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview",
10 | "check": "svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json"
11 | },
12 | "devDependencies": {
13 | "@repo/typescript-config": "workspace:^",
14 | "@repo/testing": "workspace:^",
15 | "@sveltejs/vite-plugin-svelte": "^3.1.1",
16 | "@tsconfig/svelte": "^5.0.4",
17 | "svelte": "^4.2.18",
18 | "svelte-check": "^4.1.1",
19 | "tslib": "^2.6.3",
20 | "vite": "^5.0.0",
21 | "vite-plugin-csp-guard": "workspace:^"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/apps/svelte-app/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/svelte-app/src/App.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
16 | Vite + Svelte
17 |
18 |
19 |
20 |
21 |
22 |
23 | Check out SvelteKit, the official Svelte app framework powered by Vite!
24 |
25 |
26 |
27 | Click on the Vite and Svelte logos to learn more
28 |
29 |
30 |
31 |
48 |
--------------------------------------------------------------------------------
/apps/svelte-app/src/lib/Counter.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
12 |
26 |
--------------------------------------------------------------------------------
/apps/svelte-app/src/main.ts:
--------------------------------------------------------------------------------
1 | import './app.css'
2 | import App from './App.svelte'
3 |
4 | const app = new App({
5 | target: document.getElementById('app')!,
6 | })
7 |
8 | export default app
9 |
--------------------------------------------------------------------------------
/apps/svelte-app/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/apps/svelte-app/svelte.config.js:
--------------------------------------------------------------------------------
1 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
2 |
3 | export default {
4 | // Consult https://svelte.dev/docs#compile-time-svelte-preprocess
5 | // for more information about preprocessors
6 | preprocess: vitePreprocess(),
7 | }
8 |
--------------------------------------------------------------------------------
/apps/svelte-app/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests,viteLogoTest } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Svelte";
4 |
5 | const BTN_COLOUR = "rgb(255, 62, 0)"
6 | const HEADER_COLOR = "rgb(33, 53, 71)"
7 |
8 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
9 | viteLogoTest()
--------------------------------------------------------------------------------
/apps/svelte-app/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/svelte-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/svelte/tsconfig.json",
3 | "compilerOptions": {
4 | "target": "ESNext",
5 | "useDefineForClassFields": true,
6 | "module": "ESNext",
7 | "resolveJsonModule": true,
8 | /**
9 | * Typecheck JS in `.svelte` and `.js` files by default.
10 | * Disable checkJs if you'd like to use dynamic types in JS.
11 | * Note that setting allowJs false does not prevent the use
12 | * of JS in `.svelte` files.
13 | */
14 | "allowJs": true,
15 | "checkJs": true,
16 | "isolatedModules": true,
17 | "moduleDetection": "force"
18 | },
19 | "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/apps/svelte-app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "strict": true,
9 | },
10 | "include": ["vite.config.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/apps/svelte-app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import { svelte } from "@sveltejs/vite-plugin-svelte";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | svelte(),
9 | csp({
10 | dev: {
11 | run: true,
12 | },
13 | build: {
14 | sri: true,
15 | },
16 | }) as PluginOption,
17 | ],
18 | preview: {
19 | port: 4008,
20 | },
21 | server: {
22 | port: 3008,
23 | },
24 | });
25 |
--------------------------------------------------------------------------------
/apps/tailwind/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/tailwind/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Tailwind
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/tailwind/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@repo/eslint-config": "workspace:^",
14 | "react": "^18.3.1",
15 | "react-dom": "^18.3.1"
16 | },
17 | "devDependencies": {
18 | "@repo/typescript-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.3.3",
21 | "@types/react-dom": "^18.3.0",
22 | "@typescript-eslint/eslint-plugin": "^7.13.1",
23 | "@typescript-eslint/parser": "^7.13.1",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "autoprefixer": "^10.4.19",
26 | "eslint": "^8.57.0",
27 | "eslint-plugin-react-hooks": "^4.6.2",
28 | "eslint-plugin-react-refresh": "^0.4.7",
29 | "postcss": "^8.4.39",
30 | "tailwindcss": "^3.4.4",
31 | "vite-plugin-csp-guard": "workspace:^"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/apps/tailwind/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/apps/tailwind/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/tailwind/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function App() {
4 | const [count, setCount] = useState(0);
5 |
6 | return (
7 |
8 |
Vite + Tailwind
9 |
10 |
16 |
17 | Edit{" "}
18 |
19 | src/App.tsx
20 |
{" "}
21 | and save to test HMR
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/apps/tailwind/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/apps/tailwind/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/apps/tailwind/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/tailwind/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | export default {
3 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | };
9 |
--------------------------------------------------------------------------------
/apps/tailwind/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Tailwind";
4 | const BTN_COLOUR = "rgb(59, 130, 246)"
5 | const HEADER_COLOR = "rgb(0, 0, 0)"
6 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
7 |
--------------------------------------------------------------------------------
/apps/tailwind/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/tailwind/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 | "target": "ES2020",
6 | "useDefineForClassFields": true,
7 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
8 | "module": "ESNext",
9 | "skipLibCheck": true,
10 |
11 | /* Bundler mode */
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "moduleDetection": "force",
17 | "noEmit": true,
18 | "jsx": "react-jsx",
19 |
20 | /* Linting */
21 | "strict": true,
22 | "noUnusedLocals": true,
23 | "noUnusedParameters": true,
24 | "noFallthroughCasesInSwitch": true
25 | },
26 | "include": ["src"]
27 | }
28 |
--------------------------------------------------------------------------------
/apps/tailwind/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | {
5 | "path": "./tsconfig.app.json"
6 | },
7 | {
8 | "path": "./tsconfig.node.json"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/apps/tailwind/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | "noEmit": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/apps/tailwind/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react() as PluginOption,
9 | csp({
10 | dev: {
11 | run: true,
12 | outlierSupport: ["tailwind"],
13 | },
14 | build: {
15 | sri: true,
16 | },
17 | }),
18 | ],
19 | preview: {
20 | port: 4003,
21 | },
22 | server: {
23 | port: 3003,
24 | },
25 | });
26 |
--------------------------------------------------------------------------------
/apps/tailwind4/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/tailwind4/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Tailwind 4
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/tailwind4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind4",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@repo/eslint-config": "workspace:^",
14 | "@tailwindcss/vite": "^4.0.9",
15 | "react": "^18.3.1",
16 | "react-dom": "^18.3.1",
17 | "tailwindcss": "^4.0.0"
18 | },
19 | "devDependencies": {
20 | "@repo/testing": "workspace:^",
21 | "@repo/typescript-config": "workspace:^",
22 | "@types/react": "^18.3.3",
23 | "@types/react-dom": "^18.3.0",
24 | "@typescript-eslint/eslint-plugin": "^7.13.1",
25 | "@typescript-eslint/parser": "^7.13.1",
26 | "@vitejs/plugin-react": "^4.3.4",
27 | "autoprefixer": "^10.4.19",
28 | "eslint": "^8.57.0",
29 | "eslint-plugin-react-hooks": "^4.6.2",
30 | "eslint-plugin-react-refresh": "^0.4.7",
31 | "vite-plugin-csp-guard": "workspace:^"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/apps/tailwind4/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/tailwind4/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | function App() {
4 | const [count, setCount] = useState(0);
5 |
6 | return (
7 |
8 |
Vite + Tailwind 4
9 |
10 |
16 |
17 | Edit{" "}
18 |
19 | src/App.tsx
20 |
{" "}
21 | and save to test HMR
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/apps/tailwind4/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.tsx'
4 | // import './style.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/apps/tailwind4/src/style.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
--------------------------------------------------------------------------------
/apps/tailwind4/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/tailwind4/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | export default {
3 | content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | };
9 |
--------------------------------------------------------------------------------
/apps/tailwind4/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Tailwind 4";
4 | const BTN_COLOUR = "oklch(0.623 0.214 259.815)"
5 | const HEADER_COLOR = "rgb(0, 0, 0)"
6 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
7 |
--------------------------------------------------------------------------------
/apps/tailwind4/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/tailwind4/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 | "target": "ES2020",
6 | "useDefineForClassFields": true,
7 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
8 | "module": "ESNext",
9 | "skipLibCheck": true,
10 |
11 | /* Bundler mode */
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "moduleDetection": "force",
17 | "noEmit": true,
18 | "jsx": "react-jsx",
19 |
20 | /* Linting */
21 | "strict": true,
22 | "noUnusedLocals": true,
23 | "noUnusedParameters": true,
24 | "noFallthroughCasesInSwitch": true
25 | },
26 | "include": ["src"]
27 | }
28 |
--------------------------------------------------------------------------------
/apps/tailwind4/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | {
5 | "path": "./tsconfig.app.json"
6 | },
7 | {
8 | "path": "./tsconfig.node.json"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/apps/tailwind4/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | "noEmit": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/apps/tailwind4/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 | import tailwindcss from "@tailwindcss/vite";
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | plugins: [
9 | react() as PluginOption,
10 | tailwindcss() as PluginOption,
11 | csp({
12 | dev: {
13 | run: true,
14 | outlierSupport: ["tailwind"],
15 | },
16 | build: {
17 | sri: true,
18 | },
19 | }),
20 | ],
21 | preview: {
22 | port: 4014,
23 | },
24 | server: {
25 | port: 3014,
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/apps/vite4/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/vite4/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/vite4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite4",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0"
15 | },
16 | "devDependencies": {
17 | "@repo/typescript-config": "workspace:^",
18 | "@repo/eslint-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.2.66",
21 | "@types/react-dom": "^18.2.22",
22 | "@typescript-eslint/eslint-plugin": "^7.2.0",
23 | "@typescript-eslint/parser": "^7.2.0",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.0",
27 | "eslint-plugin-react-refresh": "^0.4.6",
28 | "vite": "^4.0.0",
29 | "vite-plugin-csp-guard": "workspace:^"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/apps/vite4/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vite4/src/components/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/vite4/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { lazy, useState } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.css";
5 |
6 | const Home = lazy(() => import("./Home"));
7 |
8 | function App() {
9 | const [count, setCount] = useState(0);
10 |
11 | return (
12 | <>
13 |
21 | Vite + React
22 |
23 |
24 |
27 |
28 | Edit src/App.tsx
and save to test HMR
29 |
30 |
31 |
32 | Click on the Vite and React logos to learn more
33 |
34 | >
35 | );
36 | }
37 |
38 | export default App;
39 |
--------------------------------------------------------------------------------
/apps/vite4/src/components/Home.tsx:
--------------------------------------------------------------------------------
1 | import Injector from "./Injector";
2 |
3 | const Home = () => {
4 | return (
5 |
6 |
Home
7 |
8 |
9 | );
10 | };
11 |
12 | export default Home;
13 |
--------------------------------------------------------------------------------
/apps/vite4/src/components/Injector.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | const Injector = () => {
4 | const injectScript = (scriptContent: string) => {
5 | const script = document.createElement("script");
6 | script.textContent = scriptContent;
7 | script.async = true;
8 | document.body.appendChild(script);
9 | };
10 |
11 | useEffect(() => {
12 | const scriptContent = `
13 | // Your inline script code here
14 | console.log('Inline script executed');
15 | `;
16 | injectScript(scriptContent);
17 | }, []);
18 |
19 | return <>>;
20 | };
21 |
22 | export default Injector;
23 |
--------------------------------------------------------------------------------
/apps/vite4/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/vite4/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.tsx";
4 | import "./index.css";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/vite4/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/vite4/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, jQueryTest, inlineScriptBlockedTest, viteLogoTest} from '@repo/testing';
2 |
3 | const APP_TITLE = "Vite + React";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)"
5 | const BTN_COLOUR = "rgb(255, 0, 0)"
6 |
7 | genericTests(APP_TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | jQueryTest()
9 | inlineScriptBlockedTest(APP_TITLE)
10 | viteLogoTest()
11 | // cspGenerationTest()
12 |
--------------------------------------------------------------------------------
/apps/vite4/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }]
5 | }
6 |
--------------------------------------------------------------------------------
/apps/vite4/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/vite4/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react(),
9 | csp({
10 | algorithm: "sha256",
11 | dev: {
12 | run: true,
13 | },
14 | policy: {
15 | "font-src": ["https://fonts.gstatic.com"],
16 | "script-src-elem": ["'self'"],
17 | "connect-src": ["*"],
18 | "object-src": ["'none'"],
19 | },
20 | override: true,
21 | }) as PluginOption // Needed due to pnpm different dependency versions for Vite,
22 | ],
23 | preview: {
24 | port: 4011,
25 | },
26 | server: {
27 | port: 3011,
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/apps/vite5/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/vite5/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/vite5/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite5",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0"
15 | },
16 | "devDependencies": {
17 | "@repo/typescript-config": "workspace:^",
18 | "@repo/eslint-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.2.66",
21 | "@types/react-dom": "^18.2.22",
22 | "@typescript-eslint/eslint-plugin": "^7.2.0",
23 | "@typescript-eslint/parser": "^7.2.0",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.0",
27 | "eslint-plugin-react-refresh": "^0.4.6",
28 | "vite": "^5.3.1",
29 | "vite-plugin-csp-guard": "workspace:^"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/apps/vite5/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vite5/src/components/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/vite5/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { lazy, useState } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.css";
5 |
6 | const Home = lazy(() => import("./Home"));
7 |
8 | function App() {
9 | const [count, setCount] = useState(0);
10 |
11 | return (
12 | <>
13 |
21 | Vite + React
22 |
23 |
24 |
27 |
28 | Edit src/App.tsx
and save to test HMR
29 |
30 |
31 |
32 | Click on the Vite and React logos to learn more
33 |
34 | >
35 | );
36 | }
37 |
38 | export default App;
39 |
--------------------------------------------------------------------------------
/apps/vite5/src/components/Home.tsx:
--------------------------------------------------------------------------------
1 | import Injector from "./Injector";
2 |
3 | const Home = () => {
4 | return (
5 |
6 |
Home
7 |
8 |
9 | );
10 | };
11 |
12 | export default Home;
13 |
--------------------------------------------------------------------------------
/apps/vite5/src/components/Injector.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | const Injector = () => {
4 | const injectScript = (scriptContent: string) => {
5 | const script = document.createElement("script");
6 | script.textContent = scriptContent;
7 | script.async = true;
8 | document.body.appendChild(script);
9 | };
10 |
11 | useEffect(() => {
12 | const scriptContent = `
13 | // Your inline script code here
14 | console.log('Inline script executed');
15 | `;
16 | injectScript(scriptContent);
17 | }, []);
18 |
19 | return <>>;
20 | };
21 |
22 | export default Injector;
23 |
--------------------------------------------------------------------------------
/apps/vite5/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/vite5/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.tsx";
4 | import "./index.css";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/vite5/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/vite5/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, jQueryTest, inlineScriptBlockedTest, viteLogoTest } from '@repo/testing';
2 |
3 | const APP_TITLE = "Vite + React";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)"
5 | const BTN_COLOUR = "rgb(255, 0, 0)"
6 |
7 | genericTests(APP_TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | jQueryTest()
9 | inlineScriptBlockedTest(APP_TITLE)
10 | viteLogoTest()
11 |
--------------------------------------------------------------------------------
/apps/vite5/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }]
5 | }
6 |
--------------------------------------------------------------------------------
/apps/vite5/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/vite5/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react(),
9 | csp({
10 | algorithm: "sha256",
11 | dev: {
12 | run: true,
13 | },
14 | policy: {
15 | "font-src": ["https://fonts.gstatic.com"],
16 | "script-src-elem": ["'self'"],
17 | "connect-src": ["*"],
18 | "object-src": ["'none'"],
19 | },
20 | override: true,
21 | }) as PluginOption // Needed due to pnpm different dependency versions for Vite,
22 | ],
23 | preview: {
24 | port: 4012,
25 | },
26 | server: {
27 | port: 3012,
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/apps/vite6/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@repo/eslint-config/vite-react.js"],
4 | };
5 |
--------------------------------------------------------------------------------
/apps/vite6/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/vite6/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite6",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "tsc && eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0"
15 | },
16 | "devDependencies": {
17 | "@repo/typescript-config": "workspace:^",
18 | "@repo/eslint-config": "workspace:^",
19 | "@repo/testing": "workspace:^",
20 | "@types/react": "^18.2.66",
21 | "@types/react-dom": "^18.2.22",
22 | "@typescript-eslint/eslint-plugin": "^7.2.0",
23 | "@typescript-eslint/parser": "^7.2.0",
24 | "@vitejs/plugin-react": "^4.3.4",
25 | "eslint": "^8.57.0",
26 | "eslint-plugin-react-hooks": "^4.6.0",
27 | "eslint-plugin-react-refresh": "^0.4.6",
28 | "vite": "6.0.5",
29 | "vite-plugin-csp-guard": "workspace:^"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/apps/vite6/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vite6/src/components/App.css:
--------------------------------------------------------------------------------
1 | #root {
2 | max-width: 1280px;
3 | margin: 0 auto;
4 | padding: 2rem;
5 | text-align: center;
6 | }
7 |
8 | .logo {
9 | height: 6em;
10 | padding: 1.5em;
11 | will-change: filter;
12 | transition: filter 300ms;
13 | }
14 | .logo:hover {
15 | filter: drop-shadow(0 0 2em #646cffaa);
16 | }
17 | .logo.react:hover {
18 | filter: drop-shadow(0 0 2em #61dafbaa);
19 | }
20 |
21 | @keyframes logo-spin {
22 | from {
23 | transform: rotate(0deg);
24 | }
25 | to {
26 | transform: rotate(360deg);
27 | }
28 | }
29 |
30 | @media (prefers-reduced-motion: no-preference) {
31 | a:nth-of-type(2) .logo {
32 | animation: logo-spin infinite 20s linear;
33 | }
34 | }
35 |
36 | .card {
37 | padding: 2em;
38 | }
39 |
40 | .read-the-docs {
41 | color: #888;
42 | }
43 |
--------------------------------------------------------------------------------
/apps/vite6/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import { lazy, useState } from "react";
2 | import reactLogo from "../assets/react.svg";
3 | import viteLogo from "/vite.svg";
4 | import "./App.css";
5 |
6 | const Home = lazy(() => import("./Home"));
7 |
8 | function App() {
9 | const [count, setCount] = useState(0);
10 |
11 | return (
12 | <>
13 |
21 | Vite + React
22 |
23 |
24 |
27 |
28 | Edit src/App.tsx
and save to test HMR
29 |
30 |
31 |
32 | Click on the Vite and React logos to learn more
33 |
34 | >
35 | );
36 | }
37 |
38 | export default App;
39 |
--------------------------------------------------------------------------------
/apps/vite6/src/components/Home.tsx:
--------------------------------------------------------------------------------
1 | import Injector from "./Injector";
2 |
3 | const Home = () => {
4 | return (
5 |
6 |
Home
7 |
8 |
9 | );
10 | };
11 |
12 | export default Home;
13 |
--------------------------------------------------------------------------------
/apps/vite6/src/components/Injector.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | const Injector = () => {
4 | const injectScript = (scriptContent: string) => {
5 | const script = document.createElement("script");
6 | script.textContent = scriptContent;
7 | script.async = true;
8 | document.body.appendChild(script);
9 | };
10 |
11 | useEffect(() => {
12 | const scriptContent = `
13 | // Your inline script code here
14 | console.log('Inline script executed');
15 | `;
16 | injectScript(scriptContent);
17 | }, []);
18 |
19 | return <>>;
20 | };
21 |
22 | export default Injector;
23 |
--------------------------------------------------------------------------------
/apps/vite6/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | @media (prefers-color-scheme: light) {
58 | :root {
59 | color: #213547;
60 | background-color: #ffffff;
61 | }
62 | a:hover {
63 | color: #747bff;
64 | }
65 | button {
66 | background-color: #f9f9f9;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/apps/vite6/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./components/App.tsx";
4 | import "./index.css";
5 |
6 | ReactDOM.createRoot(document.getElementById("root")!).render(
7 |
8 |
9 |
10 | );
11 |
--------------------------------------------------------------------------------
/apps/vite6/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/vite6/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, jQueryTest, inlineScriptBlockedTest, viteLogoTest } from '@repo/testing';
2 |
3 | const APP_TITLE = "Vite + React";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)"
5 | const BTN_COLOUR = "rgb(255, 0, 0)"
6 |
7 | genericTests(APP_TITLE, {headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR})
8 | jQueryTest()
9 | inlineScriptBlockedTest(APP_TITLE)
10 | viteLogoTest()
11 |
--------------------------------------------------------------------------------
/apps/vite6/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite",
3 | "include": ["src"],
4 | "references": [{ "path": "./tsconfig.node.json" }]
5 | }
6 |
--------------------------------------------------------------------------------
/apps/vite6/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "@repo/typescript-config/node",
4 | "compilerOptions": {
5 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/vite6/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import react from "@vitejs/plugin-react";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react(),
9 | csp({
10 | algorithm: "sha256",
11 | dev: {
12 | run: true,
13 | },
14 | policy: {
15 | "font-src": ["'self'","https://fonts.gstatic.com"],
16 | "script-src-elem": ["'self'"],
17 | "connect-src": ["*"],
18 | "object-src": ["'none'"],
19 | "img-src": ["'self'","https://placehold.co/600x400", "data:"],
20 | },
21 | override: true
22 | }) as PluginOption // Needed due to pnpm different dependency versions for Vite,
23 | ],
24 | preview: {
25 | port: 4013,
26 | },
27 | server: {
28 | port: 3013,
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/apps/vue-app/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar"]
3 | }
4 |
--------------------------------------------------------------------------------
/apps/vue-app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Vue
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/vue-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vue-tsc -b && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "vue": "^3.4.31"
13 | },
14 | "devDependencies": {
15 | "@repo/eslint-config": "workspace:^",
16 | "@repo/testing": "workspace:^",
17 | "@vitejs/plugin-vue": "^5.2.1",
18 | "vue-tsc": "^2.0.24",
19 | "vite-plugin-csp-guard": "workspace:^"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/apps/vue-app/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vue-app/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
31 |
--------------------------------------------------------------------------------
/apps/vue-app/src/assets/vue.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vue-app/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | {{ msg }}
11 |
12 |
13 |
14 |
15 | Edit
16 | components/HelloWorld.vue
to test HMR
17 |
18 |
19 |
20 |
21 | Check out
22 | create-vue, the official Vue + Vite starter
25 |
26 |
27 | Learn more about IDE Support for Vue in the
28 | Vue Docs Scaling up Guide.
33 |
34 | Click on the Vite and Vue logos to learn more
35 |
36 |
37 |
51 |
--------------------------------------------------------------------------------
/apps/vue-app/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import './style.css'
3 | import App from './App.vue'
4 |
5 | createApp(App).mount('#app')
6 |
--------------------------------------------------------------------------------
/apps/vue-app/src/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | a {
17 | font-weight: 500;
18 | color: #646cff;
19 | text-decoration: inherit;
20 | }
21 | a:hover {
22 | color: #535bf2;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | display: flex;
28 | place-items: center;
29 | min-width: 320px;
30 | min-height: 100vh;
31 | }
32 |
33 | h1 {
34 | font-size: 3.2em;
35 | line-height: 1.1;
36 | }
37 |
38 | button {
39 | border-radius: 8px;
40 | border: 1px solid transparent;
41 | padding: 0.6em 1.2em;
42 | font-size: 1em;
43 | font-weight: 500;
44 | font-family: inherit;
45 | background-color: #1a1a1a;
46 | cursor: pointer;
47 | transition: border-color 0.25s;
48 | }
49 | button:hover {
50 | border-color: #646cff;
51 | }
52 | button:focus,
53 | button:focus-visible {
54 | outline: 4px auto -webkit-focus-ring-color;
55 | }
56 |
57 | .card {
58 | padding: 2em;
59 | }
60 |
61 | #app {
62 | max-width: 1280px;
63 | margin: 0 auto;
64 | padding: 2rem;
65 | text-align: center;
66 | }
67 |
68 | @media (prefers-color-scheme: light) {
69 | :root {
70 | color: #213547;
71 | background-color: #ffffff;
72 | }
73 | a:hover {
74 | color: #747bff;
75 | }
76 | button {
77 | background-color: #f9f9f9;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/apps/vue-app/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/vue-app/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest, } from '@repo/testing';
2 |
3 | const TITLE = "Vite + Vue";
4 |
5 | const BTN_COLOUR = "rgb(66, 184, 131)"
6 | const HEADER_COLOR = "rgb(33, 53, 71)"
7 |
8 | genericTests(TITLE, {headerColour: HEADER_COLOR, buttonColour: BTN_COLOUR})
9 | viteLogoTest()
--------------------------------------------------------------------------------
/apps/vue-app/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/vue-app/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 | "target": "ES2020",
6 | "useDefineForClassFields": true,
7 | "module": "ESNext",
8 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
9 | "skipLibCheck": true,
10 |
11 | /* Bundler mode */
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "moduleDetection": "force",
17 | "noEmit": true,
18 | "jsx": "preserve",
19 |
20 | /* Linting */
21 | "strict": true,
22 | "noUnusedLocals": true,
23 | "noUnusedParameters": true,
24 | "noFallthroughCasesInSwitch": true
25 | },
26 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
27 | }
28 |
--------------------------------------------------------------------------------
/apps/vue-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | {
5 | "path": "./tsconfig.app.json"
6 | },
7 | {
8 | "path": "./tsconfig.node.json"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/apps/vue-app/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "noEmit": true
11 | },
12 | "include": ["vite.config.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/vue-app/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import vue from "@vitejs/plugin-vue";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | vue() as PluginOption,
9 | csp({
10 | dev: { run: true, outlierSupport: ["vue"] },
11 | build: { sri: true },
12 | }),
13 | ],
14 | preview: {
15 | port: 4007,
16 | },
17 | server: {
18 | port: 3007,
19 | },
20 | });
21 |
--------------------------------------------------------------------------------
/apps/vue-router/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar"]
3 | }
4 |
--------------------------------------------------------------------------------
/apps/vue-router/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Vue
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/vue-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-router",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vue-tsc -b && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "vue": "^3.5.13",
13 | "vue-router": "^4.5.0"
14 | },
15 | "devDependencies": {
16 | "@repo/eslint-config": "workspace:*",
17 | "@repo/typescript-config": "workspace:*",
18 | "@repo/testing": "workspace:*",
19 | "@vitejs/plugin-vue": "^5.2.1",
20 | "@vue/tsconfig": "^0.7.0",
21 | "typescript": "~5.7.2",
22 | "vite": "^6.2.0",
23 | "vite-plugin-csp-guard": "workspace:*",
24 | "vue-tsc": "^2.2.4"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/apps/vue-router/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vue-router/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
31 |
--------------------------------------------------------------------------------
/apps/vue-router/src/Bye.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
31 |
--------------------------------------------------------------------------------
/apps/vue-router/src/Four.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
31 |
--------------------------------------------------------------------------------
/apps/vue-router/src/Hello.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
31 |
--------------------------------------------------------------------------------
/apps/vue-router/src/assets/vue.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/vue-router/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | {{ msg }}
11 |
12 |
13 |
14 |
15 | Edit
16 | components/HelloWorld.vue
to test HMR
17 |
18 |
19 |
20 |
21 | Check out
22 | create-vue, the official Vue + Vite starter
25 |
26 |
27 | Learn more about IDE Support for Vue in the
28 | Vue Docs Scaling up Guide.
33 |
34 | Click on the Vite and Vue logos to learn more
35 |
36 |
37 |
42 |
--------------------------------------------------------------------------------
/apps/vue-router/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import "./style.css";
3 | import App from "./App.vue";
4 | import router from "./router";
5 |
6 | createApp(App).use(router).mount("#app");
7 |
--------------------------------------------------------------------------------
/apps/vue-router/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from "vue-router";
2 |
3 | const router = createRouter({
4 | history: createWebHistory(),
5 | routes: [
6 | {
7 | path: "/",
8 | name: "root",
9 | component: () => import("../App.vue"),
10 | },
11 | {
12 | path: "/hello",
13 | name: "hello",
14 | component: () => import("../Hello.vue"),
15 | },
16 | {
17 | path: "/bye",
18 | name: "bye",
19 | component: () => import("../Bye.vue"),
20 | },
21 | {
22 | path: "/four",
23 | name: "four",
24 | component: () => import("../Four.vue"),
25 | },
26 | ],
27 | });
28 |
29 | export default router;
30 |
--------------------------------------------------------------------------------
/apps/vue-router/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/apps/vue-router/tests/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { genericTests, viteLogoTest } from "@repo/testing";
2 |
3 | const TITLE = "Vite + Vue";
4 | const HEADER_COLOUR = "rgb(33, 53, 71)";
5 | const BTN_COLOUR = "rgb(249, 249, 249)";
6 |
7 | genericTests(TITLE, { headerColour: HEADER_COLOUR, buttonColour: BTN_COLOUR });
8 | viteLogoTest();
9 |
--------------------------------------------------------------------------------
/apps/vue-router/tests/preview-only/main.spec.ts:
--------------------------------------------------------------------------------
1 | import { sriTest } from '@repo/testing';
2 |
3 | sriTest();
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apps/vue-router/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@vue/tsconfig/tsconfig.dom.json",
3 | "compilerOptions": {
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 |
6 | /* Linting */
7 | "strict": true,
8 | "noUnusedLocals": true,
9 | "noUnusedParameters": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "noUncheckedSideEffectImports": true
12 | },
13 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
14 | }
15 |
--------------------------------------------------------------------------------
/apps/vue-router/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/vite.json",
3 | "include": [
4 | "src"
5 | ],
6 | "exclude": [
7 | "node_modules"
8 | ],
9 | "compilerOptions": {
10 | "baseUrl": "."
11 | }
12 | }
--------------------------------------------------------------------------------
/apps/vue-router/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4 | "target": "ES2022",
5 | "lib": ["ES2023"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 |
16 | /* Linting */
17 | "strict": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": true,
20 | "noFallthroughCasesInSwitch": true,
21 | "noUncheckedSideEffectImports": true
22 | },
23 | "include": ["vite.config.ts"]
24 | }
25 |
--------------------------------------------------------------------------------
/apps/vue-router/tsconfig.tsbuildinfo:
--------------------------------------------------------------------------------
1 | {"root":["./src/app.vue","./src/bye.vue","./src/four.vue","./src/hello.vue","./src/main.ts","./src/vite-env.d.ts","./src/components/helloworld.vue","./src/router/index.ts"],"version":"5.7.3"}
--------------------------------------------------------------------------------
/apps/vue-router/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig, PluginOption } from "vite";
2 | import vue from "@vitejs/plugin-vue";
3 | import csp from "vite-plugin-csp-guard";
4 |
5 | // https://vite.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | vue(),
9 | csp({
10 | policy: {
11 | "img-src": ["'self'", "data:"],
12 | },
13 | build: {
14 | sri: true,
15 | outlierSupport: ["vue-router"],
16 | },
17 | debug: true,
18 | }) as PluginOption,
19 | ],
20 | preview: {
21 | port: 4020,
22 | },
23 | server: {
24 | port: 3020,
25 | },
26 | });
27 |
--------------------------------------------------------------------------------
/packages/eslint-config/library.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require("node:path");
2 |
3 | const project = resolve(process.cwd(), "tsconfig.json");
4 |
5 | /** @type {import("eslint").Linter.Config} */
6 | module.exports = {
7 | extends: ["eslint:recommended", "prettier", "eslint-config-turbo"],
8 | plugins: ["only-warn"],
9 | globals: {
10 | React: true,
11 | JSX: true,
12 | },
13 | env: {
14 | node: true,
15 | },
16 | settings: {
17 | "import/resolver": {
18 | typescript: {
19 | project,
20 | },
21 | },
22 | },
23 | ignorePatterns: [
24 | // Ignore dotfiles
25 | ".*.js",
26 | "node_modules/",
27 | "dist/",
28 | ],
29 | overrides: [
30 | {
31 | files: ["*.js?(x)", "*.ts?(x)"],
32 | },
33 | ],
34 | };
35 |
--------------------------------------------------------------------------------
/packages/eslint-config/next.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require("node:path");
2 |
3 | const project = resolve(process.cwd(), "tsconfig.json");
4 |
5 | /** @type {import("eslint").Linter.Config} */
6 | module.exports = {
7 | extends: [
8 | "eslint:recommended",
9 | "prettier",
10 | require.resolve("@vercel/style-guide/eslint/next"),
11 | "eslint-config-turbo",
12 | ],
13 | globals: {
14 | React: true,
15 | JSX: true,
16 | },
17 | env: {
18 | node: true,
19 | browser: true,
20 | },
21 | plugins: ["only-warn"],
22 | settings: {
23 | "import/resolver": {
24 | typescript: {
25 | project,
26 | },
27 | },
28 | },
29 | ignorePatterns: [
30 | // Ignore dotfiles
31 | ".*.js",
32 | "node_modules/",
33 | ],
34 | overrides: [{ files: ["*.js?(x)", "*.ts?(x)"] }],
35 | };
36 |
--------------------------------------------------------------------------------
/packages/eslint-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/eslint-config",
3 | "version": "0.0.0",
4 | "private": true,
5 | "files": [
6 | "library.js",
7 | "next.js",
8 | "react-internal.js"
9 | ],
10 | "devDependencies": {
11 | "@typescript-eslint/eslint-plugin": "^6.17.0",
12 | "@typescript-eslint/parser": "^6.17.0",
13 | "@vercel/style-guide": "^5.1.0",
14 | "eslint-config-prettier": "^9.1.0",
15 | "eslint-config-turbo": "^2.3.3",
16 | "eslint-plugin-only-warn": "^1.1.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/eslint-config/vite-react.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require("node:path");
2 |
3 | const project = resolve(process.cwd(), "tsconfig.json");
4 |
5 | /** @type {import("eslint").Linter.Config} */
6 | module.exports = {
7 | env: { browser: true, es2020: true },
8 | extends: [
9 | "eslint:recommended",
10 | "plugin:@typescript-eslint/recommended",
11 | "plugin:react-hooks/recommended",
12 | ],
13 | ignorePatterns: ["dist", ".eslintrc.cjs"],
14 | parser: "@typescript-eslint/parser",
15 | plugins: ["react-refresh"],
16 | rules: {
17 | "react-refresh/only-export-components": [
18 | "warn",
19 | { allowConstantExport: true },
20 | ],
21 | },
22 | settings: {
23 | "import/resolver": {
24 | typescript: {
25 | project,
26 | },
27 | },
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/packages/testing/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/testing",
3 | "version": "0.0.0",
4 | "private": true,
5 | "license": "MIT",
6 | "type": "module",
7 | "scripts": {
8 | "build": "rollup -c"
9 | },
10 | "exports": {
11 | ".": {
12 | "types": "./dist/index.d.ts",
13 | "import": "./dist/index.js"
14 | }
15 | },
16 | "dependencies": {
17 | "csp-toolkit": "1.3.1"
18 | },
19 | "devDependencies": {
20 | "@rollup/plugin-node-resolve": "^15.2.3",
21 | "@rollup/plugin-typescript": "^12.1.2",
22 | "rollup": "^4.28.1",
23 | "@repo/typescript-config": "workspace:^"
24 | }
25 | }
--------------------------------------------------------------------------------
/packages/testing/rollup.config.mjs:
--------------------------------------------------------------------------------
1 | import typescript from '@rollup/plugin-typescript';
2 | import { nodeResolve } from '@rollup/plugin-node-resolve';
3 |
4 | export default {
5 | input: 'src/index.ts', // Assuming your main entry is index.ts
6 | output: [
7 | {
8 | file: 'dist/index.js',
9 | format: 'esm', // Can be 'cjs' or 'esm' depending on your requirements
10 | sourcemap: true,
11 | },
12 | ],
13 | plugins: [
14 | nodeResolve(),
15 | typescript(
16 | {
17 | tsconfig: "tsconfig.json",
18 | declaration: true,
19 | declarationDir: "dist",
20 | include: ["src/**/*.ts"],
21 | sourceMap: true,
22 | }
23 | ),
24 | ],
25 | external: [
26 | 'react',
27 | 'vite',
28 | "@playwright/test",
29 | ],
30 | };
--------------------------------------------------------------------------------
/packages/testing/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/base.json",
3 | "compilerOptions": {
4 | "jsx": "react-jsx",
5 | "module": "ESNext",
6 | "target": "esnext",
7 | "moduleResolution": "Bundler",
8 | "strict": true,
9 | "noUnusedLocals": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "noImplicitAny": true,
13 | "lib": ["dom", "esnext"],
14 | "types": ["node"],
15 | "noEmitOnError": true,
16 | },
17 | "include": ["src/**/*"],
18 | }
19 |
--------------------------------------------------------------------------------
/packages/typescript-config/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Default",
4 | "compilerOptions": {
5 | "declaration": true,
6 | "declarationMap": true,
7 | "esModuleInterop": true,
8 | "incremental": false,
9 | "isolatedModules": true,
10 | "lib": ["es2022", "DOM", "DOM.Iterable"],
11 | "module": "NodeNext",
12 | "moduleDetection": "force",
13 | "moduleResolution": "NodeNext",
14 | "noUncheckedIndexedAccess": true,
15 | "resolveJsonModule": true,
16 | "skipLibCheck": true,
17 | "strict": true,
18 | "target": "ES2022"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/typescript-config/nextjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Next.js",
4 | "extends": "./base.json",
5 | "compilerOptions": {
6 | "plugins": [{ "name": "next" }],
7 | "module": "ESNext",
8 | "moduleResolution": "Bundler",
9 | "allowJs": true,
10 | "jsx": "preserve",
11 | "noEmit": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/typescript-config/node.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "composite": true,
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "noEmit": false,
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/typescript-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@repo/typescript-config",
3 | "version": "0.0.0",
4 | "private": true,
5 | "license": "MIT",
6 | "publishConfig": {
7 | "access": "public"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/typescript-config/vite.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "React Library",
4 | "compilerOptions": {
5 | "jsx": "react-jsx",
6 | "moduleResolution": "bundler",
7 | "allowImportingTsExtensions": true,
8 | "resolveJsonModule": true,
9 | "isolatedModules": true,
10 | "noEmit": true,
11 | "strict": true,
12 | "noUnusedLocals": true,
13 | "noUnusedParameters": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "target": "ES2020",
16 | "useDefineForClassFields": true,
17 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
18 | "module": "ESNext",
19 | "skipLibCheck": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/rollup.config.mjs:
--------------------------------------------------------------------------------
1 | import resolve from "@rollup/plugin-node-resolve";
2 | import commonjs from "@rollup/plugin-commonjs";
3 | import typescript from "@rollup/plugin-typescript";
4 | import { defineConfig } from "rollup";
5 | import terser from "@rollup/plugin-terser";
6 |
7 | export default defineConfig(
8 | [
9 | {
10 | input: "src/index.ts", // Main plugin entry point
11 | output: [
12 | {
13 | file: "dist/index.esm.js",
14 | format: "esm",
15 | sourcemap: true, // Enable sourcemaps for debugging
16 | },
17 | {
18 | file: "dist/index.cjs.js",
19 | format: "cjs",
20 | sourcemap: true,
21 | },
22 | ],
23 | external: ["lightningcss", "fsevents", "vite", "cheerio"],
24 | plugins: [
25 | typescript({
26 | tsconfig: "tsconfig.json",
27 | declaration: true,
28 | declarationDir: "dist",
29 | include: ["src/**/*.ts"],
30 | exclude: ["src/server/**/*.ts"],
31 | sourceMap: true,
32 | }),
33 | resolve(),
34 | commonjs(),
35 | terser(),
36 | ],
37 | }
38 | ]
39 | );
40 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/src/constants.ts:
--------------------------------------------------------------------------------
1 | export const FEATURE_FLAGS = {
2 | mpa: false,
3 | cssInJs: false,
4 | };
5 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/src/css/extraction.ts:
--------------------------------------------------------------------------------
1 | const cssParser = (unparsed: string) => {
2 | // Step 1: Remove the enclosing double quotes
3 | let convertedCss = unparsed.slice(1, -1);
4 |
5 | // This was found to be an issue with classnames that have a \ in them, tailwind uses this.
6 | // Adjusted Step: Directly replace double backslashes before a colon with a single backslash.
7 | convertedCss = convertedCss.replace(/\\\\:/g, "\\:");
8 |
9 | // Step 2: Replace \n with actual newlines
10 | convertedCss = convertedCss.replace(/\\n/g, "\n");
11 |
12 | // Step 3: Unescape double quotes (if any)
13 | convertedCss = convertedCss.replace(/\\"/g, '"');
14 |
15 | return convertedCss;
16 | };
17 |
18 | const extractCSSFromVariable = (code: string) => {
19 | // Step 2: Use regex to find and extract the CSS content
20 | const regex =
21 | /const __vite__css\s*=\s*([\s\S]*?)(?=\s*__vite__updateStyle\(__vite__id,\s*__vite__css\))/;
22 | const match = code.match(regex);
23 | if (match && match[1]) {
24 | let cssContent = match[1];
25 | return cssContent;
26 | } else {
27 | // Return an empty string if the variable or its content is not found
28 | return "";
29 | }
30 | };
31 |
32 | export const getCSS = (code: string): string => {
33 | // Step 1: Extract the CSS content from the code
34 | const cssContent = extractCSSFromVariable(code);
35 |
36 | // Step 2: Parse the CSS content
37 | const parsedCss = cssParser(cssContent);
38 |
39 | return parsedCss;
40 | };
41 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/src/policy/constants.ts:
--------------------------------------------------------------------------------
1 | import { CSPPolicy } from "csp-toolkit";
2 |
3 | export const DEFAULT_DEV_POLICY: CSPPolicy = {
4 | "default-src": ["'self'"],
5 | "img-src": ["'self'", "data:"],
6 | "script-src-elem": ["'self'"],
7 | "style-src-elem": ["'self'"],
8 | };
9 |
10 | export const DEFAULT_POLICY: CSPPolicy = {
11 | "default-src": ["'self'"],
12 | "img-src": ["'self'"],
13 | "script-src-elem": ["'self'"],
14 | "style-src-elem": ["'self'"],
15 | };
16 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/src/policy/createPolicy.ts:
--------------------------------------------------------------------------------
1 | import { HtmlTagDescriptor } from "vite";
2 | import { HashCollection } from "../types";
3 | import { policyToString, CSPPolicy} from "csp-toolkit";
4 |
5 | type GeneratePolicyProps = {
6 | policy: CSPPolicy;
7 | collection: HashCollection;
8 | };
9 | export const generatePolicyString = ({
10 | collection,
11 | policy,
12 | }: GeneratePolicyProps) => {
13 | const finalPolicy = { ...policy };
14 |
15 | // Generate the final policy
16 | for (const [key, value] of Object.entries(collection)) {
17 | const currentMap = value;
18 | const currentPolicy = finalPolicy[key as keyof CSPPolicy] ?? [];
19 |
20 | if (currentPolicy.includes("'unsafe-inline'")) {
21 | // If we have unsafe-inline, we should not add any hashes because this will override the unsafe-inline
22 | continue;
23 | }
24 |
25 | if (currentMap.size > 0) {
26 | finalPolicy[key as keyof CSPPolicy] = [
27 | ...currentPolicy,
28 | ...Array.from(currentMap.keys()),
29 | ];
30 | }
31 | }
32 | // Create the policy string
33 | const policyString = policyToString(finalPolicy);
34 |
35 | return policyString;
36 | };
37 |
38 | export const policyToTag = (policy: string): HtmlTagDescriptor[] => {
39 | return [
40 | {
41 | tag: "meta",
42 | attrs: {
43 | "http-equiv": "Content-Security-Policy",
44 | content: policy,
45 | },
46 | injectTo: "head-prepend",
47 | },
48 | ];
49 | };
50 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/src/transform/constants.ts:
--------------------------------------------------------------------------------
1 | import { BuildOutlier, DevOptions, DevOutlier } from "../types";
2 |
3 | export const REQUIRE_POST_TRANSFORM: Array = [
4 | "tailwind",
5 | "sass",
6 | "less",
7 | "stylus",
8 | "vue",
9 | ];
10 |
11 | export const REQUIRE_STRONGER_LAZY_LOADING: Array = [
12 | "vue-router",
13 | ];
14 |
15 | export const DEFAULT_DEV_OPTIONS: DevOptions = {
16 | run: false,
17 | outlierSupport: [],
18 | };
19 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/tests/extraction.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, test } from "vitest";
2 | import {
3 | EDGE_CASE_APP_CSS,
4 | EDGE_CASE_INDEX_CSS,
5 | EDGE_CASE_TAILWIND,
6 | } from "../mocks/post";
7 | import { getCSS } from "../src/css/extraction";
8 | import { EDGE_CASE_INDEX, EDGE_CASE_APP, TAILWIND_CSS } from "../mocks/css";
9 |
10 | describe("Extracting CSS", () => {
11 | test("Extract CSS from Post Code Bundle", () => {
12 | const cssIndex = getCSS(EDGE_CASE_INDEX_CSS);
13 | const cssApp = getCSS(EDGE_CASE_APP_CSS);
14 | expect(cssIndex).toEqual(EDGE_CASE_INDEX);
15 | expect(cssApp).toEqual(EDGE_CASE_APP);
16 | });
17 |
18 | test("Extract Tailwind CSS from Post Code Bundle", () => {
19 | const css = getCSS(EDGE_CASE_TAILWIND);
20 | expect(css).toEqual(TAILWIND_CSS);
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/packages/vite-plugin-csp-guard/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@repo/typescript-config/base.json",
3 | "compilerOptions": {
4 | "jsx": "react-jsx",
5 | "module": "ESNext",
6 | "target": "esnext",
7 | "moduleResolution": "Bundler",
8 | "strict": true,
9 | "noUnusedLocals": true,
10 | "resolveJsonModule": true,
11 | "esModuleInterop": true,
12 | "noImplicitAny": true,
13 | "lib": ["dom", "esnext"],
14 | "types": ["node"],
15 | "noEmitOnError": true,
16 | },
17 | "include": ["src/**/*", "tests/**/*", "mocks/**/*"],
18 | }
19 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/*'
3 | - 'apps/*'
--------------------------------------------------------------------------------
/scripts/cleanup-modules.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Find all directories containing node_modules and remove them
4 | find . -type d -name "node_modules" -exec rm -rf {} +
5 |
6 | echo "node_modules directories have been removed from all apps and packages."
--------------------------------------------------------------------------------
/scripts/get-package-path.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Check if the package name is passed as an argument
4 | if [ -z "$1" ]; then
5 | echo "Error: Package name is required as an argument."
6 | exit 1
7 | fi
8 |
9 | PACKAGE_NAME=$1
10 |
11 | # Use pnpm list with depth -1 and output JSON
12 | PACKAGE_PATH=$(pnpm list --depth=-1 --json -r | jq -r --arg PACKAGE_NAME "$PACKAGE_NAME" '.[] | select(.name == $PACKAGE_NAME) | .path')
13 |
14 | # Check if the package was found
15 | if [ -z "$PACKAGE_PATH" ]; then
16 | echo "Error: Package '$PACKAGE_NAME' not found."
17 | exit 1
18 | fi
19 |
20 | # Output the path to the package
21 | echo "$PACKAGE_PATH"
--------------------------------------------------------------------------------
/scripts/hash-file-content.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const crypto = require("crypto");
3 | const process = require("process");
4 |
5 | const generateHashFromFile = (filePath, algorithm = "sha256") => {
6 | try {
7 | const fileContent = fs.readFileSync(filePath, { encoding: "utf-8" });
8 | const hash = crypto.createHash(algorithm);
9 | hash.update(fileContent);
10 | return hash.digest("base64");
11 | } catch (error) {
12 | console.error(`Error reading or hashing file: ${error.message}`);
13 | process.exit(1);
14 | }
15 | };
16 |
17 | // Check if a file path is provided
18 | if (process.argv.length < 3) {
19 | console.log("Usage: node hash-file-content.js ");
20 | process.exit(1);
21 | }
22 |
23 | const filePath = process.argv[2];
24 | const hashResult = generateHashFromFile(filePath);
25 | console.log(`Hash for '${filePath}': ${hashResult}`);
26 |
--------------------------------------------------------------------------------
/scripts/hash-file-content.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Check if a file path is provided as an argument
4 | if [ "$#" -ne 1 ]; then
5 | echo "Usage: $0 "
6 | exit 1
7 | fi
8 |
9 | file_path="$1"
10 |
11 | # Check if the file exists
12 | if [ ! -f "$file_path" ]; then
13 | echo "Error: File does not exist."
14 | exit 1
15 | fi
16 |
17 | # Generate SHA-256 hash of the file content in binary format and then base64 encode it
18 | openssl dgst -sha256 -binary "$file_path" | base64
--------------------------------------------------------------------------------
/scripts/packages-to-release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Disallowed packages (packages to ignore for publishing)
4 | DISALLOWED_PACKAGES=("@repo/eslint-config" "@repo/testing" "@repo/typescript-config")
5 |
6 | # Get changed packages using Turbo
7 | CHANGED_PACKAGES=$(pnpm exec turbo build \
8 | --filter="./packages/*" \
9 | --filter='!./apps/*' \
10 | --filter='[HEAD^1]' \
11 | --dry-run=json | jq -r '.packages[]' | sed 's|^//||')
12 |
13 | # Filter out disallowed packages
14 | ALLOWED_CHANGED_PACKAGES=()
15 | for package in $CHANGED_PACKAGES; do
16 | if [[ ! " ${DISALLOWED_PACKAGES[*]} " == *" $package "* ]]; then
17 | ALLOWED_CHANGED_PACKAGES+=("$package")
18 | fi
19 | done
20 |
21 | # Join the array into a space-separated string, then use jq to create a JSON array
22 | echo "${ALLOWED_CHANGED_PACKAGES[@]}" | jq -R 'split(" ") | map(select(length > 0)) | @json' | jq -r .
--------------------------------------------------------------------------------
/scripts/version-has-changed.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Inputs
4 | from=$1
5 | to=$2
6 | packages_input=$3
7 |
8 | # Parse the input string into a JSON array using jq
9 | # The input should already be a valid JSON string representing an array
10 | packages=$(echo "$packages_input" | jq -r '.[]')
11 |
12 | # Filter changed packages
13 | changed_packages=()
14 |
15 | for package in $packages; do
16 | # Get the package path using pnpm
17 | PACKAGE_PATH=$(pnpm list --depth=-1 --json -r | jq -r --arg PACKAGE_NAME "$package" '.[] | select(.name == $PACKAGE_NAME) | .path')
18 |
19 | # Check if the path exists
20 | if [[ -d "$PACKAGE_PATH" ]]; then
21 | # Check for version changes in the package.json
22 | diff_output=$(git diff "$from".."$to" -- "$PACKAGE_PATH/package.json" || true)
23 |
24 | # Check if the diff contains a version change
25 | if [[ $diff_output == *"\"version\":"* ]]; then
26 | changed_packages+=("$package")
27 | fi
28 | fi
29 | done
30 |
31 | # Output the changed packages as a JSON array
32 | echo "${changed_packages[@]}" | jq -R 'split(" ") | map(select(length > 0)) | @json' | jq -r .
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "globalDependencies": ["**/.env.*local"],
4 | "tasks": {
5 | "build": {
6 | "dependsOn": ["^build"],
7 | "outputs": [".next/**", "!.next/cache/**", "dist/**", "build/**"]
8 | },
9 | "lint": {
10 | "dependsOn": ["^lint"]
11 | },
12 | "test": {
13 | "dependsOn": ["^build"]
14 | },
15 | "test:ui": {
16 | "dependsOn": ["^build"]
17 | },
18 | "dev": {
19 | "cache": false,
20 | "persistent": true,
21 | "dependsOn": ["^build"]
22 | },
23 | "preview": {
24 | "dependsOn": ["^build", "build"],
25 | "persistent": true
26 | }
27 | },
28 | "ui": "stream"
29 | }
30 |
--------------------------------------------------------------------------------