{"id":29182876,"url":"https://github.com/magiclabs/example-chrome-extension","last_synced_at":"2025-07-01T20:33:19.613Z","repository":{"id":44551051,"uuid":"344692166","full_name":"magiclabs/example-chrome-extension","owner":"magiclabs","description":null,"archived":false,"fork":false,"pushed_at":"2022-02-08T14:41:25.000Z","size":253,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2023-07-26T18:33:26.789Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magiclabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-05T04:18:21.000Z","updated_at":"2023-07-26T18:33:26.790Z","dependencies_parsed_at":"2022-09-10T04:15:53.379Z","dependency_job_id":null,"html_url":"https://github.com/magiclabs/example-chrome-extension","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/magiclabs/example-chrome-extension","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclabs%2Fexample-chrome-extension","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclabs%2Fexample-chrome-extension/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclabs%2Fexample-chrome-extension/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclabs%2Fexample-chrome-extension/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magiclabs","download_url":"https://codeload.github.com/magiclabs/example-chrome-extension/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magiclabs%2Fexample-chrome-extension/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263033232,"owners_count":23403118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-01T20:33:18.985Z","updated_at":"2025-07-01T20:33:19.602Z","avatar_url":"https://github.com/magiclabs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Quick Start Instructions\n\n```txt\n$ git clone https://github.com/magiclabs/example-chrome-extension.git\n$ cd example-chrome-extension\n$ mv .env.example .env // enter your Magic Publishable API key\n$ yarn install\n$ yarn build\n```\n\nScroll down to \"Running the App Locally\" for instructions on how to upload your extension to your browser.\n\n# Resources\n\nView the example code [**here**](https://github.com/magiclabs/example-chrome-extension).\n\nTry out the browser extension [**here**](https://chrome.google.com/webstore/detail/magic-chrome-extension/ealdjejebmabnecpgbahojanllhpjlef).\n\n# Introduction\n\nMaybe you want to allow users of your extension to have profiles, or maybe you want to charge for premuim features. This tutorial shows how you can integrate Magic passwordless authentication into a Chrome browser extension using React.\n\nAfter clicking the browser extension icon and then the \"login\" button, the user will be directed to a full-page tab to complete the auth flow. After that, clicking the browser extension will show the user authenticated!\n\n_Note: The new tab is required because if we had the login form inside the browser extension popup, as soon as the user navigated away to check their email for the link, the popup page would close and the auth flow would break._\n\n## File Structure\n\nOur application's file structure will look like this.\n\n```txt\n├── .env\n├── build\n├── README.md\n├── package.json\n├── public\n│   ├── icon-purple.png\n│   ├── index.html\n│   └── manifest.json\n├── src\n│   ├── components\n│   │   ├── App.js\n│   │   ├── Loading.js\n│   │   ├── Login.js\n│   │   └── Profile.js\n│   ├── index.js\n│   ├── magic.js\n│   └── styles.css\n└── yarn.lock\n```\n\nThe folder that we will be uploading to Chrome will be `build`, which after you run `yarn build` will look something like this.\n\n```txt\n├── build\n│   ├── asset-manifest.json\n│   ├── icon-purple.png\n│   ├── index.html\n│   ├── manifest.json\n│   └── static\n│       ├── css\n│       │   ├── main.ee12e5fd.chunk.css\n│       │   └── main.ee12e5fd.chunk.css.map\n│       └── js\n│           ├── 2.c16f79f9.chunk.js\n│           ├── 2.c16f79f9.chunk.js.LICENSE.txt\n│           ├── 2.c16f79f9.chunk.js.map\n│           ├── main.bae666a1.chunk.js\n│           ├── main.bae666a1.chunk.js.map\n│           ├── runtime-main.33ea36a3.js\n│           └── runtime-main.33ea36a3.js.map\n```\n\n# Building the App\n\nThe Magic React app boilerplate will be taken from the `Hello World (React)` template using the `npx make-magic` command.\n\n```txt\n$ npx make-magic\nnpx: installed 1 in 1.472s\n\n\n █▀▀ █▀█ █▀▀ ▄▀█ ▀█▀ █▀▀\n █▄▄ █▀▄ ██▄ █▀█  █  ██▄\n\n █▀▄▀█ ▄▀█ █▀▀ █ █▀▀\n █ ▀ █ █▀█ █▄█ █ █▄▄\n\n ▄▀█ █▀█ █▀█\n █▀█ █▀▀ █▀▀\n\n\nRunning scaffold create-magic-app\n\n✔ What is your project named? · example-electron\n✔ Choose a template: · hello-world-react\n✔ Enter your Magic publishable API key: · pk_test_...\n✔ Choose an NPM client: yarn\n```\n\nSince there's no redirect back to the chrome extension, go ahead and delete\n\n1. the `redirectURI` parameter given to `loginWithMagicLink()`\n2. the `/components/Callback.js` component\n3. the `/callback` route in `App.js`\n\n## Manifest.json\n\nEvery browser extension needs a [`manifest.json`](https://developer.chrome.com/docs/extensions/mv3/manifest/) file, which tells Chrome important information about your extension, such as your icons, permissions (tab controls, storage access, etc), which scripts should be loaded into users browser windows, and much more.\n\n```json\n{\n  \"name\": \"Magic Chrome Extension\",\n  \"description\": \"Build a Chrome extension with Magic auth!\",\n  \"version\": \"0.1.0\",\n  \"manifest_version\": 3,\n  \"action\": {\n    \"default_popup\": \"index.html\",\n    \"default_icon\": {\n      \"16\": \"/icon-purple.png\",\n      \"48\": \"/icon-purple.png\",\n      \"128\": \"/icon-purple.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"/icon-purple.png\",\n    \"48\": \"/icon-purple.png\",\n    \"128\": \"/icon-purple.png\"\n  }\n}\n```\n\n## Login.js\n\nA few changes need to be made to the `Login.js` component which was generated for us with the `npx make-magic` command. If the window is \u003e 400 pixels wide, it's safe to assume the user is on the full page view, and if so, we'll display the full login form. Otherwise we are assuming the user is viewing in the actual extension popup, so we'll display a button to login, which will create a new full page tab with the login form.\n\n```js\nexport default function Login() {\n  const [email, setEmail] = useState('');\n  const [isLoggingIn, setIsLoggingIn] = useState(false);\n  const [isFullPage, setIsFullPage] = useState(false);\n  const history = useHistory();\n\n  /* Relying on the page width to tell if the user is viewing in the popup or full page */\n  useEffect(() =\u003e {\n    if (window.innerWidth \u003e 400) setIsFullPage(true);\n  }, []);\n\n  /**\n   * Perform login action via Magic's passwordless flow. Upon successuful\n   * completion of the login flow, a user is redirected to the homepage.\n   */\n  const login = useCallback(async () =\u003e {\n    setIsLoggingIn(true);\n\n    try {\n      await magic.auth.loginWithMagicLink({ email });\n      history.push('/');\n    } catch {\n      setIsLoggingIn(false);\n    }\n  }, [email]);\n\n  /**\n   * Saves the value of our email input into component state.\n   */\n  const handleInputOnChange = useCallback((event) =\u003e {\n    setEmail(event.target.value);\n  }, []);\n\n  return (\n    \u003cdiv className='container'\u003e\n      {!isFullPage ? (\n        \u003cbutton onClick={() =\u003e chrome.tabs.create({ url: 'index.html' })}\u003eLogin\u003c/button\u003e\n      ) : (\n        \u003c\u003e\n          \u003ch1\u003ePlease sign up or login\u003c/h1\u003e\n          \u003cinput\n            type='email'\n            name='email'\n            required='required'\n            placeholder='Enter your email'\n            onChange={handleInputOnChange}\n            disabled={isLoggingIn}\n          /\u003e\n          \u003cbutton onClick={login} disabled={isLoggingIn}\u003e\n            Send\n          \u003c/button\u003e\n        \u003c/\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\n# Running the App Locally\n\nYou need to upload your `build` folder to Chrome to test your extension locally. Run the following command in your terminal to create the `build` folder.\n\n```txt\nyarn build\n```\n\nNext, visit `chrome://extensions` in your Chrome URL bar. Then toggle `Developer Mode` on in the top right.\n\nClick \"Load unpacked\" and select your `build` folder. You should now see your Chrome extension in your browser! Test it out by clicking through and logging in.\n\n## Potential Errors\n\nYou may run into an error such as\n\n```\nRefused to execute inline script because it violates the following Content Security Policy directive: \"script-src 'self'\"...\n```\n\nChrome has CSP settings to block certain scripts from being run. If you notice yourself running into this, make sure to include `INLINE_RUNTIME_CHUNK=false` in your `.env` file when running `yarn build`.\n\n# Done\n\nYour browser extension app is now secured with Magic! You can follow this link for instructions on how to publish your new extension to the Chrome Web Store https://developer.chrome.com/docs/webstore/publish/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagiclabs%2Fexample-chrome-extension","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagiclabs%2Fexample-chrome-extension","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagiclabs%2Fexample-chrome-extension/lists"}