├── public ├── favicon.ico ├── icons │ ├── maskable_icon.png │ ├── maskable_icon_x128.png │ ├── maskable_icon_x192.png │ ├── maskable_icon_x384.png │ ├── maskable_icon_x48.png │ ├── maskable_icon_x512.png │ ├── maskable_icon_x72.png │ └── maskable_icon_x96.png ├── screenshots │ ├── iphone.png │ └── ipad-pro.png ├── robots.txt ├── images │ ├── arrow-right-solid.svg │ ├── exchange-alt-solid.svg │ ├── tools-solid.svg │ ├── undraw_at_home_octe.svg │ ├── undraw_convert_2gjv.svg │ ├── undraw_Live_collaboration_re_60ha.svg │ └── undraw_authentication_fsn5.svg ├── sitemap.xml ├── manifest.json ├── sw.js └── workbox-ea903bce.js ├── .prettierrc.json ├── jsconfig.json ├── styles ├── globals.css └── theme.js ├── next.config.js ├── components ├── WordCounters.js ├── Nav.js ├── ColorChanger.js ├── Layout.js ├── SectionItem.js ├── Footer.js └── Header.js ├── .prettierignore ├── .gitignore ├── pages ├── _app.js ├── index.js ├── _document.js ├── word-count.js ├── secure-random-password-generator.js └── px-converter.js ├── .eslintignore ├── .eslintrc.yml ├── next-seo-config.js ├── lib └── constants.js ├── scripts └── generate-sitemap.js ├── README.md ├── package.json └── hooks ├── useWordCount.js ├── usePasswordGenerator.js └── usePxConverter.js /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "arrowParens": "avoid", 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /public/icons/maskable_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon.png -------------------------------------------------------------------------------- /public/screenshots/iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/screenshots/iphone.png -------------------------------------------------------------------------------- /public/screenshots/ipad-pro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/screenshots/ipad-pro.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x128.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x192.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x384.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x48.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x512.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x72.png -------------------------------------------------------------------------------- /public/icons/maskable_icon_x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dastasoft/handy-tools/HEAD/public/icons/maskable_icon_x96.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /api 3 | Host: https://handy-tools.dastasoft.com/ 4 | Sitemap: https://handy-tools.dastasoft.com/sitemap.xml 5 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/components/*": ["components/*"], 6 | "@/hooks/*": ["hooks/*"], 7 | "@/lib/*": ["lib/*"], 8 | "@/styles/*": ["styles/*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | height: 100%; 6 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 7 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 8 | } 9 | 10 | #__next { 11 | height: 100%; 12 | } 13 | 14 | a { 15 | color: inherit; 16 | text-decoration: none; 17 | } 18 | 19 | * { 20 | box-sizing: border-box; 21 | } 22 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require('next-pwa') 2 | const runtimeCaching = require('next-pwa/cache') 3 | 4 | module.exports = withPWA({ 5 | pwa: { 6 | dest: 'public', 7 | runtimeCaching, 8 | }, 9 | future: { 10 | webpack5: true, 11 | }, 12 | webpack: (config, { isServer }) => { 13 | if (isServer) { 14 | require('./scripts/generate-sitemap') 15 | } 16 | 17 | return config 18 | }, 19 | }) 20 | -------------------------------------------------------------------------------- /styles/theme.js: -------------------------------------------------------------------------------- 1 | import { extendTheme } from '@chakra-ui/react' 2 | import { mode } from '@chakra-ui/theme-tools' 3 | 4 | const theme = extendTheme({ 5 | fonts: { 6 | heading: 'Lato', 7 | body: 'Roboto', 8 | }, 9 | styles: { 10 | global: props => ({ 11 | 'body, h2, p': { 12 | color: mode('gray.700', 'whiteAlpha.900')(props), 13 | }, 14 | }), 15 | }, 16 | }) 17 | 18 | export default theme 19 | -------------------------------------------------------------------------------- /components/WordCounters.js: -------------------------------------------------------------------------------- 1 | import { Flex, Text, useColorModeValue } from '@chakra-ui/react' 2 | 3 | export default function WordCounters({ value, caption }) { 4 | const bg = useColorModeValue('whiteAlpha.900', 'gray.800') 5 | 6 | return ( 7 | 8 | 9 | {value} 10 | 11 | {caption} 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /public/images/arrow-right-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://handy-tools.dastasoft.com 5 | 6 | 7 | 8 | https://handy-tools.dastasoft.com/px-converter 9 | 10 | 11 | 12 | https://handy-tools.dastasoft.com/secure-random-password-generator 15 | 16 | 17 | 18 | https://handy-tools.dastasoft.com/word-count 19 | 20 | 21 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 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 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /.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 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | #eslint 37 | .eslintcache -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import { ChakraProvider } from '@chakra-ui/react' 2 | import { DefaultSeo } from 'next-seo' 3 | 4 | import SEO from '../next-seo-config' 5 | 6 | import Layout from '@/components/Layout' 7 | 8 | import '@/styles/globals.css' 9 | import theme from '@/styles/theme' 10 | 11 | function MyApp({ Component, pageProps }) { 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | } 21 | 22 | export default MyApp 23 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 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 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | public/sw.* 37 | public/workbox* -------------------------------------------------------------------------------- /components/Nav.js: -------------------------------------------------------------------------------- 1 | import { SimpleGrid } from '@chakra-ui/react' 2 | 3 | import { links } from '@/lib/constants' 4 | import SectionItem from './SectionItem' 5 | 6 | const Nav = ({ onClose }) => { 7 | return ( 8 | 9 | {links.map(link => ( 10 | 17 | ))} 18 | 19 | ) 20 | } 21 | 22 | export default Nav 23 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import { SimpleGrid } from '@chakra-ui/react' 2 | 3 | import SectionItem from '@/components/SectionItem' 4 | import { links } from '@/lib/constants' 5 | 6 | export default function Home() { 7 | return ( 8 | 9 | {links 10 | .filter(link => link.href !== '/') 11 | .map(link => ( 12 | 18 | ))} 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | es2021: true 4 | node: true 5 | extends: 6 | - 'plugin:react/recommended' 7 | - standard 8 | - prettier 9 | parserOptions: 10 | ecmaFeatures: 11 | jsx: true 12 | ecmaVersion: 12 13 | sourceType: module 14 | plugins: 15 | - react 16 | rules: 17 | { 18 | 'react/react-in-jsx-scope': 'off', 19 | 'react/display-name': 'off', 20 | 'react/prop-types': 'off', 21 | 'react/jsx-props-no-spreading': 'off', 22 | 'jsx-a11y/href-no-hash': ['off'], 23 | 'jsx-a11y/anchor-is-valid': ['off'], 24 | 'react/jsx-filename-extension': ['warn', { extensions: ['.js', '.jsx'] }], 25 | } 26 | -------------------------------------------------------------------------------- /public/images/exchange-alt-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/ColorChanger.js: -------------------------------------------------------------------------------- 1 | import { IconButton, useColorMode, useColorModeValue } from '@chakra-ui/react' 2 | import { SunIcon, MoonIcon } from '@chakra-ui/icons' 3 | 4 | export default function ColorChanger() { 5 | const { toggleColorMode } = useColorMode() 6 | const text = useColorModeValue('dark', 'light') 7 | const SwitchIcon = useColorModeValue(MoonIcon, SunIcon) 8 | 9 | return ( 10 | } 18 | /> 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /next-seo-config.js: -------------------------------------------------------------------------------- 1 | import { 2 | AUTHOR, 3 | DESCRIPTION, 4 | HOMEPAGE, 5 | THUMBNAIL, 6 | TITLE, 7 | } from '@/lib/constants' 8 | 9 | export default { 10 | title: TITLE, 11 | description: DESCRIPTION, 12 | canonical: HOMEPAGE, 13 | languageAlternates: [ 14 | { 15 | hrefLang: 'en', 16 | href: HOMEPAGE, 17 | }, 18 | ], 19 | openGraph: { 20 | profile: { 21 | username: AUTHOR, 22 | }, 23 | type: 'website', 24 | locale: 'en', 25 | url: HOMEPAGE, 26 | site_name: TITLE, 27 | images: [ 28 | { 29 | url: THUMBNAIL, 30 | width: 200, 31 | height: 200, 32 | alt: TITLE, 33 | }, 34 | ], 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /components/Layout.js: -------------------------------------------------------------------------------- 1 | import { Box, Flex, useColorModeValue } from '@chakra-ui/react' 2 | 3 | import Header from '@/components/Header' 4 | import Footer from '@/components/Footer' 5 | 6 | const Layout = ({ children }) => { 7 | const bg = useColorModeValue('linkedin.100', 'gray.700') 8 | 9 | return ( 10 | 11 |
12 | 20 | {children} 21 | 22 |