Repository: thomasjohnkane/tailwind-alpine-chrome-extension Branch: master Commit: b9458a435d4f Files: 17 Total size: 9.5 KB Directory structure: gitextract_5wu7x6hr/ ├── .gitignore ├── README.md ├── extension/ │ └── manifest.json ├── package.json ├── postcss.config.js ├── src/ │ ├── background/ │ │ └── index.js │ ├── content/ │ │ ├── index.css │ │ └── index.js │ ├── options/ │ │ ├── index.css │ │ ├── index.html │ │ └── index.js │ ├── popup/ │ │ ├── index.css │ │ ├── index.html │ │ └── index.js │ └── tailwind.css ├── tailwind.config.js └── webpack.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules extension/dist ================================================ FILE: README.md ================================================ # Tailwind3/Alpine3 Web Extension Boilerplate This is a starting place for building a Web Extension with Tailwindcss & Alpinejs | | | | |:-------------------------:|:-------------------------:|:-------------------------:| |Hello World Popup *Basic Popup with Tailwind* | Alpine Button Clicked *Alpine `@click` Works!* |Hello World Options *Basic Options*| ## Installation ### Setup local project * `git clone git@github.com:thomasjohnkane/tailwind-alpine-chrome-extension.git` * `npm i && npm run dev` ### Install on Chrome * Navigate to `chrome://extensions` in Chrome; * Enable the **Developer mode** * Click on **Load unpacked extension** (upper left nav) * Upload the entire `extension` folder ## Why use this? * It automatically puts [tailwindcss.com](https://tailwindcss.com/) into your project * It automatically puts [alpinejs](https://github.com/alpinejs/alpine) into your project * Hot reload (watches files and updates chrome) * Cross browser support (Chrome & Firefox, Safari/Edge TBD) * Provides basic `popup.html` & `options.html` (embeded in settings page) ## Goals of project - Create a starting point for building web extensions - Use alpine.js and tailwind.css - Be cross browser (chrome, firefox, safari, edge?) - Full DX path integrated - Readme to set it up - Watch script - Env based config files - Hot reloading (https://github.com/rubenspgcavalcante/webpack-extension-reloader) - deploy script (create zip for submitting to store) - Deploy instructions (per browser) ## Roadmap - [X] Create folder structure - [X] Add webpack - [X] Make hello world work in dev - [X] Add Tailwindcss - [X] Add Alpinejs - [X] Add package.json build scripts - [X] Add hot reloading - [X] Add basic options.html page - [ ] Handle sub views and routes for popup - [ ] Add basic example of content.js - [ ] Add basic example of background.js - [X] Update readme with instructions, etc - [X] Push to github - [ ] Add build-zip script for deployment - [ ] Tag release v1.0 ## Credit * Thanks to Caleb Porzio for Alpinejs * Thanks to Adam Watham for Tailwindcss * Thanks to @rubenspgcavalcante for Webpack Extension Reload plugin * Thanks to @Kocal, @EmailThis, and @williankeller for inspiration ## Security If you discover any security related issues, please email instead of using the issue tracker. ## Contributing 1. Fork it () 2. Create your feature branch (`git checkout -b feature/fooBar`) 3. Commit your changes (`git commit -am 'Add some fooBar'`) 4. Push to the branch (`git push origin feature/fooBar`) 5. Create a new Pull Request ================================================ FILE: extension/manifest.json ================================================ { "name": "Tunnelme Extension", "version": "0.0.1", "description": "Record user actions to generate API endpoints.", "manifest_version": 2, "browser_action": { "default_popup": "./dist/popup.html", "default_title": "Open the popup", "default_icon":"./dist/icons/icon-16.png" }, "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "content_scripts": [ { "js": ["dist/content.dist.js"], "css": ["dist/content.css"], "matches": ["https://*/*"] } ], "background": { "scripts": ["dist/background.dist.js"] }, "options_ui": { "page": "dist/options.html", "open_in_tab": false } } ================================================ FILE: package.json ================================================ { "name": "tailwind-alpine-web-extension", "version": "1.0.0", "scripts": { "watch:tailwind": "NODE_ENV=development postcss src/tailwind.css -o extension/dist/tailwind.dist.css -w", "dev:tailwind": "NODE_ENV=development postcss src/tailwind.css -o extension/dist/tailwind.dist.css", "build:tailwind": "NODE_ENV=production postcss src/tailwind.css -o extension/dist/tailwind.dist.css", "dev": "concurrently \"npm run watch:tailwind\" \"NODE_ENV=development webpack --config webpack.config.js --mode=development --watch\"", "build": "npm run build:tailwind && webpack --mode production" }, "devDependencies": { "alpinejs": "^3.7.1", "autoprefixer": "^10.4.0", "concurrently": "^6.5.1", "copy-webpack-plugin": "^10.2.0", "cross-env": "^7.0.3", "postcss-cli": "^9.1.0", "postcss-loader": "^6.2.1", "tailwindcss": "^3.0.7", "webpack": "^5.65.0", "webpack-cli": "^4.9.1", "webpack-extension-reloader": "^1.1.4" } } ================================================ FILE: postcss.config.js ================================================ const tailwindcss = require('tailwindcss'); module.exports = { plugins: [ tailwindcss('./tailwind.config.js'), require('autoprefixer'), ], }; ================================================ FILE: src/background/index.js ================================================ ================================================ FILE: src/content/index.css ================================================ @import "../dist/tailwind.dist.css" ================================================ FILE: src/content/index.js ================================================ import Alpine from 'alpinejs' window.Alpine = Alpine Alpine.start() ================================================ FILE: src/options/index.css ================================================ @import "../dist/tailwind.dist.css" ================================================ FILE: src/options/index.html ================================================

Options Page

Update me in `src/options/index.html`

================================================ FILE: src/options/index.js ================================================ import Alpine from 'alpinejs' window.Alpine = Alpine Alpine.start() ================================================ FILE: src/popup/index.css ================================================ @import "../dist/tailwind.dist.css" ================================================ FILE: src/popup/index.html ================================================

Hello Web Extension

Update me in `src/popup/index.html`


Great Scott!
================================================ FILE: src/popup/index.js ================================================ import Alpine from 'alpinejs' window.Alpine = Alpine Alpine.start() ================================================ FILE: src/tailwind.css ================================================ @tailwind base; @tailwind components; @tailwind utilities; ================================================ FILE: tailwind.config.js ================================================ module.exports = { content: ["./src/**/*.{html,js}"], theme: { minWidth: { '0': '0', 'popup': '350px', full: '100%' }, extend: {} }, variants: {}, plugins: [] } ================================================ FILE: webpack.config.js ================================================ const ExtensionReloader = require('webpack-extension-reloader'); const CopyPlugin = require('copy-webpack-plugin'); const path = require('path'); const contentScripts = { content: './content/index.js' } const extensionPages = { options: './options/index.js', popup: './popup/index.js', } let config = { mode: process.env.NODE_ENV, context: __dirname + '/src' }; let ExtensionConfig = Object.assign({}, config, { entry: { background: './background/index.js', ...contentScripts, ...extensionPages }, output: { path: __dirname + '/extension/dist/', filename: '[name].dist.js', }, plugins: [ new ExtensionReloader({ port: 9090, reloadPage: true, entries: { contentScript: Object.keys(contentScripts), extensionPage: Object.keys(extensionPages), background: 'background' } }), new CopyPlugin({ patterns: [ { from: './icons/*', to: __dirname + '/extension/dist/', }, { from: './popup/index.html', to: __dirname + '/extension/dist/popup.html', }, { from: './popup/index.css', to: __dirname + '/extension/dist/popup.css', }, { from: './options/index.html', to: __dirname + '/extension/dist/options.html', }, { from: './options/index.css', to: __dirname + '/extension/dist/options.css', }, { from: './content/index.css', to: __dirname + '/extension/dist/content.css', }, ] }), ] }); module.exports = [ ExtensionConfig, ];