├── src ├── background.ts ├── content_script.tsx ├── index.css ├── options.tsx └── popup.tsx ├── .gitignore ├── postcss.config.js ├── public ├── icon.png ├── options.html ├── popup.html └── manifest.json ├── jest.config.js ├── webpack ├── webpack.prod.js ├── webpack.dev.js └── webpack.common.js ├── tailwind.config.js ├── tsconfig.json ├── README.md ├── LICENSE └── package.json /src/background.ts: -------------------------------------------------------------------------------- 1 | // Background Script -------------------------------------------------------------------------------- /src/content_script.tsx: -------------------------------------------------------------------------------- 1 | // Content Script 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules/ 3 | dist/ 4 | tmp/ 5 | yarn.lock 6 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sumansid/Chrome-Extension-Starter-React-Typescript-Tailwind/HEAD/public/icon.png -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "roots": [ 3 | "src" 4 | ], 5 | "transform": { 6 | "^.+\\.ts$": "ts-jest" 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /webpack/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | 4 | module.exports = merge(common, { 5 | mode: 'production' 6 | }); -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,tsx, ts}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /webpack/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | 4 | module.exports = merge(common, { 5 | devtool: 'inline-source-map', 6 | mode: 'development' 7 | }); -------------------------------------------------------------------------------- /public/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My Test Extension Options 5 | 6 | 7 | 8 | 9 |

this is the options page

10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /public/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Getting Started Extension's Popup 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/options.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | 5 | const Options = () => { 6 | return
Options page
; 7 | }; 8 | 9 | ReactDOM.render( 10 | 11 | 12 | , 13 | document.getElementById("root") 14 | ); 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "module": "commonjs", 5 | "target": "es6", 6 | "esModuleInterop": true, 7 | "sourceMap": false, 8 | "rootDir": "src", 9 | "outDir": "dist/js", 10 | "noEmitOnError": true, 11 | "jsx": "react", 12 | "typeRoots": [ "node_modules/@types" ] 13 | } 14 | } -------------------------------------------------------------------------------- /src/popup.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | 5 | const Popup = () => { 6 | return ( 7 | <> 8 |
9 |
10 | React, Typescript, Tailwind Starter Code 11 |
12 |
13 | 14 | ); 15 | }; 16 | 17 | ReactDOM.render( 18 | 19 | 20 | , 21 | document.getElementById("root") 22 | ); 23 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | 4 | "name": "Chrome Extension TypeScript Starter", 5 | "description": "Chrome Extension, TypeScript, Visual Studio Code", 6 | "version": "1.0", 7 | 8 | "options_ui": { 9 | "page": "options.html" 10 | }, 11 | 12 | "action": { 13 | "default_icon": "icon.png", 14 | "default_popup": "popup.html" 15 | }, 16 | 17 | "content_scripts": [ 18 | { 19 | "matches": [""], 20 | "js": ["js/vendor.js", "js/content_script.js"] 21 | } 22 | ], 23 | 24 | "background": { 25 | "service_worker": "js/background.js" 26 | }, 27 | 28 | "permissions": [ 29 | "storage" 30 | ], 31 | 32 | "host_permissions": [ 33 | "" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # create-t3-extension 2 | 3 | Chrome Extension: React + TypeScript + TailWind CSS 4 | 5 | ## Prerequisites 6 | 7 | - [node + npm](https://nodejs.org/) (Current Version) 8 | 9 | ## Includes the following 10 | 11 | - TypeScript 12 | - Webpack 13 | - React 14 | - Tailwind CSS 15 | - Jest 16 | 17 | ## Project Structure 18 | 19 | - src/typescript: TypeScript source files 20 | - src/assets: static files 21 | - dist: Chrome Extension directory 22 | - dist/js: Generated JavaScript files 23 | 24 | ## Setup 25 | 26 | ``` 27 | npm install 28 | ``` 29 | 30 | ## Build 31 | 32 | ``` 33 | npm run build 34 | ``` 35 | 36 | ## Build in watch mode 37 | 38 | ``` 39 | npm run watch 40 | ``` 41 | 42 | ## References 43 | [https://github.com/chibat/chrome-extension-typescript-starter](https://github.com/chibat/chrome-extension-typescript-starter) 44 | 45 | [https://github.com/t3-oss/create-t3-app](https://github.com/t3-oss/create-t3-app) 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tomofumi Chiba 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chrome-extension-react-typescript-tailwind-starter", 3 | "version": "1.0.0", 4 | "description": "chrome-extension-react-typescript-tailwind-starter", 5 | "main": "index.js", 6 | "scripts": { 7 | "watch": "webpack --config webpack/webpack.dev.js --watch", 8 | "build": "webpack --config webpack/webpack.prod.js", 9 | "clean": "rimraf dist", 10 | "test": "npx jest", 11 | "style": "prettier --write \"src/**/*.{ts,tsx}\"" 12 | }, 13 | "author": "", 14 | "license": "MIT", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/sumansid/chrome-extention-react-typescript-tailwind-starter.git" 18 | }, 19 | "dependencies": { 20 | "react": "^17.0.1", 21 | "react-dom": "^17.0.1" 22 | }, 23 | "devDependencies": { 24 | "@types/chrome": "0.0.158", 25 | "@types/jest": "^27.0.2", 26 | "@types/react": "^17.0.0", 27 | "@types/react-dom": "^17.0.0", 28 | "autoprefixer": "^10.4.7", 29 | "copy-webpack-plugin": "^9.0.1", 30 | "css-loader": "^6.7.1", 31 | "glob": "^7.1.6", 32 | "jest": "^27.2.1", 33 | "postcss": "^8.4.14", 34 | "postcss-loader": "^7.0.0", 35 | "prettier": "^2.2.1", 36 | "rimraf": "^3.0.2 ", 37 | "style-loader": "^3.3.1", 38 | "tailwindcss": "^3.1.4", 39 | "ts-jest": "^27.0.5", 40 | "ts-loader": "^8.0.0", 41 | "typescript": "^4.4.3 ", 42 | "webpack": "^5.61.0", 43 | "webpack-cli": "^4.0.0", 44 | "webpack-merge": "^5.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /webpack/webpack.common.js: -------------------------------------------------------------------------------- 1 | const webpack = require("webpack"); 2 | const path = require("path"); 3 | const CopyPlugin = require("copy-webpack-plugin"); 4 | const srcDir = path.join(__dirname, "..", "src"); 5 | 6 | module.exports = { 7 | entry: { 8 | popup: path.join(srcDir, "popup.tsx"), 9 | options: path.join(srcDir, "options.tsx"), 10 | background: path.join(srcDir, "background.ts"), 11 | content_script: path.join(srcDir, "content_script.tsx"), 12 | }, 13 | output: { 14 | path: path.join(__dirname, "../dist/js"), 15 | filename: "[name].js", 16 | }, 17 | optimization: { 18 | splitChunks: { 19 | name: "vendor", 20 | chunks(chunk) { 21 | return chunk.name !== "background"; 22 | }, 23 | }, 24 | }, 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.tsx?$/, 29 | use: "ts-loader", 30 | exclude: /node_modules/, 31 | }, 32 | 33 | { 34 | use: [ 35 | "style-loader", 36 | "css-loader", 37 | { 38 | loader: "postcss-loader", 39 | options: { 40 | postcssOptions: { 41 | ident: "postcss", 42 | plugins: ["tailwindcss", "autoprefixer"], 43 | }, 44 | }, 45 | }, 46 | ], 47 | test: /\.css$/i, 48 | }, 49 | ], 50 | }, 51 | resolve: { 52 | extensions: [".ts", ".tsx", ".js"], 53 | }, 54 | plugins: [ 55 | new CopyPlugin({ 56 | patterns: [{ from: ".", to: "../", context: "public" }], 57 | options: {}, 58 | }), 59 | ], 60 | }; 61 | --------------------------------------------------------------------------------