├── .env.example ├── .eslintrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── stale.yml ├── .gitignore ├── .gitpod.yml ├── .prettierignore ├── .prettierrc.json ├── .vercelignore ├── LICENSE.md ├── README.md ├── components ├── FeatureCard.tsx ├── Footer.tsx ├── FrameworkCard.tsx ├── Navbar.tsx ├── PwaImages.tsx ├── Shield.tsx ├── Spinner.tsx ├── dashboard │ ├── Navbar.tsx │ └── SiteCard.tsx └── site │ ├── AdvancedSettingsTab.tsx │ ├── CodeSnippet.tsx │ ├── GeneralSettingsTab.tsx │ └── SiteHead.tsx ├── docs ├── _sidebar.txt ├── framework-agnostic.md ├── how-it-works.md ├── index.md ├── security.md ├── self-hosting.md ├── with-angular.md ├── with-html.md ├── with-nextjs-11.md ├── with-nextjs.md ├── with-nuxtjs.md ├── with-svelte-kit.md ├── with-svelte.md └── with-vue.md ├── lib ├── baseUrl.ts ├── blockLogins.ts ├── compareHashedPasswords.ts ├── deleteSite.ts ├── features.tsx ├── fetcher.ts ├── frameworks.ts ├── getLastLogin.ts ├── getSuccessfulLogins.ts ├── getUnsuccessfulLogins.ts ├── handleNewSite.ts ├── hashPassword.ts ├── rate-limit.ts ├── sortSiteCardsByUpdatedDate.ts ├── useSites.ts ├── validateAndUpdateSiteData.ts └── validatePassword.ts ├── next-env.d.ts ├── next.config.js ├── package.json ├── packages └── script.js ├── pages ├── _app.tsx ├── _document.tsx ├── api │ ├── add-new-site.ts │ ├── auth │ │ └── [...auth0].ts │ ├── fetch-sites.ts │ ├── get-site-from-site-id.ts │ ├── login-to-site.ts │ ├── site │ │ ├── block-logins.ts │ │ ├── delete-site.ts │ │ ├── update-caption.ts │ │ ├── update-logo-url.ts │ │ ├── update-max-login-duration.ts │ │ ├── update-name.ts │ │ ├── update-site-desc.ts │ │ ├── update-site-password.ts │ │ └── update-title.ts │ └── verify-token.ts ├── dashboard │ └── index.tsx ├── errors │ ├── logins-blocked.tsx │ ├── noscript.tsx │ └── request-blocked.tsx ├── index.tsx ├── new.tsx ├── p │ └── [siteId].tsx ├── site │ └── [siteId].tsx ├── support.tsx └── with.tsx ├── postcss.config.js ├── public ├── empty.png ├── favicon.ico ├── frameworks.png ├── frameworks │ ├── angular.png │ ├── frameworks.gif │ ├── gatsby.png │ ├── html.png │ ├── nextjs.png │ ├── nuxtjs.png │ ├── preact.png │ ├── react.png │ ├── svelte.png │ └── vue.png ├── icons │ ├── apple-icon-180.png │ ├── apple-splash-dark-1125-2436.jpg │ ├── apple-splash-dark-1136-640.jpg │ ├── apple-splash-dark-1170-2532.jpg │ ├── apple-splash-dark-1242-2208.jpg │ ├── apple-splash-dark-1242-2688.jpg │ ├── apple-splash-dark-1284-2778.jpg │ ├── apple-splash-dark-1334-750.jpg │ ├── apple-splash-dark-1536-2048.jpg │ ├── apple-splash-dark-1620-2160.jpg │ ├── apple-splash-dark-1668-2224.jpg │ ├── apple-splash-dark-1668-2388.jpg │ ├── apple-splash-dark-1792-828.jpg │ ├── apple-splash-dark-2048-1536.jpg │ ├── apple-splash-dark-2048-2732.jpg │ ├── apple-splash-dark-2160-1620.jpg │ ├── apple-splash-dark-2208-1242.jpg │ ├── apple-splash-dark-2224-1668.jpg │ ├── apple-splash-dark-2388-1668.jpg │ ├── apple-splash-dark-2436-1125.jpg │ ├── apple-splash-dark-2532-1170.jpg │ ├── apple-splash-dark-2688-1242.jpg │ ├── apple-splash-dark-2732-2048.jpg │ ├── apple-splash-dark-2778-1284.jpg │ ├── apple-splash-dark-640-1136.jpg │ ├── apple-splash-dark-750-1334.jpg │ ├── apple-splash-dark-828-1792.jpg │ ├── favicon-196.png │ ├── manifest-icon-192.png │ └── manifest-icon-512.png ├── logo.svg ├── manifest.json ├── noscript-error-banner.png ├── ogimage.png ├── staticshield-100x100.png ├── staticshield-rounded.png ├── staticshield-with-bg.png ├── staticshield.png ├── thumbnail.png └── vercel.svg ├── scripts └── prepare-db.js ├── styles ├── Home.module.css ├── globals.css └── theme.ts ├── tailwind.config.js ├── tsconfig.json ├── types └── interfaces.ts ├── utils ├── addHarperDbRecord.ts ├── fetchSites.ts ├── getHashedPasswordFromSiteId.ts ├── getSiteFromSiteId.ts ├── update │ ├── blockLogins.ts │ ├── deleteSite.ts │ ├── updateCaption.ts │ ├── updateLogoUrl.ts │ ├── updateMaxLoginDuration.ts │ ├── updateSiteDesc.ts │ ├── updateSiteName.ts │ ├── updateSitePassword.ts │ └── updateTitle.ts ├── updateLoginCount.ts └── updateUnsuccessfulLoginsCount.ts └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | AUTH0_SECRET= 2 | AUTH0_BASE_URL= 3 | AUTH0_ISSUER_BASE_URL= 4 | AUTH0_CLIENT_ID= 5 | AUTH0_CLIENT_SECRET= 6 | HARPERDB_URL= 7 | HARPERDB_KEY= 8 | HASH_SECRET= 9 | JWT_TOKEN= 10 | TOKEN_SECRET= 11 | NEXT_PUBLIC_BASE_URL= -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next", 3 | "rules": { 4 | "no-unused-vars": ["warn", { "varsIgnorePattern": "^_" }] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.buymeacoffee.com/lalitcodes'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: '/' 5 | schedule: 6 | interval: "weekly" 7 | open-pull-requests-limit: 0 8 | assignees: 9 | - 'Lalit2005' 10 | reviewers: 11 | - 'Lalit2005' 12 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 30 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Comment to post when marking an issue as stale. Set to `false` to disable 10 | markComment: > 11 | This issue has been automatically marked as stale because it has not had 12 | recent activity. It will be closed if no further activity occurs. Thank you 13 | for your contributions. 14 | # Comment to post when closing a stale issue. Set to `false` to disable 15 | closeComment: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # script 4 | public/script.js 5 | public/script.js.map 6 | 7 | # dependencies 8 | /node_modules 9 | /.pnp 10 | .pnp.js 11 | 12 | # testing 13 | /coverage 14 | 15 | # next.js 16 | /.next/ 17 | /out/ 18 | 19 | # production 20 | /build 21 | 22 | # misc 23 | .parcel-cache 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | 32 | # local env files 33 | .env.local 34 | .env.development.local 35 | .env.test.local 36 | .env.production.local 37 | 38 | # vercel 39 | .vercel 40 | 41 | # VSCode extensions 42 | .VSCodeCounter 43 | public/workbox-*.js.map 44 | public/workbox-*.js 45 | public/sw.js.map 46 | public/sw.js 47 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | # This configuration file was automatically generated by Gitpod. 2 | # Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file) 3 | # and commit this file to your remote git repository to share the goodness with others. 4 | 5 | tasks: 6 | - init: yarn install 7 | command: yarn dev 8 | 9 | 10 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | .vercel -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "jsxBracketSameLine": true, 4 | "jsxSingleQuote": true, 5 | "singleQuote": true, 6 | "bracketSpacing": true, 7 | "semi": true, 8 | "useTabs": false, 9 | "tabWidth": 2 10 | } 11 | -------------------------------------------------------------------------------- /.vercelignore: -------------------------------------------------------------------------------- 1 | docs/ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Lalit 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 |  4 | 5 | # [How I built it](https://lalit2005.hashnode.dev/staticshield) 6 | 7 | ## Demo 8 | 9 | Password protect a website in less than 2 mins!! 10 | 11 | https://user-images.githubusercontent.com/69138026/123917671-ab7ca700-d9a0-11eb-8531-4297d2b12ced.mp4 12 | 13 | 14 | ## Some useful links that you might require 15 | 16 | 1. StaticShield website - https://staticshield.vercel.app 17 | 2. StaticShield Docs - https://staticshield.vercel.app/docs/ 18 | 3. GitHub repo - https://github.com/Lalit2005/staticshield 19 | 4. GitHub repo (docs) - https://github.com/Lalit2005/staticshield-docs 20 | 5. GitHub repo (StaticShield examples) - https://github.com/Lalit2005/staticshield-examples 21 | 22 | ## Tech stack 📚 23 | 24 | 1. Next.js - The most amazing React framework on the planet 25 | 2. TailwindCSS - Styling 26 | 3. Geist UI - React component library 27 | 4. HarperDB - Database 28 | 5. Nextra - Documentation 29 | 6. Auth0 - Authentication 30 | 7. Axios - API requests 31 | 8. React Hook Form - Form validation 32 | 9. Zod - Validation 33 | 10. Web3forms - Form submissions 34 | 11. SWR - Remote data fetching 35 | 12. Typescript - Type checking 36 | 13. Uglify-js - Minifying script 37 | 14. Vercel - Hosting 38 | -------------------------------------------------------------------------------- /components/FeatureCard.tsx: -------------------------------------------------------------------------------- 1 | interface NavBarProps { 2 | feature: string; 3 | children: JSX.Element; 4 | } 5 | 6 | export default function FeatureCard(props: NavBarProps) { 7 | const { feature, children } = props; 8 | return ( 9 |
{feature}
15 |StaticShield
18 |Sign In
23 |Sign Up
31 |Guides
40 |Docs
50 |
71 |
79 |
88 |
97 |
107 |
Login expiration time
finishes
44 | login expiration time
can be changed in{' '}
47 | General Settings Tab
48 | {siteData.site_name}
to continue
137 | setSiteNameDeletingInput(e.target.value)}
142 | onPaste={(e) => e.preventDefault()}
143 | />
144 |
,
10 | },
11 | {
12 | feature:
13 | 'No database, backend or server side code is required. Everything is taken care by StaticShield',
14 | children: 86 | OH, IT'S 87 |
20 | Logins to this site are temporarily blocked. If you are the site 21 | owner, visit the `Advanced` tab under settings for this site in 22 | StaticShield dashboard. 23 |
24 |22 | Staticshield checks for the valid token, verifies it and redirects 23 | to login page using Javascript. Please visit{' '} 24 | 29 | enablejavascript.io 30 | 31 | to learn how to enable Javascript in your preferred browser 32 |
33 |24 | Staticshield checks for the valid token, verifies it and redirects 25 | to login page using Javascript. All this is done by the script 26 | that is loaded externally. Please enable network requests in your 27 | browser. 28 |
29 |29 | {message} 30 |
31 | ); 32 | }; 33 | 34 | const [warningMessage, setWarningMessage] = useState( 35 | "That's a very weak password!" 36 | ); 37 | const [description, setDescription] = useState(''); 38 | 39 | useEffect(() => { 40 | router.prefetch('/dashboard'); 41 | setDescription(router.query?.desc?.toString() || ''); 42 | }, [router]); 43 | 44 | const { setVisible, bindings } = useModal(); 45 | const [_, setToast] = useToasts(); 46 | 47 | const { 48 | register, 49 | handleSubmit, 50 | formState: { errors }, 51 | } = useForm{warningMessage}
218 |{caption}
113 |
151 | Code
152 | >
153 | }>
154 |