├── .github
├── FUNDING.yml
├── web-check-logo.png
├── screenshots
│ ├── tiles
│ │ ├── dns.png
│ │ ├── hosts.png
│ │ ├── hsts.png
│ │ ├── ports.png
│ │ ├── ssl.png
│ │ ├── carbon.png
│ │ ├── cookies.png
│ │ ├── dnssec.png
│ │ ├── domain.png
│ │ ├── headers.png
│ │ ├── quality.png
│ │ ├── ranking.png
│ │ ├── robots.png
│ │ ├── server.png
│ │ ├── sitemap.png
│ │ ├── status.png
│ │ ├── threats.png
│ │ ├── archives.png
│ │ ├── dns-server.png
│ │ ├── features.png
│ │ ├── firewall.png
│ │ ├── location.png
│ │ ├── redirects.png
│ │ ├── screenshot.png
│ │ ├── tech-stack.png
│ │ ├── block-lists.png
│ │ ├── email-config.png
│ │ ├── linked-pages.png
│ │ ├── security-txt.png
│ │ ├── social-tags.png
│ │ ├── trace-route.png
│ │ ├── txt-records.png
│ │ ├── http-security.png
│ │ ├── tls-cipher-suites.png
│ │ ├── tls-security-config.png
│ │ └── tls-handshake-simulation.png
│ ├── web-check-screenshot1.png
│ ├── web-check-screenshot2.png
│ ├── web-check-screenshot3.png
│ ├── web-check-screenshot4.png
│ ├── web-check-screenshot5.png
│ ├── web-check-screenshot6.png
│ ├── web-check-screenshot7.png
│ ├── web-check-screenshot8.png
│ ├── web-check-screenshot9.png
│ ├── web-check-screenshot10.png
│ └── README.md
└── workflows
│ ├── mirror.yml
│ └── credits.yml
├── src
├── web-check-live
│ ├── typings
│ │ ├── file-types.d.ts
│ │ └── react-simple-maps.d.ts
│ ├── main.tsx
│ ├── styles
│ │ ├── colors.ts
│ │ ├── typography.ts
│ │ ├── globals.tsx
│ │ ├── dimensions.ts
│ │ └── index.css
│ ├── components
│ │ ├── misc
│ │ │ ├── Flag.tsx
│ │ │ ├── ActionButtons.tsx
│ │ │ ├── LocationMap.tsx
│ │ │ ├── Footer.tsx
│ │ │ ├── ErrorBoundary.tsx
│ │ │ ├── DocContent.tsx
│ │ │ └── SelfScanMsg.tsx
│ │ ├── Results
│ │ │ ├── Headers.tsx
│ │ │ ├── BlockLists.tsx
│ │ │ ├── Screenshot.tsx
│ │ │ ├── OpenPorts.tsx
│ │ │ ├── TxtRecords.tsx
│ │ │ ├── Firewall.tsx
│ │ │ ├── HttpSecurity.tsx
│ │ │ ├── ServerInfo.tsx
│ │ │ ├── RobotsTxt.tsx
│ │ │ ├── ServerStatus.tsx
│ │ │ ├── DnsRecords.tsx
│ │ │ ├── Redirects.tsx
│ │ │ ├── Archives.tsx
│ │ │ ├── Hsts.tsx
│ │ │ ├── DomainLookup.tsx
│ │ │ ├── HostNames.tsx
│ │ │ ├── DnsServer.tsx
│ │ │ ├── Lighthouse.tsx
│ │ │ ├── TraceRoute.tsx
│ │ │ ├── ServerLocation.tsx
│ │ │ ├── BuiltWith.tsx
│ │ │ ├── CarbonFootprint.tsx
│ │ │ ├── Sitemap.tsx
│ │ │ ├── MailConfig.tsx
│ │ │ ├── SocialTags.tsx
│ │ │ ├── Cookies.tsx
│ │ │ ├── SiteFeatures.tsx
│ │ │ ├── WhoIs.tsx
│ │ │ └── SecurityTxt.tsx
│ │ └── Form
│ │ │ ├── Nav.tsx
│ │ │ ├── Card.tsx
│ │ │ └── Heading.tsx
│ ├── utils
│ │ └── get-keys.ts
│ ├── App.tsx
│ └── views
│ │ └── NotFound.tsx
├── env.d.ts
├── components
│ ├── homepage
│ │ ├── TempDisabled.astro
│ │ ├── Features.astro
│ │ ├── ButtonGroup.astro
│ │ └── SponsorSegment.astro
│ ├── molecules
│ │ └── Icon.svelte
│ └── scafold
│ │ └── Footer.astro
├── layouts
│ └── Base.astro
├── styles
│ ├── colors.scss
│ └── media-queries.scss
└── pages
│ ├── check
│ └── [...target].astro
│ ├── web-check-api
│ └── spec.astro
│ ├── index.astro
│ └── account
│ └── index.astro
├── public
├── banner.png
├── favicon.ico
├── web-check.png
├── robots.txt
├── favicon-16x16.png
├── favicon-32x32.png
├── apple-touch-icon.png
├── fonts
│ ├── Inter-Bold.ttf
│ ├── Inter-Thin.ttf
│ ├── Inter-Black.ttf
│ ├── Inter-Light.ttf
│ ├── Inter-Medium.ttf
│ ├── Inter-Regular.ttf
│ ├── Inter-ExtraBold.ttf
│ ├── Inter-SemiBold.ttf
│ ├── PTMono-Regular.ttf
│ ├── Inter-ExtraLight.ttf
│ ├── Hubot-Sans
│ │ ├── Hubot-Sans.ttf
│ │ ├── Hubot-Sans.woff2
│ │ ├── OTF
│ │ │ ├── HubotSans-Black.otf
│ │ │ ├── HubotSans-Bold.otf
│ │ │ ├── HubotSans-Light.otf
│ │ │ ├── HubotSans-Italic.otf
│ │ │ ├── HubotSans-Medium.otf
│ │ │ ├── HubotSans-Regular.otf
│ │ │ ├── HubotSans-SemiBold.otf
│ │ │ ├── HubotSans-BoldItalic.otf
│ │ │ ├── HubotSans-ExtraBold.otf
│ │ │ ├── HubotSans-ExtraLight.otf
│ │ │ ├── HubotSans-BlackItalic.otf
│ │ │ ├── HubotSans-LightItalic.otf
│ │ │ ├── HubotSans-MediumItalic.otf
│ │ │ ├── HubotSansCondensed-Bold.otf
│ │ │ ├── HubotSansExpanded-Black.otf
│ │ │ ├── HubotSansExpanded-Bold.otf
│ │ │ ├── HubotSansExpanded-Light.otf
│ │ │ ├── HubotSans-ExtraBoldItalic.otf
│ │ │ ├── HubotSans-SemiBoldItalic.otf
│ │ │ ├── HubotSansCondensed-Black.otf
│ │ │ ├── HubotSansCondensed-Italic.otf
│ │ │ ├── HubotSansCondensed-Light.otf
│ │ │ ├── HubotSansCondensed-Medium.otf
│ │ │ ├── HubotSansExpanded-Italic.otf
│ │ │ ├── HubotSansExpanded-Medium.otf
│ │ │ ├── HubotSansExpanded-Regular.otf
│ │ │ ├── HubotSans-ExtraLightItalic.otf
│ │ │ ├── HubotSansCondensed-ExtraBold.otf
│ │ │ ├── HubotSansCondensed-Regular.otf
│ │ │ ├── HubotSansCondensed-SemiBold.otf
│ │ │ ├── HubotSansExpanded-BoldItalic.otf
│ │ │ ├── HubotSansExpanded-ExtraBold.otf
│ │ │ ├── HubotSansExpanded-ExtraLight.otf
│ │ │ ├── HubotSansExpanded-SemiBold.otf
│ │ │ ├── HubotSansCondensed-BlackItalic.otf
│ │ │ ├── HubotSansCondensed-BoldItalic.otf
│ │ │ ├── HubotSansCondensed-ExtraLight.otf
│ │ │ ├── HubotSansCondensed-LightItalic.otf
│ │ │ ├── HubotSansExpanded-BlackItalic.otf
│ │ │ ├── HubotSansExpanded-LightItalic.otf
│ │ │ ├── HubotSansExpanded-MediumItalic.otf
│ │ │ ├── HubotSansCondensed-MediumItalic.otf
│ │ │ ├── HubotSansCondensed-SemiBoldItalic.otf
│ │ │ ├── HubotSansExpanded-ExtraBoldItalic.otf
│ │ │ ├── HubotSansExpanded-SemiBoldItalic.otf
│ │ │ ├── HubotSansCondensed-ExtraBoldItalic.otf
│ │ │ ├── HubotSansCondensed-ExtraLightItalic.otf
│ │ │ └── HubotSansExpanded-ExtraLightItalic.otf
│ │ ├── TTF
│ │ │ ├── HubotSans-Black.ttf
│ │ │ ├── HubotSans-Bold.ttf
│ │ │ ├── HubotSans-Light.ttf
│ │ │ ├── HubotSans-Italic.ttf
│ │ │ ├── HubotSans-Medium.ttf
│ │ │ ├── HubotSans-Regular.ttf
│ │ │ ├── HubotSans-SemiBold.ttf
│ │ │ ├── HubotSans-BoldItalic.ttf
│ │ │ ├── HubotSans-ExtraBold.ttf
│ │ │ ├── HubotSans-ExtraLight.ttf
│ │ │ ├── HubotSans-BlackItalic.ttf
│ │ │ ├── HubotSans-LightItalic.ttf
│ │ │ ├── HubotSans-MediumItalic.ttf
│ │ │ ├── HubotSansCondensed-Bold.ttf
│ │ │ ├── HubotSansExpanded-Black.ttf
│ │ │ ├── HubotSansExpanded-Bold.ttf
│ │ │ ├── HubotSansExpanded-Light.ttf
│ │ │ ├── HubotSans-ExtraBoldItalic.ttf
│ │ │ ├── HubotSans-SemiBoldItalic.ttf
│ │ │ ├── HubotSansCondensed-Black.ttf
│ │ │ ├── HubotSansCondensed-Italic.ttf
│ │ │ ├── HubotSansCondensed-Light.ttf
│ │ │ ├── HubotSansCondensed-Medium.ttf
│ │ │ ├── HubotSansExpanded-Italic.ttf
│ │ │ ├── HubotSansExpanded-Medium.ttf
│ │ │ ├── HubotSansExpanded-Regular.ttf
│ │ │ ├── HubotSans-ExtraLightItalic.ttf
│ │ │ ├── HubotSansCondensed-ExtraBold.ttf
│ │ │ ├── HubotSansCondensed-Regular.ttf
│ │ │ ├── HubotSansCondensed-SemiBold.ttf
│ │ │ ├── HubotSansExpanded-BoldItalic.ttf
│ │ │ ├── HubotSansExpanded-ExtraBold.ttf
│ │ │ ├── HubotSansExpanded-ExtraLight.ttf
│ │ │ ├── HubotSansExpanded-SemiBold.ttf
│ │ │ ├── HubotSansCondensed-BlackItalic.ttf
│ │ │ ├── HubotSansCondensed-BoldItalic.ttf
│ │ │ ├── HubotSansCondensed-ExtraLight.ttf
│ │ │ ├── HubotSansCondensed-LightItalic.ttf
│ │ │ ├── HubotSansExpanded-BlackItalic.ttf
│ │ │ ├── HubotSansExpanded-LightItalic.ttf
│ │ │ ├── HubotSansExpanded-MediumItalic.ttf
│ │ │ ├── HubotSansCondensed-MediumItalic.ttf
│ │ │ ├── HubotSansCondensed-SemiBoldItalic.ttf
│ │ │ ├── HubotSansExpanded-ExtraBoldItalic.ttf
│ │ │ ├── HubotSansExpanded-SemiBoldItalic.ttf
│ │ │ ├── HubotSansCondensed-ExtraBoldItalic.ttf
│ │ │ ├── HubotSansCondensed-ExtraLightItalic.ttf
│ │ │ └── HubotSansExpanded-ExtraLightItalic.ttf
│ │ └── WOFF2
│ │ │ ├── HubotSans-Bold.woff2
│ │ │ ├── HubotSans-Black.woff2
│ │ │ ├── HubotSans-Italic.woff2
│ │ │ ├── HubotSans-Light.woff2
│ │ │ ├── HubotSans-Medium.woff2
│ │ │ ├── HubotSans-ExtraBold.woff2
│ │ │ ├── HubotSans-Regular.woff2
│ │ │ ├── HubotSans-SemiBold.woff2
│ │ │ ├── HubotSans-BlackItalic.woff2
│ │ │ ├── HubotSans-BoldItalic.woff2
│ │ │ ├── HubotSans-ExtraLight.woff2
│ │ │ ├── HubotSans-LightItalic.woff2
│ │ │ ├── HubotSans-MediumItalic.woff2
│ │ │ ├── HubotSans-SemiBoldItalic.woff2
│ │ │ ├── HubotSansCondensed-Black.woff2
│ │ │ ├── HubotSansCondensed-Bold.woff2
│ │ │ ├── HubotSansCondensed-Light.woff2
│ │ │ ├── HubotSansExpanded-Black.woff2
│ │ │ ├── HubotSansExpanded-Bold.woff2
│ │ │ ├── HubotSansExpanded-Italic.woff2
│ │ │ ├── HubotSansExpanded-Light.woff2
│ │ │ ├── HubotSansExpanded-Medium.woff2
│ │ │ ├── HubotSans-ExtraBoldItalic.woff2
│ │ │ ├── HubotSans-ExtraLightItalic.woff2
│ │ │ ├── HubotSansCondensed-Italic.woff2
│ │ │ ├── HubotSansCondensed-Medium.woff2
│ │ │ ├── HubotSansCondensed-Regular.woff2
│ │ │ ├── HubotSansExpanded-Regular.woff2
│ │ │ ├── HubotSansExpanded-SemiBold.woff2
│ │ │ ├── HubotSans[slnt,wdth,wght].woff2
│ │ │ ├── HubotSansCondensed-BoldItalic.woff2
│ │ │ ├── HubotSansCondensed-ExtraBold.woff2
│ │ │ ├── HubotSansCondensed-ExtraLight.woff2
│ │ │ ├── HubotSansCondensed-SemiBold.woff2
│ │ │ ├── HubotSansExpanded-BlackItalic.woff2
│ │ │ ├── HubotSansExpanded-BoldItalic.woff2
│ │ │ ├── HubotSansExpanded-ExtraBold.woff2
│ │ │ ├── HubotSansExpanded-ExtraLight.woff2
│ │ │ ├── HubotSansExpanded-LightItalic.woff2
│ │ │ ├── HubotSansCondensed-BlackItalic.woff2
│ │ │ ├── HubotSansCondensed-LightItalic.woff2
│ │ │ ├── HubotSansCondensed-MediumItalic.woff2
│ │ │ ├── HubotSansExpanded-MediumItalic.woff2
│ │ │ ├── HubotSansCondensed-ExtraBoldItalic.woff2
│ │ │ ├── HubotSansCondensed-SemiBoldItalic.woff2
│ │ │ ├── HubotSansExpanded-ExtraBoldItalic.woff2
│ │ │ ├── HubotSansExpanded-ExtraLightItalic.woff2
│ │ │ ├── HubotSansExpanded-SemiBoldItalic.woff2
│ │ │ └── HubotSansCondensed-ExtraLightItalic.woff2
│ └── Inter-VariableFont_slnt,wght.ttf
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── assets
│ ├── images
│ │ ├── vercel.svg
│ │ ├── background-dots.svg
│ │ ├── netlify.svg
│ │ ├── github.svg
│ │ ├── docker.svg
│ │ └── swagger.svg
│ └── badges
│ │ ├── webcheck.svg
│ │ ├── sponsor.svg
│ │ └── github.svg
├── security.txt
├── manifest.json
├── placeholder.html
├── error.html
└── index.html
├── svelte.config.js
├── docker-compose.yml
├── fly.toml
├── vite.config.js
├── api
├── headers.js
├── get-ip.js
├── redirects.js
├── quality.js
├── trace-route.js
├── tech-stack.js
├── http-security.js
├── tls.js
├── rank.js
├── txt-records.js
├── features.js
├── ssl.js
├── dns-server.js
├── carbon.js
├── status.js
├── sitemap.js
├── dnssec.js
├── _common
│ └── aws-webpack.config.js
├── hsts.js
├── cookies.js
├── robots-txt.js
├── dns.js
├── legacy-rank.js
└── linked-pages.js
├── vercel.json
├── tsconfig.json
├── LICENSE
├── .gitignore
├── .env
└── netlify.toml
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [lissy93]
2 |
--------------------------------------------------------------------------------
/src/web-check-live/typings/file-types.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.ttf"
2 |
--------------------------------------------------------------------------------
/public/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/banner.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/web-check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/web-check.png
--------------------------------------------------------------------------------
/src/web-check-live/typings/react-simple-maps.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'react-simple-maps';
2 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/favicon-32x32.png
--------------------------------------------------------------------------------
/.github/web-check-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/web-check-logo.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/fonts/Inter-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-Bold.ttf
--------------------------------------------------------------------------------
/public/fonts/Inter-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-Thin.ttf
--------------------------------------------------------------------------------
/src/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/public/fonts/Inter-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-Black.ttf
--------------------------------------------------------------------------------
/public/fonts/Inter-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-Light.ttf
--------------------------------------------------------------------------------
/public/fonts/Inter-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-Medium.ttf
--------------------------------------------------------------------------------
/public/fonts/Inter-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-Regular.ttf
--------------------------------------------------------------------------------
/public/fonts/Inter-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-ExtraBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Inter-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-SemiBold.ttf
--------------------------------------------------------------------------------
/public/fonts/PTMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/PTMono-Regular.ttf
--------------------------------------------------------------------------------
/.github/screenshots/tiles/dns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/dns.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/hosts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/hosts.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/hsts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/hsts.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/ports.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/ports.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/ssl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/ssl.png
--------------------------------------------------------------------------------
/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/public/fonts/Inter-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-ExtraLight.ttf
--------------------------------------------------------------------------------
/.github/screenshots/tiles/carbon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/carbon.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/cookies.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/cookies.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/dnssec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/dnssec.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/domain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/domain.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/headers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/headers.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/quality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/quality.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/ranking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/ranking.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/robots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/robots.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/server.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/sitemap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/sitemap.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/status.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/threats.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/threats.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/archives.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/archives.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/dns-server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/dns-server.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/features.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/features.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/firewall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/firewall.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/location.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/redirects.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/redirects.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/screenshot.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/tech-stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/tech-stack.png
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/Hubot-Sans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/Hubot-Sans.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/Hubot-Sans.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/Hubot-Sans.woff2
--------------------------------------------------------------------------------
/.github/screenshots/tiles/block-lists.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/block-lists.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/email-config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/email-config.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/linked-pages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/linked-pages.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/security-txt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/security-txt.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/social-tags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/social-tags.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/trace-route.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/trace-route.png
--------------------------------------------------------------------------------
/.github/screenshots/tiles/txt-records.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/txt-records.png
--------------------------------------------------------------------------------
/svelte.config.js:
--------------------------------------------------------------------------------
1 | import { vitePreprocess } from '@astrojs/svelte';
2 |
3 | export default {
4 | preprocess: vitePreprocess(),
5 | }
6 |
--------------------------------------------------------------------------------
/.github/screenshots/tiles/http-security.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/http-security.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot1.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot2.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot3.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot4.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot5.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot6.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot7.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot8.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot9.png
--------------------------------------------------------------------------------
/public/fonts/Inter-VariableFont_slnt,wght.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Inter-VariableFont_slnt,wght.ttf
--------------------------------------------------------------------------------
/.github/screenshots/tiles/tls-cipher-suites.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/tls-cipher-suites.png
--------------------------------------------------------------------------------
/.github/screenshots/web-check-screenshot10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/web-check-screenshot10.png
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-Black.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-Black.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-Bold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-Light.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-Black.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-Bold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-Light.ttf
--------------------------------------------------------------------------------
/.github/screenshots/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/.github/screenshots/tiles/tls-security-config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/tls-security-config.png
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-Italic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-Medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-Medium.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-Regular.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-Italic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-Medium.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-Regular.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-Bold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-BoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-BoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLight.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLight.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-Black.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-Black.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-Italic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-Light.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-Medium.woff2
--------------------------------------------------------------------------------
/.github/screenshots/tiles/tls-handshake-simulation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/.github/screenshots/tiles/tls-handshake-simulation.png
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-BlackItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-BlackItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-LightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-LightItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-MediumItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-MediumItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Bold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Black.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Black.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Bold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Bold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Light.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-BlackItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-LightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-MediumItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Bold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Black.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Bold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Light.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-Regular.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Black.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Black.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Italic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Light.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Medium.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Italic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Italic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Medium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Medium.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Regular.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Black.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Italic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Light.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Medium.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Italic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Medium.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Regular.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-BlackItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-BlackItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-BoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLight.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLight.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-LightItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLightItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Regular.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLight.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBold.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Regular.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLight.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-MediumItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-MediumItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Black.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Black.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Bold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Light.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Black.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Black.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Bold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Italic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Light.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Medium.woff2
--------------------------------------------------------------------------------
/public/assets/images/vercel.svg:
--------------------------------------------------------------------------------
1 | Vercel
2 |
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BlackItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BlackItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLight.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-LightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-LightItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BlackItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BlackItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-LightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-LightItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-MediumItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-MediumItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BlackItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLight.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-LightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BlackItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-LightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-MediumItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLightItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Italic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Medium.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Medium.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Regular.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Regular.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSans[slnt,wdth,wght].woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSans[slnt,wdth,wght].woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-MediumItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-MediumItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-MediumItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLight.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLight.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BlackItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BlackItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBold.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLight.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLight.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-LightItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBoldItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLightItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLightItalic.otf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BlackItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BlackItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-LightItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-MediumItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-MediumItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-MediumItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-MediumItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLightItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBoldItalic.woff2
--------------------------------------------------------------------------------
/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lissy93/web-check/HEAD/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLightItalic.woff2
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.9'
2 | services:
3 | web-check:
4 | container_name: Web-Check
5 | image: lissy93/web-check
6 | ports:
7 | - 3000:3000
8 | restart: unless-stopped
9 |
--------------------------------------------------------------------------------
/public/security.txt:
--------------------------------------------------------------------------------
1 | Contact: mailto:security@as93.net
2 | Contact: mailto:alicia@omg.lol
3 | Expires: 2024-12-31T23:59:00.000Z
4 | Encryption: https://keybase.io/aliciasykes/pgp_keys.asc?fingerprint=0688f8d34587d954e9e51fb8fedb68f55c0283a7
5 | Preferred-Languages: en
6 | Canonical: /security.txt
7 |
--------------------------------------------------------------------------------
/fly.toml:
--------------------------------------------------------------------------------
1 | app = 'web-check'
2 | primary_region = 'lhr'
3 |
4 | [build]
5 |
6 | [http_service]
7 | internal_port = 3000
8 | force_https = true
9 | auto_stop_machines = true
10 | auto_start_machines = true
11 | min_machines_running = 0
12 | processes = ['app']
13 |
14 | [[vm]]
15 | memory = '1gb'
16 | cpu_kind = 'shared'
17 | cpus = 1
18 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | // vite.config.js
2 | import { defineConfig } from 'vite';
3 | import react from '@vitejs/plugin-react';
4 |
5 | export default defineConfig({
6 | plugins: [
7 | react({
8 | jsxImportSource: '@emotion/react',
9 | babel: {
10 | plugins: ['babel-plugin-styled-components'],
11 | },
12 | }),
13 | ],
14 | });
15 |
--------------------------------------------------------------------------------
/src/web-check-live/main.tsx:
--------------------------------------------------------------------------------
1 | import { BrowserRouter } from "react-router-dom";
2 | import { StaticRouter } from "react-router-dom/server";
3 | import App from "./App.tsx";
4 |
5 | export default ({ pathname }: { pathname: string }) => (
6 | import.meta.env.SSR
7 | ?
8 | :
9 | )
10 |
--------------------------------------------------------------------------------
/public/assets/images/background-dots.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Web Check",
3 | "name": "Lissy93/Web-Check",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "apple-touch-icon.png",
12 | "type": "image/png",
13 | "sizes": "180x180"
14 | }
15 | ],
16 | "start_url": ".",
17 | "display": "standalone",
18 | "theme_color": "#9fef00",
19 | "background_color": "#141d2b"
20 | }
21 |
--------------------------------------------------------------------------------
/.github/workflows/mirror.yml:
--------------------------------------------------------------------------------
1 | # Pushes the contents of the repo to the Codeberg mirror
2 | name: 🪞 Mirror to Codeberg
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | - cron: '30 0 * * 0'
7 | jobs:
8 | codeberg:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v4
12 | with: { fetch-depth: 0 }
13 | - uses: pixta-dev/repository-mirroring-action@v1
14 | with:
15 | target_repo_url: git@codeberg.org:alicia/web-check.git
16 | ssh_private_key: ${{ secrets.CODEBERG_SSH }}
17 |
--------------------------------------------------------------------------------
/api/headers.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import middleware from './_common/middleware.js';
3 |
4 | const headersHandler = async (url, event, context) => {
5 | try {
6 | const response = await axios.get(url, {
7 | validateStatus: function (status) {
8 | return status >= 200 && status < 600; // Resolve only if the status code is less than 600
9 | },
10 | });
11 |
12 | return response.headers;
13 | } catch (error) {
14 | throw new Error(error.message);
15 | }
16 | };
17 |
18 | export const handler = middleware(headersHandler);
19 | export default handler;
20 |
--------------------------------------------------------------------------------
/src/web-check-live/styles/colors.ts:
--------------------------------------------------------------------------------
1 |
2 | const colors = {
3 | primary: '#c1fb41',
4 | primaryLighter: '#cff97a',
5 | textColor: '#ffffff',
6 | textColorSecondary: '#a4b1cd',
7 | background: '#141517',
8 | backgroundDarker: '#000000',
9 | backgroundLighter: '#242525',
10 | bgShadowColor: '#101010',
11 | fgShadowColor: '#3f550e',
12 | primaryTransparent: '#9fef0012',
13 |
14 | // Action Colors
15 | info: '#04e4f4',
16 | success: '#20e253',
17 | warning: '#f6f000',
18 | error: '#fca016',
19 | danger: '#f80363',
20 | neutral: '#272f4d',
21 | };
22 |
23 | export default colors;
24 |
--------------------------------------------------------------------------------
/src/web-check-live/styles/typography.ts:
--------------------------------------------------------------------------------
1 |
2 | export const TextSizes = {
3 | xSmall: '0.75rem',
4 | small: '1rem',
5 | medium: '1.5rem',
6 | large: '2rem',
7 | xLarge: '3rem',
8 | xxLarge: '4rem',
9 | };
10 |
11 | export const TextReset = `
12 | font-size: ${TextSizes.small};
13 | font-family: PTMono, Helvetica, Arial, sans-serif;
14 | font-weight: 400;
15 | font-style: normal;
16 | font-stretch: normal;
17 | line-height: normal;
18 | letter-spacing: 0.38px;
19 | margin: 0;
20 | padding: 0;
21 | -webkit-font-smoothing: antialiased;
22 | -moz-osx-font-smoothing: grayscale;
23 | `;
24 |
--------------------------------------------------------------------------------
/src/web-check-live/styles/globals.tsx:
--------------------------------------------------------------------------------
1 | import { Global, css } from '@emotion/react';
2 |
3 | const GlobalStyles = () => (
4 |
21 | );
22 |
23 | export default GlobalStyles;
24 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "routes": [
4 | {
5 | "src": "/api/(.*)",
6 | "dest": "/api/$1.js"
7 | }
8 | ],
9 | "functions": {
10 | "api/*.js": {
11 | "maxDuration": 10
12 | }
13 | },
14 | "env": {
15 | "PLATFORM": "vercel",
16 | "CI": "false",
17 | "CHROME_PATH": "/usr/bin/chromium",
18 | "NODE_VERSION": "21.x",
19 | "GOOGLE_CLOUD_API_KEY": "",
20 | "BUILT_WITH_API_KEY": "",
21 | "REACT_APP_SHODAN_API_KEY": "",
22 | "REACT_APP_WHO_API_KEY": ""
23 | },
24 | "build": {
25 | "env": {
26 | "PLATFORM": "vercel"
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/api/get-ip.js:
--------------------------------------------------------------------------------
1 | import dns from 'dns';
2 | import middleware from './_common/middleware.js';
3 |
4 | const lookupAsync = (address) => {
5 | return new Promise((resolve, reject) => {
6 | dns.lookup(address, (err, ip, family) => {
7 | if (err) {
8 | reject(err);
9 | } else {
10 | resolve({ ip, family });
11 | }
12 | });
13 | });
14 | };
15 |
16 | const ipHandler = async (url) => {
17 | const address = url.replaceAll('https://', '').replaceAll('http://', '');
18 | return await lookupAsync(address);
19 | };
20 |
21 |
22 | export const handler = middleware(ipHandler);
23 | export default handler;
24 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/Flag.tsx:
--------------------------------------------------------------------------------
1 | interface Props {
2 | countryCode: string,
3 | width: number,
4 | };
5 |
6 | const Flag = ({ countryCode, width }: Props): JSX.Element => {
7 |
8 | const getFlagUrl = (code: string, w: number = 64) => {
9 | const protocol = 'https';
10 | const cdn = 'flagcdn.com';
11 | const dimensions = `${width}x${width * 0.75}`;
12 | const country = countryCode.toLowerCase();
13 | const ext = 'png';
14 | return `${protocol}://${cdn}/${dimensions}/${country}.${ext}`;
15 | };
16 |
17 | return ( );
18 | }
19 |
20 | export default Flag;
21 |
--------------------------------------------------------------------------------
/public/assets/images/netlify.svg:
--------------------------------------------------------------------------------
1 | Netlify
2 |
--------------------------------------------------------------------------------
/src/web-check-live/utils/get-keys.ts:
--------------------------------------------------------------------------------
1 |
2 | const keys = {
3 | shodan: import.meta.env.REACT_APP_SHODAN_API_KEY || "default_value_if_not_set",
4 | whoApi: import.meta.env.REACT_APP_WHO_API_KEY || "default_value_if_not_set",
5 | disableEverything: import.meta.env.VITE_DISABLE_EVERYTHING === 'true',
6 | };
7 | // const keys = process && process.env ? {
8 | // shodan: process.env.REACT_APP_SHODAN_API_KEY,
9 | // whoApi: process.env.REACT_APP_WHO_API_KEY,
10 | // } : {
11 | // shodan: import.meta.env.REACT_APP_SHODAN_API_KEY || "default_value_if_not_set",
12 | // whoApi: import.meta.env.REACT_APP_WHO_API_KEY || "default_value_if_not_set",
13 | // };
14 |
15 | export default keys;
16 |
--------------------------------------------------------------------------------
/src/components/homepage/TempDisabled.astro:
--------------------------------------------------------------------------------
1 |
2 |
3 | ⚠️ Web Check is temporarily disabled due to excess demand and associated costs.
4 | We apologize for any inconvenience and are working on a solution.
5 |
6 |
7 |
8 |
28 |
--------------------------------------------------------------------------------
/api/redirects.js:
--------------------------------------------------------------------------------
1 | import got from 'got';
2 | import middleware from './_common/middleware.js';
3 |
4 | const redirectsHandler = async (url) => {
5 | const redirects = [url];
6 | try {
7 | await got(url, {
8 | followRedirect: true,
9 | maxRedirects: 12,
10 | hooks: {
11 | beforeRedirect: [
12 | (options, response) => {
13 | redirects.push(response.headers.location);
14 | },
15 | ],
16 | },
17 | });
18 |
19 | return {
20 | redirects: redirects,
21 | };
22 | } catch (error) {
23 | throw new Error(`Error: ${error.message}`);
24 | }
25 | };
26 |
27 | export const handler = middleware(redirectsHandler);
28 | export default handler;
29 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Headers.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import Row from 'web-check-live/components/Form/Row';
3 | import type { ReactNode } from 'react';
4 |
5 | const HeadersCard = (props: { data: any, title: string, actionButtons: ReactNode }): JSX.Element => {
6 | const headers = props.data;
7 | return (
8 |
9 | {
10 | Object.keys(headers).map((header: string, index: number) => {
11 | return (
12 |
13 | )
14 | })
15 | }
16 |
17 | );
18 | }
19 |
20 | export default HeadersCard;
21 |
--------------------------------------------------------------------------------
/api/quality.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import middleware from './_common/middleware.js';
3 |
4 | const qualityHandler = async (url, event, context) => {
5 | const apiKey = process.env.GOOGLE_CLOUD_API_KEY;
6 |
7 | if (!apiKey) {
8 | throw new Error(
9 | 'Missing Google API. You need to set the `GOOGLE_CLOUD_API_KEY` environment variable'
10 | );
11 | }
12 |
13 | const endpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?`
14 | + `url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY`
15 | + `&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile`
16 | + `&key=${apiKey}`;
17 |
18 | return (await axios.get(endpoint)).data;
19 | };
20 |
21 | export const handler = middleware(qualityHandler);
22 | export default handler;
23 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/BlockLists.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 |
5 | const BlockListsCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
6 | const blockLists = props.data.blocklists;
7 | return (
8 |
9 | { blockLists.map((blocklist: any, blockIndex: number) => (
10 |
16 | ))}
17 |
18 | );
19 | }
20 |
21 | export default BlockListsCard;
22 |
--------------------------------------------------------------------------------
/public/assets/images/github.svg:
--------------------------------------------------------------------------------
1 | GitHub
2 |
--------------------------------------------------------------------------------
/src/components/homepage/Features.astro:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | import Icon from '@components/molecules/Icon.svelte';
4 |
5 | interface Props {
6 | supportedChecks: string[];
7 | }
8 |
9 | const { supportedChecks } = Astro.props;
10 |
11 | ---
12 |
13 |
14 | {supportedChecks.map((check) => (
15 |
16 |
17 | {check}
18 |
19 | ))}
20 | More
21 |
22 |
23 |
41 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Screenshot.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 |
3 | const cardStyles = `
4 | overflow: auto;
5 | max-height: 50rem;
6 | grid-row: span 2;
7 | img {
8 | border-radius: 6px;
9 | width: 100%;
10 | margin 0.5rem 0;;
11 | }
12 | `;
13 |
14 | const ScreenshotCard = (props: { data: { image?: string, data?: string, }, title: string, actionButtons: any }): JSX.Element => {
15 | const screenshot = props.data;
16 | return (
17 |
18 | { screenshot.image && }
19 | { (!screenshot.image && screenshot.data) && }
20 |
21 | );
22 | }
23 |
24 | export default ScreenshotCard;
25 |
--------------------------------------------------------------------------------
/src/layouts/Base.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import { ViewTransitions } from 'astro:transitions'
3 | import MetaTags from '@layouts/MetaTags.astro';
4 |
5 | import '@styles/typography.scss';
6 | import '@styles/global.scss';
7 | import '@styles/colors.scss';
8 | import '@styles/media-queries.scss';
9 |
10 | interface Props {
11 | title?: string;
12 | description?: string;
13 | keywords?: string;
14 | customSchemaJson?: any;
15 | breadcrumbs?: Array<{
16 | name: string;
17 | item: string;
18 | }>
19 | }
20 |
21 | ---
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/OpenPorts.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import Row from 'web-check-live/components/Form/Row';
3 |
4 | const cardStyles = `
5 | small { margin-top: 1rem; opacity: 0.5; }
6 | `;
7 |
8 | const OpenPortsCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
9 | const portData = props.data;
10 | return (
11 |
12 | {portData.openPorts.map((port: any) => (
13 |
14 | {port}
15 |
16 | )
17 | )}
18 |
19 |
20 | Unable to establish connections to:
21 | {portData.failedPorts.join(', ')}
22 |
23 |
24 | );
25 | }
26 |
27 | export default OpenPortsCard;
28 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/TxtRecords.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 |
5 | const cardStyles = `
6 | grid-column: span 2;
7 | span.val { max-width: 32rem !important; }
8 | span { overflow: hidden; }
9 | `;
10 |
11 | const TxtRecordCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
12 | const records = props.data;
13 | return (
14 |
15 | { !records &&
}
16 | {Object.keys(records).map((recordName: any, index: number) => {
17 | return (
18 |
19 | );
20 | })}
21 |
22 | );
23 | }
24 |
25 | export default TxtRecordCard;
26 |
--------------------------------------------------------------------------------
/src/web-check-live/styles/dimensions.ts:
--------------------------------------------------------------------------------
1 | export type InputSize = 'small' | 'medium' | 'large';
2 |
3 | export const applySize = (inputSize?: InputSize) => {
4 | const sizeSpecificStyles = {
5 | small: `
6 | font-size: 1rem;
7 | border-radius: 0.25rem;
8 | padding: 0.5rem 1rem;
9 | margin: 0.5rem;
10 | `,
11 | medium: `
12 | font-size: 1.5rem;
13 | border-radius: 0.25rem;
14 | padding: 0.75rem 1.5rem;
15 | margin: 0.5rem;
16 | `,
17 | large: `
18 | font-size: 2rem;
19 | border-radius: 0.25rem;
20 | padding: 1rem 1.75rem;
21 | margin: 0.5rem;
22 | `,
23 | };
24 | switch (inputSize) {
25 | case 'small': return sizeSpecificStyles.small;
26 | case 'medium': return sizeSpecificStyles.medium;
27 | case 'large': return sizeSpecificStyles.large;
28 | default: return sizeSpecificStyles.small;
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Firewall.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 |
5 | const Note = styled.small`
6 | opacity: 0.5;
7 | display: block;
8 | margin-top: 0.5rem;
9 | `;
10 |
11 | const FirewallCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
12 | const data = props.data;
13 | return (
14 |
15 |
16 | { data.waf &&
}
17 | { !data.hasWaf && (
18 | *The domain may be protected with a proprietary or custom WAF which we were unable to identify automatically
19 | ) }
20 |
21 | );
22 | }
23 |
24 | export default FirewallCard;
25 |
--------------------------------------------------------------------------------
/api/trace-route.js:
--------------------------------------------------------------------------------
1 | import url from 'url';
2 | import traceroute from 'traceroute';
3 | import middleware from './_common/middleware.js';
4 |
5 | const traceRouteHandler = async (urlString, context) => {
6 | // Parse the URL and get the hostname
7 | const urlObject = url.parse(urlString);
8 | const host = urlObject.hostname;
9 |
10 | if (!host) {
11 | throw new Error('Invalid URL provided');
12 | }
13 |
14 | // Traceroute with callback
15 | const result = await new Promise((resolve, reject) => {
16 | traceroute.trace(host, (err, hops) => {
17 | if (err || !hops) {
18 | reject(err || new Error('No hops found'));
19 | } else {
20 | resolve(hops);
21 | }
22 | });
23 | });
24 |
25 | return {
26 | message: "Traceroute completed!",
27 | result,
28 | };
29 | };
30 |
31 | export const handler = middleware(traceRouteHandler);
32 | export default handler;
33 |
--------------------------------------------------------------------------------
/api/tech-stack.js:
--------------------------------------------------------------------------------
1 | import Wappalyzer from 'wappalyzer';
2 | import middleware from './_common/middleware.js';
3 |
4 | const techStackHandler = async (url) => {
5 | const options = {};
6 |
7 | const wappalyzer = new Wappalyzer(options);
8 |
9 | try {
10 | await wappalyzer.init();
11 | const headers = {};
12 | const storage = {
13 | local: {},
14 | session: {},
15 | };
16 | const site = await wappalyzer.open(url, headers, storage);
17 | const results = await site.analyze();
18 |
19 | if (!results.technologies || results.technologies.length === 0) {
20 | throw new Error('Unable to find any technologies for site');
21 | }
22 | return results;
23 | } catch (error) {
24 | throw new Error(error.message);
25 | } finally {
26 | await wappalyzer.destroy();
27 | }
28 | };
29 |
30 | export const handler = middleware(techStackHandler);
31 | export default handler;
32 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/HttpSecurity.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import Row from 'web-check-live/components/Form/Row';
3 |
4 | const HttpSecurityCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
5 | const data = props.data;
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
17 | export default HttpSecurityCard;
18 |
--------------------------------------------------------------------------------
/api/http-security.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import middleware from './_common/middleware.js';
3 |
4 | const httpsSecHandler = async (url) => {
5 | const fullUrl = url.startsWith('http') ? url : `http://${url}`;
6 |
7 | try {
8 | const response = await axios.get(fullUrl);
9 | const headers = response.headers;
10 | return {
11 | strictTransportPolicy: headers['strict-transport-security'] ? true : false,
12 | xFrameOptions: headers['x-frame-options'] ? true : false,
13 | xContentTypeOptions: headers['x-content-type-options'] ? true : false,
14 | xXSSProtection: headers['x-xss-protection'] ? true : false,
15 | contentSecurityPolicy: headers['content-security-policy'] ? true : false,
16 | }
17 | } catch (error) {
18 | return {
19 | statusCode: 500,
20 | body: JSON.stringify({ error: error.message }),
21 | };
22 | }
23 | };
24 |
25 | export const handler = middleware(httpsSecHandler);
26 | export default handler;
27 |
--------------------------------------------------------------------------------
/api/tls.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import middleware from './_common/middleware.js';
3 |
4 | const MOZILLA_TLS_OBSERVATORY_API = 'https://tls-observatory.services.mozilla.com/api/v1';
5 |
6 | const tlsHandler = async (url) => {
7 | try {
8 | const domain = new URL(url).hostname;
9 | const scanResponse = await axios.post(`${MOZILLA_TLS_OBSERVATORY_API}/scan?target=${domain}`);
10 | const scanId = scanResponse.data.scan_id;
11 |
12 | if (typeof scanId !== 'number') {
13 | return {
14 | statusCode: 500,
15 | body: { error: 'Failed to get scan_id from TLS Observatory' },
16 | };
17 | }
18 | const resultResponse = await axios.get(`${MOZILLA_TLS_OBSERVATORY_API}/results?id=${scanId}`);
19 | return {
20 | statusCode: 200,
21 | body: resultResponse.data,
22 | };
23 | } catch (error) {
24 | return { error: error.message };
25 | }
26 | };
27 |
28 | export const handler = middleware(tlsHandler);
29 | export default handler;
30 |
--------------------------------------------------------------------------------
/api/rank.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import middleware from './_common/middleware.js';
3 |
4 | const rankHandler = async (url) => {
5 | const domain = url ? new URL(url).hostname : null;
6 | if (!domain) throw new Error('Invalid URL');
7 |
8 | try {
9 | const auth = process.env.TRANCO_API_KEY ? // Auth is optional.
10 | { auth: { username: process.env.TRANCO_USERNAME, password: process.env.TRANCO_API_KEY } }
11 | : {};
12 | const response = await axios.get(
13 | `https://tranco-list.eu/api/ranks/domain/${domain}`, { timeout: 5000 }, auth,
14 | );
15 | if (!response.data || !response.data.ranks || response.data.ranks.length === 0) {
16 | return { skipped: `Skipping, as ${domain} isn't ranked in the top 100 million sites yet.`};
17 | }
18 | return response.data;
19 | } catch (error) {
20 | return { error: `Unable to fetch rank, ${error.message}` };
21 | }
22 | };
23 |
24 | export const handler = middleware(rankHandler);
25 | export default handler;
26 |
27 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Form/Nav.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import type { ReactNode } from 'react';
3 | import { Link } from 'react-router-dom';
4 |
5 | import { StyledCard } from 'web-check-live/components/Form/Card';
6 | import Heading from 'web-check-live/components/Form/Heading';
7 | import colors from 'web-check-live/styles/colors';
8 |
9 | const Header = styled(StyledCard)`
10 | margin: 1rem auto;
11 | display: flex;
12 | flex-wrap: wrap;
13 | align-items: baseline;
14 | justify-content: space-between;
15 | padding: 0.5rem 1rem;
16 | align-items: center;
17 | width: 95vw;
18 | `;
19 |
20 | const Nav = (props: { children?: ReactNode}) => {
21 | return (
22 |
23 |
24 |
25 | Web Check
26 |
27 | {props.children && props.children}
28 |
29 | );
30 | };
31 |
32 | export default Nav;
33 |
--------------------------------------------------------------------------------
/src/styles/colors.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --primary: #d6fb41;
3 | --primary-lighter: #cff97a;
4 | --text-color: #ffffff;
5 | --text-color-secondary: #ffffffb6;
6 | --text-color-thirdly: #ffffff5b;
7 | --background: #111211;
8 | --background-darker: #111927;
9 | // --background-lighter: #1a2332;
10 | --background-lighter: #3A3B3A;
11 | --background-50: #11121180;
12 | --bg-shadow-color: #0f1620;
13 | --fg-shadow-color: #456602;
14 | --primary-transparent: #d6fb4130;
15 |
16 | // Action Colors
17 | --info: #04e4f4;
18 | --success: #20e253;
19 | --warning: #f6f000;
20 | --error: #fca016;
21 | --danger: #f80363;
22 | --neutral: #272f4d;
23 | }
24 |
25 | html[data-theme="light"] {
26 | --primary: #4a7700;
27 | --primary-lighter: #a4cf50;
28 | --text-color: #333333;
29 | --text-color-secondary: #57667e;
30 | --background: #ffffff;
31 | --background-darker: #f0f0f0;
32 | --background-lighter: #fafafa;
33 | --bg-shadow-color: #e0e0e0;
34 | --fg-shadow-color: #678800;
35 | --primary-transparent: #4a770033;
36 | }
37 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/ServerInfo.tsx:
--------------------------------------------------------------------------------
1 | import type { ServerInfo } from 'web-check-live/utils/result-processor';
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 |
5 | const ServerInfoCard = (props: { data: ServerInfo, title: string, actionButtons: any }): JSX.Element => {
6 | const info = props.data;
7 | const { org, asn, isp, os, ports, ip, loc, type } = info;
8 | return (
9 |
10 | { org &&
}
11 | { (isp && isp !== org) &&
}
12 | { os &&
}
13 | { asn &&
}
14 | { ports &&
}
15 | { ip &&
}
16 | { type &&
}
17 | { loc &&
}
18 |
19 | );
20 | }
21 |
22 | export default ServerInfoCard;
23 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/RobotsTxt.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row, { type RowProps } from 'web-check-live/components/Form/Row';
4 |
5 | const cardStyles = `
6 | grid-row: span 2;
7 | .content {
8 | max-height: 50rem;
9 | overflow-y: auto;
10 | }
11 | `;
12 |
13 | const RobotsTxtCard = ( props: { data: { robots: RowProps[]}, title: string, actionButtons: any}): JSX.Element => {
14 | const { data } = props;
15 | const robots = data?.robots || [];
16 |
17 | return (
18 |
19 |
20 | {
21 | robots.length === 0 &&
No crawl rules found.
22 | }
23 | {
24 | robots.map((row: RowProps, index: number) => {
25 | return (
26 |
|
27 | )
28 | })
29 | }
30 |
31 |
32 | );
33 | }
34 |
35 | export default RobotsTxtCard;
36 |
--------------------------------------------------------------------------------
/src/web-check-live/App.tsx:
--------------------------------------------------------------------------------
1 | import { Routes, Route, Outlet } from 'react-router-dom';
2 |
3 | import Home from 'web-check-live/views/Home.tsx';
4 | import Results from 'web-check-live/views/Results.tsx';
5 | import About from 'web-check-live/views/About.tsx';
6 | import NotFound from 'web-check-live/views/NotFound.tsx';
7 |
8 | import ErrorBoundary from 'web-check-live/components/boundaries/PageError.tsx';
9 | import GlobalStyles from './styles/globals.tsx';
10 |
11 | const Layout = () => {
12 | return (
13 | <>
14 |
15 |
16 | >
17 | );
18 | }
19 |
20 | export default function App() {
21 | return (
22 |
23 |
24 | }>
25 | } />
26 | } />
27 | } />
28 | } />
29 | } />
30 |
31 |
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/ServerStatus.tsx:
--------------------------------------------------------------------------------
1 |
2 | import colors from 'web-check-live/styles/colors';
3 | import { Card } from 'web-check-live/components/Form/Card';
4 | import Row from 'web-check-live/components/Form/Row';
5 |
6 | const cardStyles = `
7 | span.val {
8 | &.up { color: ${colors.success}; }
9 | &.down { color: ${colors.danger}; }
10 | }
11 | `;
12 |
13 | const ServerStatusCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
14 | const serverStatus = props.data;
15 | return (
16 |
17 |
18 | Is Up?
19 | { serverStatus.isUp ? ✅ Online : ❌ Offline }
20 |
21 |
22 | { serverStatus.responseTime &&
}
23 |
24 | );
25 | }
26 |
27 | export default ServerStatusCard;
28 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "module": "ES2020",
5 | "moduleResolution": "node",
6 | "allowImportingTsExtensions": true,
7 | "plugins": [
8 | {
9 | "name": "@astrojs/ts-plugin"
10 | },
11 | ],
12 | "lib": [
13 | "DOM",
14 | "DOM.Iterable",
15 | "ES2020"
16 | ],
17 | "allowJs": true,
18 | "skipLibCheck": true,
19 | "esModuleInterop": true,
20 | "allowSyntheticDefaultImports": true,
21 | "strict": true,
22 | "forceConsistentCasingInFileNames": true,
23 | "noFallthroughCasesInSwitch": true,
24 | "resolveJsonModule": true,
25 | "isolatedModules": true,
26 | "noEmit": true,
27 | "jsx": "react-jsx",
28 | "jsxImportSource": "react",
29 | "baseUrl": "src",
30 | "paths": {
31 | "@/*": ["*"],
32 | "@components/*": ["components/*"],
33 | "@layouts/*": ["layouts/*"],
34 | "@pages/*": ["pages/*"],
35 | "@styles/*": ["styles/*"],
36 | "@assets/*": ["assets/*"],
37 | }
38 | },
39 | "include": [
40 | "src"
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/api/txt-records.js:
--------------------------------------------------------------------------------
1 | import dns from 'dns/promises';
2 | import middleware from './_common/middleware.js';
3 |
4 | const txtRecordHandler = async (url, event, context) => {
5 | try {
6 | const parsedUrl = new URL(url);
7 |
8 | const txtRecords = await dns.resolveTxt(parsedUrl.hostname);
9 |
10 | // Parsing and formatting TXT records into a single object
11 | const readableTxtRecords = txtRecords.reduce((acc, recordArray) => {
12 | const recordObject = recordArray.reduce((recordAcc, recordString) => {
13 | const splitRecord = recordString.split('=');
14 | const key = splitRecord[0];
15 | const value = splitRecord.slice(1).join('=');
16 | return { ...recordAcc, [key]: value };
17 | }, {});
18 | return { ...acc, ...recordObject };
19 | }, {});
20 |
21 | return readableTxtRecords;
22 |
23 | } catch (error) {
24 | if (error.code === 'ERR_INVALID_URL') {
25 | throw new Error(`Invalid URL ${error}`);
26 | } else {
27 | throw error;
28 | }
29 | }
30 | };
31 |
32 | export const handler = middleware(txtRecordHandler);
33 | export default handler;
34 |
--------------------------------------------------------------------------------
/src/components/molecules/Icon.svelte:
--------------------------------------------------------------------------------
1 |
23 |
24 | {#if iconMap[name]}
25 |
29 | {/if}
30 |
31 |
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Alicia Sykes
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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ------------------------
2 | # ENVIRONMENT SETTINGS
3 | # ------------------------
4 | .env
5 |
6 | # ------------------------
7 | # PRODUCTION
8 | # ------------------------
9 | /build/
10 |
11 | # ------------------------
12 | # BUILT FILES
13 | # ------------------------
14 | dist/
15 | .vercel/
16 | .netlify/
17 | .webpack/
18 | .serverless/
19 | .astro/
20 |
21 | # ------------------------
22 | # DEPENDENCIES
23 | # ------------------------
24 | node_modules/
25 | .yarn/cache/
26 | .yarn/unplugged/
27 | .yarn/build-state.yml
28 | .yarn/install-state.gz
29 | .pnpm/
30 | .pnp.*
31 |
32 | # ------------------------
33 | # LOGS
34 | # ------------------------
35 | logs/
36 | *.log
37 | npm-debug.log*
38 | yarn-debug.log*
39 | yarn-error.log*
40 | lerna-debug.log*
41 | .pnpm-debug.log*
42 |
43 | # ------------------------
44 | # TESTING
45 | # ------------------------
46 | coverage/
47 | .nyc_output/
48 |
49 | # ------------------------
50 | # OS SPECIFIC
51 | # ------------------------
52 | .DS_Store
53 | Thumbs.db
54 |
55 | # ------------------------
56 | # EDITORS
57 | # ------------------------
58 | .idea/
59 | .vscode/
60 | *.swp
61 | *.swo
62 |
63 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | # Environmental Variables can be stored here
2 | # Be sure to uncomment any line you populate
3 | # Everything is optional, but some features won't work without external API access
4 |
5 | # API Keys for external services (backend)
6 | GOOGLE_CLOUD_API_KEY=''
7 | TORRENT_IP_API_KEY=''
8 | SECURITY_TRAILS_API_KEY=''
9 | BUILT_WITH_API_KEY=''
10 | URL_SCAN_API_KEY=''
11 | TRANCO_USERNAME=''
12 | TRANCO_API_KEY=''
13 | CLOUDMERSIVE_API_KEY=''
14 |
15 | # API Keys for external services (frontend)
16 | REACT_APP_SHODAN_API_KEY=''
17 | REACT_APP_WHO_API_KEY=''
18 |
19 | # Configuration settings
20 | # CHROME_PATH='/usr/bin/chromium' # The path the the Chromium executable
21 | # PORT='3000' # Port to serve the API, when running server.js
22 | # DISABLE_GUI='false' # Disable the GUI, and only serve the API
23 | # API_TIMEOUT_LIMIT='10000' # The timeout limit for API requests, in milliseconds
24 | # API_CORS_ORIGIN='*' # Enable CORS, by setting your allowed hostname(s) here
25 | # API_ENABLE_RATE_LIMIT='true' # Enable rate limiting for the API
26 | # REACT_APP_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote)
27 | # ENABLE_ANALYTICS='false' # Enable Plausible hit counter for the frontend
28 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/DnsRecords.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import Row, { ListRow } from 'web-check-live/components/Form/Row';
3 |
4 | const styles = `
5 | grid-row: span 2;
6 | .content {
7 | max-height: 50rem;
8 | overflow-x: hidden;
9 | overflow-y: auto;
10 | }
11 | `;
12 |
13 | const DnsRecordsCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
14 | const dnsRecords = props.data;
15 | return (
16 |
17 |
18 | { dnsRecords.A &&
}
19 | { dnsRecords.AAAA?.length > 0 && }
20 | { dnsRecords.MX?.length > 0 && }
21 | { dnsRecords.CNAME?.length > 0 && }
22 | { dnsRecords.NS?.length > 0 && }
23 | { dnsRecords.PTR?.length > 0 && }
24 | { dnsRecords.SOA?.length > 0 && }
25 |
26 |
27 | );
28 | }
29 |
30 | export default DnsRecordsCard;
31 |
--------------------------------------------------------------------------------
/src/web-check-live/styles/index.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'PTMono';
3 | src: url('/fonts/PTMono-Regular.ttf') format('truetype');
4 | font-weight: normal;
5 | font-style: normal;
6 | }
7 |
8 | html {
9 | scroll-behavior: smooth;
10 | }
11 |
12 | body {
13 | margin: 0;
14 | font-family: 'PTMono', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
15 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
16 | sans-serif;
17 | -webkit-font-smoothing: antialiased;
18 | -moz-osx-font-smoothing: grayscale;
19 | background: #141517;
20 | color: #fff;
21 | }
22 |
23 | code {
24 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
25 | monospace;
26 | }
27 | #fancy-background { color: var(--background, #141517); }
28 |
29 |
30 | ::selection {
31 | background: var(--primary, #d6fb41);
32 | color: var(--background, #141517);
33 | }
34 |
35 |
36 | svg.rsm-svg {
37 | background: #141517;
38 | border-radius: 6px;
39 | }
40 |
41 | :root {
42 | --toastify-color-dark: #111927 !important;
43 | --toastify-color-info: #04e4f4 !important;
44 | --toastify-color-success: #20e253 !important;
45 | --toastify-color-warning: #f6f000 !important;
46 | --toastify-color-error: #f80363 !important;
47 | }
48 |
49 | #fancy-background {
50 | position: absolute;
51 | }
52 |
--------------------------------------------------------------------------------
/src/components/scafold/Footer.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const repo = 'github.com/lissy93/web-check';
3 | const github = `https://${repo}`;
4 |
5 | const licenseText = 'MIT';
6 | const licenseLink = `${github}/blob/master/LICENSE`;
7 |
8 | const aboutLink = '/about';
9 | const projectName = 'Web Check';
10 |
11 | const authorName = 'Alicia Sykes';
12 | const authorLink = 'https://aliciasykes.com';
13 | const currentYear = new Date().getFullYear();
14 | ---
15 |
16 |
28 |
29 |
54 |
--------------------------------------------------------------------------------
/.github/workflows/credits.yml:
--------------------------------------------------------------------------------
1 | # Inserts list of community members into ./README.md
2 | name: 💓 Inserts Contributors & Sponsors
3 | on:
4 | workflow_dispatch: # Manual dispatch
5 | schedule:
6 | - cron: '45 1 * * 0' # At 01:45 on Sunday.
7 |
8 | jobs:
9 | # Job #1 - Fetches sponsors and inserts table into readme
10 | insert-sponsors:
11 | runs-on: ubuntu-latest
12 | name: Inserts Sponsors 💓
13 | steps:
14 | - name: Checkout
15 | uses: actions/checkout@v4
16 | - name: Updates readme with sponsors
17 | uses: JamesIves/github-sponsors-readme-action@v1
18 | with:
19 | token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
20 | file: .github/README.md
21 |
22 | # Job #2 - Fetches contributors and inserts table into readme
23 | insert-contributors:
24 | runs-on: ubuntu-latest
25 | name: Inserts Contributors 💓
26 | steps:
27 | - name: Updates readme with contributors
28 | uses: akhilmhdh/contributors-readme-action@v2.3.10
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }}
31 | with:
32 | image_size: 80
33 | readme_path: .github/README.md
34 | columns_per_row: 6
35 | commit_message: 'docs: Updates contributors list'
36 | committer_username: liss-bot
37 | committer_email: liss-bot@d0h.co
38 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Form/Card.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 |
3 | import { type ReactNode } from 'react';
4 | import ErrorBoundary from 'web-check-live/components/misc/ErrorBoundary';
5 | import Heading from 'web-check-live/components/Form/Heading';
6 | import colors from 'web-check-live/styles/colors';
7 |
8 | export const StyledCard = styled.section<{ styles?: string}>`
9 | background: ${colors.backgroundLighter};
10 | color: ${colors.textColor};
11 | box-shadow: 4px 4px 0px ${colors.bgShadowColor};
12 | border-radius: 8px;
13 | padding: 1rem;
14 | position: relative;
15 | margin 0.5rem;
16 | max-height: 64rem;
17 | overflow: auto;
18 | ${props => props.styles}
19 | `;
20 |
21 | interface CardProps {
22 | children: ReactNode;
23 | heading?: string,
24 | styles?: string;
25 | actionButtons?: ReactNode | undefined;
26 | };
27 |
28 | export const Card = (props: CardProps): JSX.Element => {
29 | const { children, heading, styles, actionButtons } = props;
30 | return (
31 |
32 |
33 | { actionButtons && actionButtons }
34 | { heading && {heading} }
35 | {children}
36 |
37 |
38 | );
39 | }
40 |
41 | export default StyledCard;
42 |
--------------------------------------------------------------------------------
/api/features.js:
--------------------------------------------------------------------------------
1 | import https from 'https';
2 | import middleware from './_common/middleware.js';
3 |
4 | const featuresHandler = async (url) => {
5 | const apiKey = process.env.BUILT_WITH_API_KEY;
6 |
7 | if (!url) {
8 | throw new Error('URL query parameter is required');
9 | }
10 |
11 | if (!apiKey) {
12 | throw new Error('Missing BuiltWith API key in environment variables');
13 | }
14 |
15 | const apiUrl = `https://api.builtwith.com/free1/api.json?KEY=${apiKey}&LOOKUP=${encodeURIComponent(url)}`;
16 |
17 | try {
18 | const response = await new Promise((resolve, reject) => {
19 | const req = https.get(apiUrl, res => {
20 | let data = '';
21 |
22 | res.on('data', chunk => {
23 | data += chunk;
24 | });
25 |
26 | res.on('end', () => {
27 | if (res.statusCode >= 200 && res.statusCode <= 299) {
28 | resolve(data);
29 | } else {
30 | reject(new Error(`Request failed with status code: ${res.statusCode}`));
31 | }
32 | });
33 | });
34 |
35 | req.on('error', error => {
36 | reject(error);
37 | });
38 |
39 | req.end();
40 | });
41 |
42 | return response;
43 | } catch (error) {
44 | throw new Error(`Error making request: ${error.message}`);
45 | }
46 | };
47 |
48 | export const handler = middleware(featuresHandler);
49 | export default handler;
50 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Redirects.tsx:
--------------------------------------------------------------------------------
1 | import colors from 'web-check-live/styles/colors';
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 |
5 | const cardStyles = `
6 | div {
7 | justify-content: flex-start;
8 | align-items: baseline;
9 | }
10 | .arrow-thing {
11 | color: ${colors.primary};
12 | font-size: 1.8rem;
13 | font-weight: bold;
14 | margin-right: 0.5rem;
15 | }
16 | .redirect-count {
17 | color: ${colors.textColorSecondary};
18 | margin: 0;
19 | }
20 | `;
21 |
22 | const RedirectsCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
23 | const redirects = props.data;
24 | return (
25 |
26 | { !redirects?.redirects.length &&
}
27 |
28 | Followed {redirects.redirects.length}{' '}
29 | redirect{redirects.redirects.length === 1 ? '' : 's'} when contacting host
30 |
31 | {redirects.redirects.map((redirect: any, index: number) => {
32 | return (
33 |
34 | ↳ {redirect}
35 |
36 | );
37 | })}
38 |
39 | );
40 | }
41 |
42 | export default RedirectsCard;
43 |
--------------------------------------------------------------------------------
/src/pages/check/[...target].astro:
--------------------------------------------------------------------------------
1 | ---
2 | import BaseLayout from '@layouts/Base.astro';
3 | import Main from '../../web-check-live/main.tsx';
4 | import '../../web-check-live/styles/index.css';
5 |
6 | export const prerender = false;
7 |
8 | const { pathname, search } = new URL(Astro.request.url);
9 |
10 | const searchUrl = new URLSearchParams(search).get('url');
11 |
12 | if (searchUrl) {
13 | Astro.redirect(`/check/${encodeURIComponent(searchUrl)}`);
14 | }
15 |
16 | ---
17 |
18 |
19 |
20 |
21 |
22 |
43 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Archives.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import colors from 'web-check-live/styles/colors';
3 | import { Card } from 'web-check-live/components/Form/Card';
4 | import Row from 'web-check-live/components/Form/Row';
5 |
6 | const Note = styled.small`
7 | opacity: 0.5;
8 | display: block;
9 | margin-top: 0.5rem;
10 | a {
11 | color: ${colors.primary};
12 | }
13 | `;
14 |
15 | const ArchivesCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
16 | const data = props.data;
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 | { data.scanFrequency?.scansPerDay > 1 ?
25 |
:
26 |
27 | }
28 |
29 |
30 | View historical versions of this page here ,
31 | via the Internet Archive's Wayback Machine.
32 |
33 |
34 | );
35 | }
36 |
37 | export default ArchivesCard;
38 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | # Build settings and site core config
2 | [build]
3 | base = "/"
4 | command = "yarn build"
5 | publish = "dist"
6 | functions = "api"
7 |
8 | # Environmental variables and optional secrets
9 | [build.environment]
10 | PLATFORM = "netlify"
11 | PUBLIC_API_ENDPOINT = "/.netlify/functions"
12 | # Build configuration env vars (uncomment if you want to conigure these)
13 | # CI="false" # Set CI to false, to prevent warnings from exiting the build
14 | # CHROME_PATH='/usr/bin/chromium' # Path to Chromium binary
15 | # NODE_VERSION = "16.16.0" # Set the version of Node.js to use
16 |
17 | # Optional secrets and API keys (uncomment if you want to add these)
18 | # GOOGLE_CLOUD_API_KEY='' # Google Cloud API key, for running Lighthouse scans
19 | # BUILT_WITH_API_KEY='' # BuiltWith API key, for detecting site features
20 | # REACT_APP_SHODAN_API_KEY='' # Shodan API key, for using Shodan scan API
21 | # REACT_APP_WHO_API_KEY='' # WhoAPI key, for iniiating client-side whois lookup
22 |
23 | # Redirect the /api/* path to the lambda functions
24 | [[redirects]]
25 | from = "/api/*"
26 | to = "/.netlify/functions/:splat"
27 | status = 301
28 | force = true
29 |
30 | # Plugins
31 | [[plugins]]
32 | package = "netlify-plugin-chromium"
33 | [plugins.inputs]
34 | packageManager = "yarn"
35 |
36 | # Set any security headers here
37 | [[headers]]
38 | for = "/*"
39 | [headers.values]
40 | # Uncomment to enable Netlify user control. Requires premium plan.
41 | # Basic-Auth = "someuser:somepassword anotheruser:anotherpassword"
42 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Hsts.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row, { type RowProps } from 'web-check-live/components/Form/Row';
4 |
5 | const cardStyles = '';
6 |
7 | const parseHeader = (headerString: string): RowProps[] => {
8 | return headerString.split(';').map((part) => {
9 | const trimmedPart = part.trim();
10 | const equalsIndex = trimmedPart.indexOf('=');
11 |
12 | if (equalsIndex >= 0) {
13 | return {
14 | lbl: trimmedPart.substring(0, equalsIndex).trim(),
15 | val: trimmedPart.substring(equalsIndex + 1).trim(),
16 | };
17 | } else {
18 | return { lbl: trimmedPart, val: 'true' };
19 | }
20 | });
21 | };
22 |
23 | const HstsCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
24 | const hstsResults = props.data;
25 | const hstsHeaders = hstsResults?.hstsHeader ? parseHeader(hstsResults.hstsHeader) : [];
26 | return (
27 |
28 | {typeof hstsResults.compatible === 'boolean' && (
29 |
30 | )}
31 | {hstsHeaders.length > 0 && hstsHeaders.map((header: RowProps, index: number) => {
32 | return (
33 |
34 | );
35 | })
36 | }
37 | {hstsResults.message && ({hstsResults.message}
)}
38 |
39 | );
40 | }
41 |
42 | export default HstsCard;
43 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/ActionButtons.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import Button from 'web-check-live/components/Form/Button';
3 | import colors from 'web-check-live/styles/colors';
4 |
5 | const ActionButtonContainer = styled.div`
6 | position: absolute;
7 | top: 0.25rem;
8 | right: 0.25rem;
9 | opacity: 0.75;
10 | display: flex;
11 | gap: 0.125rem;
12 | align-items: baseline;
13 | `;
14 |
15 | interface Action {
16 | label: string;
17 | icon: string;
18 | onClick: () => void;
19 | };
20 |
21 | const actionButtonStyles = `
22 | padding: 0 0.25rem;
23 | font-size: 1.25rem;
24 | text-align: center;
25 | width: 1.5rem;
26 | height: 1.5rem;
27 | color: ${colors.textColor};
28 | background: none;
29 | box-shadow: none;
30 | transition: all 0.2s ease-in-out;
31 | margin: 0;
32 | display: flex;
33 | align-items: center;
34 | &:hover {
35 | color: ${colors.primary};
36 | background: ${colors.backgroundDarker};
37 | box-shadow: none;
38 | }
39 | `;
40 |
41 | const ActionButtons = (props: { actions: any }): JSX.Element => {
42 | const actions = props.actions;
43 | if (!actions) return (<>>);
44 | return (
45 |
46 | { actions.map((action: Action, index: number) =>
47 |
52 | {action.icon}
53 |
54 | )}
55 |
56 | );
57 | };
58 |
59 | export default ActionButtons;
60 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/LocationMap.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | ComposableMap,
3 | Geographies,
4 | Geography,
5 | Annotation,
6 | } from 'react-simple-maps';
7 |
8 | import colors from 'web-check-live/styles/colors';
9 | import MapFeatures from 'web-check-live/assets/data/map-features.json';
10 |
11 | interface Props {
12 | lat: number,
13 | lon: number,
14 | label?: string,
15 | };
16 |
17 | const MapChart = (location: Props) => {
18 | const { lat, lon, label } = location;
19 |
20 | return (
21 |
29 |
35 | {({ geographies }: any) =>
36 | geographies.map((geo: any) => (
37 |
38 | ))
39 | }
40 |
41 |
51 |
52 | {label || "Server"}
53 |
54 |
55 |
56 | );
57 | };
58 |
59 | export default MapChart;
60 |
--------------------------------------------------------------------------------
/api/ssl.js:
--------------------------------------------------------------------------------
1 | import tls from 'tls';
2 | import middleware from './_common/middleware.js';
3 |
4 | const sslHandler = async (urlString) => {
5 | try {
6 | const parsedUrl = new URL(urlString);
7 | const options = {
8 | host: parsedUrl.hostname,
9 | port: parsedUrl.port || 443,
10 | servername: parsedUrl.hostname,
11 | rejectUnauthorized: false,
12 | };
13 |
14 | return new Promise((resolve, reject) => {
15 | const socket = tls.connect(options, () => {
16 | if (!socket.authorized) {
17 | return reject(new Error(`SSL handshake not authorized. Reason: ${socket.authorizationError}`));
18 | }
19 |
20 | const cert = socket.getPeerCertificate();
21 | if (!cert || Object.keys(cert).length === 0) {
22 | return reject(new Error(`
23 | No certificate presented by the server.\n
24 | The server is possibly not using SNI (Server Name Indication) to identify itself, and you are connecting to a hostname-aliased IP address.
25 | Or it may be due to an invalid SSL certificate, or an incomplete SSL handshake at the time the cert is being read.`));
26 | }
27 |
28 | const { raw, issuerCertificate, ...certWithoutRaw } = cert;
29 | resolve(certWithoutRaw);
30 | socket.end();
31 | });
32 |
33 | socket.on('error', (error) => {
34 | reject(new Error(`Error fetching site certificate: ${error.message}`));
35 | });
36 | });
37 |
38 | } catch (error) {
39 | throw new Error(error.message);
40 | }
41 | };
42 |
43 | export const handler = middleware(sslHandler);
44 | export default handler;
45 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/DomainLookup.tsx:
--------------------------------------------------------------------------------
1 |
2 | import colors from 'web-check-live/styles/colors';
3 | import { Card } from 'web-check-live/components/Form/Card';
4 | import Row from 'web-check-live/components/Form/Row';
5 |
6 | const cardStyles = `
7 | span.val {
8 | &.up { color: ${colors.success}; }
9 | &.down { color: ${colors.danger}; }
10 | }
11 | `;
12 |
13 | const DomainLookupCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
14 | const domain = props.data.internicData || {};
15 | return (
16 |
17 | { domain.Domain_Name &&
}
18 | { domain.Creation_Date &&
}
19 | { domain.Updated_Date &&
}
20 | { domain.Registry_Expiry_Date &&
}
21 | { domain.Registry_Domain_ID &&
}
22 | { domain.Registrar_WHOIS_Server &&
}
23 | { domain.Registrar &&
24 | Registrar
25 | {domain.Registrar}
26 |
}
27 | { domain.Registrar_IANA_ID &&
}
28 |
29 | );
30 | }
31 |
32 | export default DomainLookupCard;
33 |
--------------------------------------------------------------------------------
/api/dns-server.js:
--------------------------------------------------------------------------------
1 | import { promises as dnsPromises, lookup } from 'dns';
2 | import axios from 'axios';
3 | import middleware from './_common/middleware.js';
4 |
5 | const dnsHandler = async (url) => {
6 | try {
7 | const domain = url.replace(/^(?:https?:\/\/)?/i, "");
8 | const addresses = await dnsPromises.resolve4(domain);
9 | const results = await Promise.all(addresses.map(async (address) => {
10 | const hostname = await dnsPromises.reverse(address).catch(() => null);
11 | let dohDirectSupports = false;
12 | try {
13 | await axios.get(`https://${address}/dns-query`);
14 | dohDirectSupports = true;
15 | } catch (error) {
16 | dohDirectSupports = false;
17 | }
18 | return {
19 | address,
20 | hostname,
21 | dohDirectSupports,
22 | };
23 | }));
24 |
25 | // let dohMozillaSupport = false;
26 | // try {
27 | // const mozillaList = await axios.get('https://firefox.settings.services.mozilla.com/v1/buckets/security-state/collections/onecrl/records');
28 | // dohMozillaSupport = results.some(({ hostname }) => mozillaList.data.data.some(({ id }) => id.includes(hostname)));
29 | // } catch (error) {
30 | // console.error(error);
31 | // }
32 |
33 | return {
34 | domain,
35 | dns: results,
36 | // dohMozillaSupport,
37 | };
38 | } catch (error) {
39 | throw new Error(`An error occurred while resolving DNS. ${error.message}`); // This will be caught and handled by the commonMiddleware
40 | }
41 | };
42 |
43 |
44 | export const handler = middleware(dnsHandler);
45 | export default handler;
46 |
47 |
--------------------------------------------------------------------------------
/src/components/homepage/ButtonGroup.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import Icon from '@components/molecules/Icon.svelte';
3 |
4 | interface Props {
5 | links: {
6 | title: string;
7 | url: string;
8 | icon: string;
9 | isCta: boolean;
10 | }[];
11 | }
12 |
13 | const { links } = Astro.props;
14 |
15 | ---
16 |
17 |
22 |
23 |
67 |
--------------------------------------------------------------------------------
/public/placeholder.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Web-Check
7 |
8 |
9 |
14 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/api/carbon.js:
--------------------------------------------------------------------------------
1 | import https from 'https';
2 | import middleware from './_common/middleware.js';
3 |
4 | const carbonHandler = async (url) => {
5 |
6 | // First, get the size of the website's HTML
7 | const getHtmlSize = (url) => new Promise((resolve, reject) => {
8 | https.get(url, res => {
9 | let data = '';
10 | res.on('data', chunk => {
11 | data += chunk;
12 | });
13 | res.on('end', () => {
14 | const sizeInBytes = Buffer.byteLength(data, 'utf8');
15 | resolve(sizeInBytes);
16 | });
17 | }).on('error', reject);
18 | });
19 |
20 | try {
21 | const sizeInBytes = await getHtmlSize(url);
22 | const apiUrl = `https://api.websitecarbon.com/data?bytes=${sizeInBytes}&green=0`;
23 |
24 | // Then use that size to get the carbon data
25 | const carbonData = await new Promise((resolve, reject) => {
26 | https.get(apiUrl, res => {
27 | let data = '';
28 | res.on('data', chunk => {
29 | data += chunk;
30 | });
31 | res.on('end', () => {
32 | resolve(JSON.parse(data));
33 | });
34 | }).on('error', reject);
35 | });
36 |
37 | if (!carbonData.statistics || (carbonData.statistics.adjustedBytes === 0 && carbonData.statistics.energy === 0)) {
38 | return {
39 | statusCode: 200,
40 | body: JSON.stringify({ skipped: 'Not enough info to get carbon data' }),
41 | };
42 | }
43 |
44 | carbonData.scanUrl = url;
45 | return carbonData;
46 | } catch (error) {
47 | throw new Error(`Error: ${error.message}`);
48 | }
49 | };
50 |
51 | export const handler = middleware(carbonHandler);
52 | export default handler;
53 |
--------------------------------------------------------------------------------
/api/status.js:
--------------------------------------------------------------------------------
1 | import https from 'https';
2 | import { performance, PerformanceObserver } from 'perf_hooks';
3 | import middleware from './_common/middleware.js';
4 |
5 | const statusHandler = async (url) => {
6 | if (!url) {
7 | throw new Error('You must provide a URL query parameter!');
8 | }
9 |
10 | let dnsLookupTime;
11 | let responseCode;
12 | let startTime;
13 |
14 | const obs = new PerformanceObserver((items) => {
15 | dnsLookupTime = items.getEntries()[0].duration;
16 | performance.clearMarks();
17 | });
18 |
19 | obs.observe({ entryTypes: ['measure'] });
20 |
21 | performance.mark('A');
22 |
23 | try {
24 | startTime = performance.now();
25 | const response = await new Promise((resolve, reject) => {
26 | const req = https.get(url, res => {
27 | let data = '';
28 | responseCode = res.statusCode;
29 | res.on('data', chunk => {
30 | data += chunk;
31 | });
32 | res.on('end', () => {
33 | resolve(res);
34 | });
35 | });
36 |
37 | req.on('error', reject);
38 | req.end();
39 | });
40 |
41 | if (responseCode < 200 || responseCode >= 400) {
42 | throw new Error(`Received non-success response code: ${responseCode}`);
43 | }
44 |
45 | performance.mark('B');
46 | performance.measure('A to B', 'A', 'B');
47 | let responseTime = performance.now() - startTime;
48 | obs.disconnect();
49 |
50 | return { isUp: true, dnsLookupTime, responseTime, responseCode };
51 |
52 | } catch (error) {
53 | obs.disconnect();
54 | throw error;
55 | }
56 | };
57 |
58 | export const handler = middleware(statusHandler);
59 | export default handler;
60 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/HostNames.tsx:
--------------------------------------------------------------------------------
1 |
2 | import styled from '@emotion/styled';
3 | import type { HostNames } from 'web-check-live/utils/result-processor';
4 | import colors from 'web-check-live/styles/colors';
5 | import { Card } from 'web-check-live/components/Form/Card';
6 | import Heading from 'web-check-live/components/Form/Heading';
7 |
8 | const Row = styled.div`
9 | display: flex;
10 | justify-content: space-between;
11 | padding: 0.25rem;
12 | &:not(:last-child) { border-bottom: 1px solid ${colors.primaryTransparent}; }
13 | span:first-child { font-weight: bold; }
14 | `;
15 |
16 | const HostListSection = (props: { list: string[], title: string }) => {
17 | const { list, title } = props;
18 | return (
19 | <>
20 | {title}
21 | { list.map((entry: string, index: number) => {
22 | return (
23 | { entry }
24 | )}
25 | )}
26 | >
27 | );
28 | }
29 |
30 | const cardStyles = `
31 | max-height: 50rem;
32 | overflow: auto;
33 | `;
34 |
35 | const HostNamesCard = (props: { data: HostNames, title: string, actionButtons: any }): JSX.Element => {
36 | const hosts = props.data;
37 | return (
38 |
39 | { hosts.domains.length > 0 &&
40 |
41 | }
42 | { hosts.hostnames.length > 0 &&
43 |
44 | }
45 |
46 | );
47 | }
48 |
49 | export default HostNamesCard;
50 |
--------------------------------------------------------------------------------
/public/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Web-Check
7 |
8 |
9 |
15 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/api/sitemap.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import xml2js from 'xml2js';
3 | import middleware from './_common/middleware.js';
4 |
5 | const sitemapHandler = async (url) => {
6 | let sitemapUrl = `${url}/sitemap.xml`;
7 |
8 | const hardTimeOut = 5000;
9 |
10 | try {
11 | // Try to fetch sitemap directly
12 | let sitemapRes;
13 | try {
14 | sitemapRes = await axios.get(sitemapUrl, { timeout: hardTimeOut });
15 | } catch (error) {
16 | if (error.response && error.response.status === 404) {
17 | // If sitemap not found, try to fetch it from robots.txt
18 | const robotsRes = await axios.get(`${url}/robots.txt`, { timeout: hardTimeOut });
19 | const robotsTxt = robotsRes.data.split('\n');
20 |
21 | for (let line of robotsTxt) {
22 | if (line.toLowerCase().startsWith('sitemap:')) {
23 | sitemapUrl = line.split(' ')[1].trim();
24 | break;
25 | }
26 | }
27 |
28 | if (!sitemapUrl) {
29 | return { skipped: 'No sitemap found' };
30 | }
31 |
32 | sitemapRes = await axios.get(sitemapUrl, { timeout: hardTimeOut });
33 | } else {
34 | throw error; // If other error, throw it
35 | }
36 | }
37 |
38 | const parser = new xml2js.Parser();
39 | const sitemap = await parser.parseStringPromise(sitemapRes.data);
40 |
41 | return sitemap;
42 | } catch (error) {
43 | if (error.code === 'ECONNABORTED') {
44 | return { error: `Request timed-out after ${hardTimeOut}ms` };
45 | } else {
46 | return { error: error.message };
47 | }
48 | }
49 | };
50 |
51 | export const handler = middleware(sitemapHandler);
52 | export default handler;
53 |
54 |
--------------------------------------------------------------------------------
/public/assets/images/docker.svg:
--------------------------------------------------------------------------------
1 | Docker
2 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/DnsServer.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Heading from 'web-check-live/components/Form/Heading';
4 | import Row from 'web-check-live/components/Form/Row';
5 | import colors from 'web-check-live/styles/colors';
6 |
7 | const cardStyles = `
8 | small {
9 | margin-top: 1rem;
10 | opacity: 0.5;
11 | display: block;
12 | a { color: ${colors.primary}; }
13 | }
14 | `;
15 |
16 | const DnsServerCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
17 | const dnsSecurity = props.data;
18 | return (
19 |
20 | {dnsSecurity.dns.map((dns: any, index: number) => {
21 | return (
22 | { dnsSecurity.dns.length > 1 && DNS Server #{index+1} }
23 |
24 | { dns.hostname &&
}
25 |
26 |
);
27 | })}
28 | {dnsSecurity.dns.length > 0 && (
29 | * DoH Support is determined by the DNS server's response to a DoH query.
30 | Sometimes this gives false negatives, and it's also possible that the DNS server supports DoH but does not respond to DoH queries.
31 | If the DNS server does not support DoH, it may still be possible to use DoH by using a DoH proxy.
32 | )}
33 |
34 | );
35 | }
36 |
37 | export default DnsServerCard;
38 |
--------------------------------------------------------------------------------
/api/dnssec.js:
--------------------------------------------------------------------------------
1 | import https from 'https';
2 | import middleware from './_common/middleware.js';
3 |
4 | const dnsSecHandler = async (domain) => {
5 | const dnsTypes = ['DNSKEY', 'DS', 'RRSIG'];
6 | const records = {};
7 |
8 | for (const type of dnsTypes) {
9 | const options = {
10 | hostname: 'dns.google',
11 | path: `/resolve?name=${encodeURIComponent(domain)}&type=${type}`,
12 | method: 'GET',
13 | headers: {
14 | 'Accept': 'application/dns-json'
15 | }
16 | };
17 |
18 | try {
19 | const dnsResponse = await new Promise((resolve, reject) => {
20 | const req = https.request(options, res => {
21 | let data = '';
22 |
23 | res.on('data', chunk => {
24 | data += chunk;
25 | });
26 |
27 | res.on('end', () => {
28 | try {
29 | resolve(JSON.parse(data));
30 | } catch (error) {
31 | reject(new Error('Invalid JSON response'));
32 | }
33 | });
34 |
35 | res.on('error', error => {
36 | reject(error);
37 | });
38 | });
39 |
40 | req.end();
41 | });
42 |
43 | if (dnsResponse.Answer) {
44 | records[type] = { isFound: true, answer: dnsResponse.Answer, response: dnsResponse.Answer };
45 | } else {
46 | records[type] = { isFound: false, answer: null, response: dnsResponse };
47 | }
48 | } catch (error) {
49 | throw new Error(`Error fetching ${type} record: ${error.message}`); // This will be caught and handled by the commonMiddleware
50 | }
51 | }
52 |
53 | return records;
54 | };
55 |
56 | export const handler = middleware(dnsSecHandler);
57 | export default handler;
58 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 | Web Check
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Welcome to Web-Check, the free and open source tool for viewing all available information about a website.
30 | Get started by entering a URL, and clicking the "Scan" button, or view the code and docs
31 | on GitHub .
32 | Licensed under MIT, ©️ Alicia Sykes 2023.
33 |
34 | JavaScript is required to continue, please enable it in your browser.
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/public/assets/badges/webcheck.svg:
--------------------------------------------------------------------------------
1 | Website: web-check.xyz Website Website web-check.xyz webcheck.zyz
2 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Lighthouse.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import { ExpandableRow } from 'web-check-live/components/Form/Row';
3 |
4 | const processScore = (percentile: number) => {
5 | return `${Math.round(percentile * 100)}%`;
6 | }
7 |
8 | interface Audit {
9 | id: string,
10 | score?: number | string,
11 | scoreDisplayMode?: string,
12 | title?: string,
13 | description?: string,
14 | displayValue?: string,
15 | };
16 |
17 | const makeValue = (audit: Audit) => {
18 | let score = audit.score;
19 | if (audit.displayValue) {
20 | score = audit.displayValue;
21 | } else if (audit.scoreDisplayMode) {
22 | score = audit.score === 1 ? '✅ Pass' : '❌ Fail';
23 | }
24 | return score;
25 | };
26 |
27 | const LighthouseCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
28 | const lighthouse = props.data;
29 | const categories = lighthouse?.categories || {};
30 | const audits = lighthouse?.audits || [];
31 |
32 | return (
33 |
34 | { Object.keys(categories).map((title: string, index: number) => {
35 | const scoreIds = categories[title].auditRefs.map((ref: { id: string }) => ref.id);
36 | const scoreList = scoreIds.map((id: string) => {
37 | return { lbl: audits[id].title, val: makeValue(audits[id]), title: audits[id].description, key: id }
38 | })
39 | return (
40 |
46 | );
47 | }) }
48 |
49 | );
50 | }
51 |
52 | export default LighthouseCard;
53 |
--------------------------------------------------------------------------------
/api/_common/aws-webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const nodeExternals = require('webpack-node-externals');
3 |
4 | module.exports = {
5 | target: 'node',
6 | mode: 'production',
7 | entry: {
8 | 'carbon': './api/carbon.js',
9 | 'cookies': './api/cookies.js',
10 | 'dns-server': './api/dns-server.js',
11 | 'dns': './api/dns.js',
12 | 'dnssec': './api/dnssec.js',
13 | 'features': './api/features.js',
14 | 'get-ip': './api/get-ip.js',
15 | 'headers': './api/headers.js',
16 | 'hsts': './api/hsts.js',
17 | 'linked-pages': './api/linked-pages.js',
18 | 'mail-config': './api/mail-config.js',
19 | 'ports': './api/ports.js',
20 | 'quality': './api/quality.js',
21 | 'redirects': './api/redirects.js',
22 | 'robots-txt': './api/robots-txt.js',
23 | 'screenshot': './api/screenshot.js',
24 | 'security-txt': './api/security-txt.js',
25 | 'sitemap': './api/sitemap.js',
26 | 'social-tags': './api/social-tags.js',
27 | 'ssl': './api/ssl.js',
28 | 'status': './api/status.js',
29 | 'tech-stack': './api/tech-stack.js',
30 | 'trace-route': './api/trace-route.js',
31 | 'txt-records': './api/txt-records.js',
32 | 'whois': './api/whois.js',
33 | },
34 | externals: [nodeExternals()],
35 | output: {
36 | filename: '[name].js',
37 | path: path.resolve(__dirname, '.webpack'),
38 | libraryTarget: 'commonjs2'
39 | },
40 | module: {
41 | rules: [
42 | {
43 | test: /\.js$/,
44 | use: {
45 | loader: 'babel-loader'
46 | },
47 | exclude: /node_modules/,
48 | }
49 | ]
50 | }
51 | };
52 |
--------------------------------------------------------------------------------
/public/assets/images/swagger.svg:
--------------------------------------------------------------------------------
1 | Swagger
2 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/Footer.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import { Link } from 'react-router-dom';
3 | import colors from 'web-check-live/styles/colors';
4 |
5 | const StyledFooter = styled.footer`
6 | bottom: 0;
7 | width: 100%;
8 | text-align: center;
9 | padding: 0.5rem 0;
10 | background: ${colors.backgroundDarker};
11 | display: flex;
12 | justify-content: space-around;
13 | align-items: center;
14 | align-content: center;
15 | flex-wrap: wrap;
16 | opacity: 0.75;
17 | transition: all 0.2s ease-in-out;
18 | @media (min-width: 1024px) {
19 | justify-content: space-between;
20 | }
21 | &:hover {
22 | opacity: 1;
23 | }
24 | span {
25 | margin: 0 0.5rem;
26 | text-align: center;
27 | }
28 | `;
29 |
30 |
31 | const ALink = styled.a`
32 | color: ${colors.primary};
33 | font-weight: bold;
34 | border-radius: 4px;
35 | padding: 0.1rem;
36 | transition: all 0.2s ease-in-out;
37 | &:hover {
38 | background: ${colors.primary};
39 | color: ${colors.backgroundDarker};
40 | text-decoration: none;
41 | }
42 | `;
43 |
44 | const Footer = (props: { isFixed?: boolean }): JSX.Element => {
45 | const licenseUrl = 'https://github.com/lissy93/web-check/blob/master/LICENSE';
46 | const authorUrl = 'https://aliciasykes.com';
47 | const githubUrl = 'https://github.com/lissy93/web-check';
48 | return (
49 |
50 |
51 | View source at github.com/lissy93/web-check
52 |
53 |
54 | Web-Check is
55 | licensed under MIT -
56 | © Alicia Sykes 2023
57 |
58 |
59 | );
60 | }
61 |
62 | export default Footer;
63 |
--------------------------------------------------------------------------------
/api/hsts.js:
--------------------------------------------------------------------------------
1 | import https from 'https';
2 | import middleware from './_common/middleware.js';
3 |
4 | const hstsHandler = async (url, event, context) => {
5 | const errorResponse = (message, statusCode = 500) => {
6 | return {
7 | statusCode: statusCode,
8 | body: JSON.stringify({ error: message }),
9 | };
10 | };
11 | const hstsIncompatible = (message, compatible = false, hstsHeader = null ) => {
12 | return { message, compatible, hstsHeader };
13 | };
14 |
15 |
16 | return new Promise((resolve, reject) => {
17 | const req = https.request(url, res => {
18 | const headers = res.headers;
19 | const hstsHeader = headers['strict-transport-security'];
20 |
21 | if (!hstsHeader) {
22 | resolve(hstsIncompatible(`Site does not serve any HSTS headers.`));
23 | } else {
24 | const maxAgeMatch = hstsHeader.match(/max-age=(\d+)/);
25 | const includesSubDomains = hstsHeader.includes('includeSubDomains');
26 | const preload = hstsHeader.includes('preload');
27 |
28 | if (!maxAgeMatch || parseInt(maxAgeMatch[1]) < 10886400) {
29 | resolve(hstsIncompatible(`HSTS max-age is less than 10886400.`));
30 | } else if (!includesSubDomains) {
31 | resolve(hstsIncompatible(`HSTS header does not include all subdomains.`));
32 | } else if (!preload) {
33 | resolve(hstsIncompatible(`HSTS header does not contain the preload directive.`));
34 | } else {
35 | resolve(hstsIncompatible(`Site is compatible with the HSTS preload list!`, true, hstsHeader));
36 | }
37 | }
38 | });
39 |
40 | req.on('error', (error) => {
41 | resolve(errorResponse(`Error making request: ${error.message}`));
42 | });
43 |
44 | req.end();
45 | });
46 | };
47 |
48 | export const handler = middleware(hstsHandler);
49 | export default handler;
50 |
--------------------------------------------------------------------------------
/api/cookies.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import puppeteer from 'puppeteer';
3 | import middleware from './_common/middleware.js';
4 |
5 | const getPuppeteerCookies = async (url) => {
6 | const browser = await puppeteer.launch({
7 | headless: 'new',
8 | args: ['--no-sandbox', '--disable-setuid-sandbox'],
9 | });
10 |
11 | try {
12 | const page = await browser.newPage();
13 | const navigationPromise = page.goto(url, { waitUntil: 'networkidle2' });
14 | const timeoutPromise = new Promise((_, reject) =>
15 | setTimeout(() => reject(new Error('Puppeteer took too long!')), 3000)
16 | );
17 | await Promise.race([navigationPromise, timeoutPromise]);
18 | return await page.cookies();
19 | } finally {
20 | await browser.close();
21 | }
22 | };
23 |
24 | const cookieHandler = async (url) => {
25 | let headerCookies = null;
26 | let clientCookies = null;
27 |
28 | try {
29 | const response = await axios.get(url, {
30 | withCredentials: true,
31 | maxRedirects: 5,
32 | });
33 | headerCookies = response.headers['set-cookie'];
34 | } catch (error) {
35 | if (error.response) {
36 | return { error: `Request failed with status ${error.response.status}: ${error.message}` };
37 | } else if (error.request) {
38 | return { error: `No response received: ${error.message}` };
39 | } else {
40 | return { error: `Error setting up request: ${error.message}` };
41 | }
42 | }
43 |
44 | try {
45 | clientCookies = await getPuppeteerCookies(url);
46 | } catch (_) {
47 | clientCookies = null;
48 | }
49 |
50 | if (!headerCookies && (!clientCookies || clientCookies.length === 0)) {
51 | return { skipped: 'No cookies' };
52 | }
53 |
54 | return { headerCookies, clientCookies };
55 | };
56 |
57 | export const handler = middleware(cookieHandler);
58 | export default handler;
59 |
--------------------------------------------------------------------------------
/src/styles/media-queries.scss:
--------------------------------------------------------------------------------
1 | // Breakpoints
2 | $breakpoint-xs: 599px; // Max width for mobile only
3 | $breakpoint-sm: 600px; // Min width for tablet portrait
4 | $breakpoint-md: 768px; // Min width for tablet landscape
5 | $breakpoint-lg: 1024px; // Min width for desktop
6 | $breakpoint-xl: 1440px; // Min width for large desktop
7 |
8 | // Mixins for specific breakpoints
9 | @mixin for-mobile-only {
10 | @media (max-width: $breakpoint-xs) {
11 | @content;
12 | }
13 | }
14 |
15 | @mixin mobile-up {
16 | @media (min-width: calc($breakpoint-xs + 1px)) {
17 | @content;
18 | }
19 | }
20 |
21 | @mixin for-tablet-portrait {
22 | @media (min-width: $breakpoint-sm) and (max-width: calc($breakpoint-md - 1px)) {
23 | @content;
24 | }
25 | }
26 |
27 | @mixin tablet-portrait-down {
28 | @media (max-width: calc($breakpoint-md - 1px)) {
29 | @content;
30 | }
31 | }
32 |
33 | @mixin tablet-up {
34 | @media (min-width: $breakpoint-sm) {
35 | @content;
36 | }
37 | }
38 |
39 | @mixin for-tablet-landscape {
40 | @media (min-width: $breakpoint-md) and (max-width: calc($breakpoint-lg - 1px)) {
41 | @content;
42 | }
43 | }
44 |
45 | @mixin tablet-landscape-down {
46 | @media (max-width: calc($breakpoint-lg - 1px)) {
47 | @content;
48 | }
49 | }
50 |
51 | @mixin for-desktop {
52 | @media (min-width: $breakpoint-lg) and (max-width: calc($breakpoint-xl - 1px)) {
53 | @content;
54 | }
55 | }
56 |
57 | @mixin desktop-down {
58 | @media (max-width: calc($breakpoint-xl - 1px)) {
59 | @content;
60 | }
61 | }
62 |
63 | @mixin for-large-desktop {
64 | @media (min-width: $breakpoint-xl) {
65 | @content;
66 | }
67 | }
68 |
69 | @mixin large-desktop-up {
70 | @media (min-width: $breakpoint-xl) {
71 | @content;
72 | }
73 | }
74 |
75 | @mixin mobile-down {
76 | @media (max-width: $breakpoint-xs) {
77 | @content;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/pages/web-check-api/spec.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import BaseLayout from '@layouts/Base.astro';
3 | import NavBar from '@components/scafold/Nav.astro';
4 | import Footer from '@components/scafold/Footer.astro';
5 | ---
6 |
7 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
42 |
43 |
56 |
--------------------------------------------------------------------------------
/src/components/homepage/SponsorSegment.astro:
--------------------------------------------------------------------------------
1 | ---
2 | const sponsorName = 'Terminal Trove';
3 | const sponsorTagline = 'The $HOME of all things terminal.';
4 | const sponsorLink = 'https://terminaltrove.com/?utm_campaign=github&utm_medium=referral&utm_content=web-check&utm_source=wcgh';
5 |
6 | const ctaPreText = 'Get updates on the latest CLI/TUI tools via the';
7 | const ctaLinkHref = 'https://terminaltrove.com/newsletter?utm_campaign=github&utm_medium=referral&utm_content=web-check&utm_source=wcgh';
8 | const ctaLinkText = 'Terminal Trove Newsletter';
9 | const ctaImageSrc = 'https://i.ibb.co/5jJ4bzZ/terminal-trove-cta.png';
10 | ---
11 |
12 |
24 |
25 |
63 |
--------------------------------------------------------------------------------
/src/web-check-live/views/NotFound.tsx:
--------------------------------------------------------------------------------
1 |
2 | import styled from '@emotion/styled';
3 |
4 | import colors from 'web-check-live/styles/colors';
5 | import Heading from 'web-check-live/components/Form/Heading';
6 | import Footer from 'web-check-live/components/misc/Footer';
7 | import Nav from 'web-check-live/components/Form/Nav';
8 | import Button from 'web-check-live/components/Form/Button';
9 | import { StyledCard } from 'web-check-live/components/Form/Card';
10 |
11 | const AboutContainer = styled.div`
12 | width: 95vw;
13 | max-width: 1000px;
14 | margin: 2rem auto;
15 | padding-bottom: 1rem;
16 | header {
17 | margin 1rem 0;
18 | }
19 | a {
20 | color: ${colors.primary};
21 | }
22 | .im-drink { font-size: 6rem; }
23 | header {
24 | width: auto;
25 | margin: 1rem;
26 | }
27 | `;
28 |
29 | const HeaderLinkContainer = styled.nav`
30 | display: flex;
31 | flex-wrap: wrap;
32 | gap: 1rem;
33 | a {
34 | text-decoration: none;
35 | }
36 | `;
37 |
38 | const NotFoundInner = styled(StyledCard)`
39 | display: flex;
40 | flex-direction: column;
41 | align-items: center;
42 | margin: 1rem;
43 | gap: 0.5rem;
44 | h2 { font-size: 8rem; }
45 | `;
46 |
47 |
48 | const NotFound = (): JSX.Element => {
49 | return (
50 | <>
51 |
52 |
53 |
54 | 404
55 | 🥴
56 | Not Found
57 |
58 | Back to Homepage
59 |
60 | Report Issue
61 |
62 |
63 |
64 | >
65 | );
66 | };
67 |
68 | export default NotFound;
69 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/TraceRoute.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import colors from 'web-check-live/styles/colors';
3 | import { Card } from 'web-check-live/components/Form/Card';
4 |
5 | const RouteRow = styled.div`
6 | text-align: center;
7 | width: fit-content;
8 | margin: 0 auto;
9 | .ipName {
10 | font-size: 1rem;
11 | }
12 | `;
13 |
14 | const RouteTimings = styled.div`
15 | p {
16 | margin: 0 auto;
17 | }
18 | .arrow {
19 | font-size: 2.5rem;
20 | color: ${colors.primary};
21 | margin-top: -1rem;
22 | }
23 | .times {
24 | font-size: 0.85rem;
25 | color: ${colors.textColorSecondary};
26 | }
27 | .completed {
28 | text-align: center;
29 | font-weight: bold;
30 | }
31 | `;
32 |
33 | const cardStyles = ``;
34 |
35 | const TraceRouteCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
36 | const traceRouteResponse = props.data;
37 | const routes = traceRouteResponse.result;
38 | return (
39 |
40 | {routes.filter((x: any) => x).map((route: any, index: number) => (
41 |
42 | {Object.keys(route)[0]}
43 |
44 | {route[Object.keys(route)[0]].map((time: any, packetIndex: number) => (
45 |
46 | { route[Object.keys(route)[0]].length > 1 && (<>Packet #{packetIndex + 1}:>) }
47 | Took {time} ms
48 |
49 | ))}
50 | ↓
51 |
52 |
53 | )
54 | )}
55 |
56 |
57 | Round trip completed in {traceRouteResponse.timeTaken} ms
58 |
59 |
60 |
61 | );
62 | }
63 |
64 | export default TraceRouteCard;
65 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/ErrorBoundary.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component, type ErrorInfo, type ReactNode } from "react";
2 | import styled from '@emotion/styled';
3 | import Card from 'web-check-live/components/Form/Card';
4 | import Heading from 'web-check-live/components/Form/Heading';
5 | import colors from 'web-check-live/styles/colors';
6 |
7 | interface Props {
8 | children: ReactNode;
9 | title?: string;
10 | key?: string;
11 | }
12 |
13 | interface State {
14 | hasError: boolean;
15 | errorMessage: string | null;
16 | }
17 |
18 | const ErrorText = styled.p`
19 | color: ${colors.danger};
20 | `;
21 |
22 | class ErrorBoundary extends Component {
23 | public state: State = {
24 | hasError: false,
25 | errorMessage: null
26 | };
27 |
28 | // Catch errors in any components below and re-render with error message
29 | public static getDerivedStateFromError(error: Error): State {
30 | return { hasError: true, errorMessage: error.message };
31 | }
32 |
33 |
34 | public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
35 | console.error("Uncaught error:", error, errorInfo);
36 | }
37 |
38 | public render() {
39 | if (this.state.hasError) {
40 | return (
41 |
42 | { this.props.title && {this.props.title} }
43 | This component errored unexpectedly
44 |
45 | Usually this happens if the result from the server was not what was expected.
46 | Check the logs for more info. If you continue to experience this issue, please raise a ticket on the repository.
47 |
48 | {
49 | this.state.errorMessage &&
50 |
51 | Error Details
52 | {this.state.errorMessage}
53 |
54 | }
55 |
56 | );
57 | }
58 |
59 | return this.props.children;
60 | }
61 | }
62 |
63 | export default ErrorBoundary;
64 |
--------------------------------------------------------------------------------
/src/pages/index.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import BaseLayout from '@layouts/Base.astro';
3 | import HeroForm from '@components/homepage/HeroForm.astro';
4 | import TempDisabled from '@/components/homepage/TempDisabled.astro';
5 | import HomeBackground from '@/components/homepage/HomeBackground';
6 | import AboutSection from '@/components/homepage/AboutSection.astro';
7 | import Footer from '@components/scafold/Footer.astro';
8 |
9 | const isBossServer = import.meta.env.BOSS_SERVER === true;
10 |
11 | const disableEverything = import.meta.env.VITE_DISABLE_EVERYTHING === true;
12 |
13 | // Redirect strait to /check or /check/:url if running as self-hosted instance
14 | if (!isBossServer) {
15 | const searchUrl = new URLSearchParams(new URL(Astro.request.url).search).get('url');
16 | const redirectUrl = searchUrl ? `/check/${encodeURIComponent(searchUrl)}` : '/check';
17 | Astro.redirect(redirectUrl);
18 | }
19 |
20 | ---
21 |
22 |
23 |
24 | {!isBossServer && ( )}
25 |
26 | { disableEverything && }
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
68 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/DocContent.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import docs, { type Doc } from 'web-check-live/utils/docs';
3 | import colors from 'web-check-live/styles/colors';
4 | import Heading from 'web-check-live/components/Form/Heading';
5 |
6 | const JobDocsContainer = styled.div`
7 | p.doc-desc, p.doc-uses, ul {
8 | margin: 0.25rem auto 1.5rem auto;
9 | }
10 | ul {
11 | padding: 0 0.5rem 0 1rem;
12 | }
13 | ul li a {
14 | color: ${colors.primary};
15 | }
16 | summary { color: ${colors.primary};}
17 | h4 {
18 | border-top: 1px solid ${colors.primary};
19 | color: ${colors.primary};
20 | opacity: 0.75;
21 | padding: 0.5rem 0;
22 | }
23 | `;
24 |
25 | const DocContent = (id: string) => {
26 | const doc = docs.filter((doc: Doc) => doc.id === id)[0] || null;
27 | return (
28 | doc? (
29 | {doc.title}
30 | About
31 | {doc.description}
32 | Use Cases
33 | {doc.use}
34 | Links
35 |
36 | {doc.resources.map((resource: string | { title: string, link: string } , index: number) => (
37 | typeof resource === 'string' ? (
38 | {resource}
39 | ) : (
40 | {resource.title}
41 | )
42 | ))}
43 |
44 |
45 | Example
46 |
47 |
48 | )
49 | : (
50 |
51 | No Docs provided for this widget yet
52 |
53 | ));
54 | };
55 |
56 | export default DocContent;
57 |
--------------------------------------------------------------------------------
/api/robots-txt.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import middleware from './_common/middleware.js';
3 |
4 | const parseRobotsTxt = (content) => {
5 | const lines = content.split('\n');
6 | const rules = [];
7 |
8 | lines.forEach(line => {
9 | line = line.trim(); // This removes trailing and leading whitespaces
10 |
11 | let match = line.match(/^(Allow|Disallow):\s*(\S*)$/i);
12 | if (match) {
13 | const rule = {
14 | lbl: match[1],
15 | val: match[2],
16 | };
17 |
18 | rules.push(rule);
19 | } else {
20 | match = line.match(/^(User-agent):\s*(\S*)$/i);
21 | if (match) {
22 | const rule = {
23 | lbl: match[1],
24 | val: match[2],
25 | };
26 |
27 | rules.push(rule);
28 | }
29 | }
30 | });
31 | return { robots: rules };
32 | }
33 |
34 | const robotsHandler = async function(url) {
35 | let parsedURL;
36 | try {
37 | parsedURL = new URL(url);
38 | } catch (error) {
39 | return {
40 | statusCode: 400,
41 | body: JSON.stringify({ error: 'Invalid url query parameter' }),
42 | };
43 | }
44 |
45 | const robotsURL = `${parsedURL.protocol}//${parsedURL.hostname}/robots.txt`;
46 |
47 | try {
48 | const response = await axios.get(robotsURL);
49 |
50 | if (response.status === 200) {
51 | const parsedData = parseRobotsTxt(response.data);
52 | if (!parsedData.robots || parsedData.robots.length === 0) {
53 | return { skipped: 'No robots.txt file present, unable to continue' };
54 | }
55 | return parsedData;
56 | } else {
57 | return {
58 | statusCode: response.status,
59 | body: JSON.stringify({ error: 'Failed to fetch robots.txt', statusCode: response.status }),
60 | };
61 | }
62 | } catch (error) {
63 | return {
64 | statusCode: 500,
65 | body: JSON.stringify({ error: `Error fetching robots.txt: ${error.message}` }),
66 | };
67 | }
68 | };
69 |
70 | export const handler = middleware(robotsHandler);
71 | export default handler;
72 |
--------------------------------------------------------------------------------
/src/web-check-live/components/misc/SelfScanMsg.tsx:
--------------------------------------------------------------------------------
1 |
2 | import styled from '@emotion/styled';
3 | import colors from 'web-check-live/styles/colors';
4 | import { StyledCard } from 'web-check-live/components/Form/Card';
5 |
6 | const StyledSelfScanMsg = styled(StyledCard)`
7 | margin: 0px auto 1rem;
8 | width: 95vw;
9 | a { color: ${colors.primary}; }
10 | b { font-weight: extra-bold; }
11 | span, i { opacity: 0.85; }
12 | img {
13 | width: 5rem;
14 | float: right;
15 | border-radius: 4px;
16 | }
17 | `;
18 |
19 | const messages = [
20 | 'Nice try! But scanning this app is like trying to tickle yourself. It just doesn\'t work!',
21 | 'Recursive scanning detected. The universe might implode...or it might not. But let\'s not try to find out.',
22 | 'Hey, stop checking us out! We\'re blushing... 😉',
23 | 'Hmmm, scanning us, are you? We feel so special!',
24 | 'Alert! Mirror scanning detected. Trust us, we\'re looking good 😉',
25 | 'We\'re flattered you\'re trying to scan us, but we can\'t tickle ourselves!',
26 | 'Oh, inspecting the inspector, aren\'t we? Inception much?',
27 | 'Just a second...wait a minute...you\'re scanning us?! Well, that\'s an interesting twist!',
28 | 'Scanning us? It\'s like asking a mirror to reflect on itself.',
29 | 'Well, this is awkward... like a dog chasing its own tail!',
30 | 'Ah, I see you\'re scanning this site... But alas, this did not cause an infinite recursive loop (this time)',
31 | ];
32 |
33 | const SelfScanMsg = () => {
34 | return (
35 |
36 |
37 | {messages[Math.floor(Math.random() * messages.length)]}
38 |
39 |
40 | But if you want to see how this site is built, why not check out
41 | the source code ?
42 |
43 |
44 | Do me a favour, and drop the repo a Star while you're there 😉
45 |
46 | );
47 | };
48 |
49 | export default SelfScanMsg;
50 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/ServerLocation.tsx:
--------------------------------------------------------------------------------
1 |
2 | import styled from '@emotion/styled';
3 | import type { ServerLocation } from 'web-check-live/utils/result-processor';
4 | import { Card } from 'web-check-live/components/Form/Card';
5 | import LocationMap from 'web-check-live/components/misc/LocationMap';
6 | import Flag from 'web-check-live/components/misc/Flag';
7 | import { TextSizes } from 'web-check-live/styles/typography';
8 | import Row, { StyledRow } from 'web-check-live/components/Form/Row';
9 |
10 | const cardStyles = '';
11 |
12 | const SmallText = styled.span`
13 | opacity: 0.5;
14 | font-size: ${TextSizes.xSmall};
15 | text-align: right;
16 | display: block;
17 | `;
18 |
19 | const MapRow = styled(StyledRow)`
20 | padding-top: 1rem;
21 | flex-direction: column;
22 | `;
23 |
24 | const CountryValue = styled.span`
25 | display: flex;
26 | gap: 0.5rem;
27 | `;
28 |
29 | const ServerLocationCard = (props: { data: ServerLocation, title: string, actionButtons: any }): JSX.Element => {
30 | const location = props.data;
31 | const {
32 | city, region, country,
33 | postCode, countryCode, coords,
34 | isp, timezone, languages, currency, currencyCode,
35 | } = location;
36 |
37 | return (
38 |
39 |
40 |
41 | Country
42 |
43 | {country}
44 | { countryCode && }
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Latitude: {coords.latitude}, Longitude: {coords.longitude}
53 |
54 |
55 | );
56 | }
57 |
58 | export default ServerLocationCard;
59 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/BuiltWith.tsx:
--------------------------------------------------------------------------------
1 |
2 | import styled from '@emotion/styled';
3 | import type { TechnologyGroup, Technology } from 'web-check-live/utils/result-processor';
4 | import colors from 'web-check-live/styles/colors';
5 | import Card from 'web-check-live/components/Form/Card';
6 | import Heading from 'web-check-live/components/Form/Heading';
7 |
8 | const Outer = styled(Card)`
9 | grid-row: span 2
10 | `;
11 |
12 | const Row = styled.div`
13 | display: flex;
14 | justify-content: space-between;
15 | padding: 0.25rem;
16 | &:not(:last-child) { border-bottom: 1px solid ${colors.primaryTransparent}; }
17 | span.lbl { font-weight: bold; }
18 | span.val {
19 | max-width: 200px;
20 | white-space: nowrap;
21 | overflow: hidden;
22 | text-overflow: ellipsis;
23 | }
24 | `;
25 |
26 | const ListRow = (props: { list: Technology[], title: string }) => {
27 | const { list, title } = props;
28 | return (
29 | <>
30 | {title}
31 | { list.map((entry: Technology, index: number) => {
32 | return (
33 | { entry.Name }
34 | )}
35 | )}
36 | >
37 | );
38 | }
39 |
40 | const BuiltWithCard = (props: { data: TechnologyGroup[]}): JSX.Element => {
41 | // const { created, updated, expires, nameservers } = whois;
42 | return (
43 |
44 | Technologies
45 | { props.data.map((group: TechnologyGroup) => {
46 | return (
47 |
48 | );
49 | })}
50 | {/* { created && }
51 | { updated && }
52 | { expires && }
53 | { nameservers && } */}
54 |
55 | );
56 | }
57 |
58 | export default BuiltWithCard;
59 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/CarbonFootprint.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import styled from '@emotion/styled';
3 | import { Card } from 'web-check-live/components/Form/Card';
4 | import Row from 'web-check-live/components/Form/Row';
5 | import colors from 'web-check-live/styles/colors';
6 |
7 | const LearnMoreInfo = styled.p`
8 | font-size: 0.8rem;
9 | margin-top: 0.5rem;
10 | opacity: 0.75;
11 | a { color: ${colors.primary}; }
12 | `;
13 |
14 | const CarbonCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
15 | const carbons = props.data.statistics;
16 | const initialUrl = props.data.scanUrl;
17 |
18 | const [carbonData, setCarbonData] = useState<{c?: number, p?: number}>({});
19 |
20 | useEffect(() => {
21 | const fetchCarbonData = async () => {
22 | try {
23 | const response = await fetch(`https://api.websitecarbon.com/b?url=${encodeURIComponent(initialUrl)}`);
24 | const data = await response.json();
25 | setCarbonData(data);
26 | } catch (error) {
27 | console.error('Error fetching carbon data:', error);
28 | }
29 | };
30 | fetchCarbonData();
31 | }, [initialUrl]);
32 |
33 | return (
34 |
35 | { (!carbons?.adjustedBytes && !carbonData.c) && Unable to calculate carbon footprint for host
}
36 | { carbons?.adjustedBytes > 0 && <>
37 |
38 |
39 |
40 | >}
41 | {carbonData.c &&
}
42 | {carbonData.p &&
}
43 |
44 | Learn more at websitecarbon.com
45 |
46 | );
47 | }
48 |
49 | export default CarbonCard;
50 |
--------------------------------------------------------------------------------
/api/dns.js:
--------------------------------------------------------------------------------
1 | import dns from 'dns';
2 | import util from 'util';
3 | import middleware from './_common/middleware.js';
4 |
5 | const dnsHandler = async (url) => {
6 | let hostname = url;
7 |
8 | // Handle URLs by extracting hostname
9 | if (hostname.startsWith('http://') || hostname.startsWith('https://')) {
10 | hostname = new URL(hostname).hostname;
11 | }
12 |
13 | try {
14 | const lookupPromise = util.promisify(dns.lookup);
15 | const resolve4Promise = util.promisify(dns.resolve4);
16 | const resolve6Promise = util.promisify(dns.resolve6);
17 | const resolveMxPromise = util.promisify(dns.resolveMx);
18 | const resolveTxtPromise = util.promisify(dns.resolveTxt);
19 | const resolveNsPromise = util.promisify(dns.resolveNs);
20 | const resolveCnamePromise = util.promisify(dns.resolveCname);
21 | const resolveSoaPromise = util.promisify(dns.resolveSoa);
22 | const resolveSrvPromise = util.promisify(dns.resolveSrv);
23 | const resolvePtrPromise = util.promisify(dns.resolvePtr);
24 |
25 | const [a, aaaa, mx, txt, ns, cname, soa, srv, ptr] = await Promise.all([
26 | lookupPromise(hostname),
27 | resolve4Promise(hostname).catch(() => []), // A record
28 | resolve6Promise(hostname).catch(() => []), // AAAA record
29 | resolveMxPromise(hostname).catch(() => []), // MX record
30 | resolveTxtPromise(hostname).catch(() => []), // TXT record
31 | resolveNsPromise(hostname).catch(() => []), // NS record
32 | resolveCnamePromise(hostname).catch(() => []), // CNAME record
33 | resolveSoaPromise(hostname).catch(() => []), // SOA record
34 | resolveSrvPromise(hostname).catch(() => []), // SRV record
35 | resolvePtrPromise(hostname).catch(() => []) // PTR record
36 | ]);
37 |
38 | return {
39 | A: a,
40 | AAAA: aaaa,
41 | MX: mx,
42 | TXT: txt,
43 | NS: ns,
44 | CNAME: cname,
45 | SOA: soa,
46 | SRV: srv,
47 | PTR: ptr
48 | };
49 | } catch (error) {
50 | throw new Error(error.message);
51 | }
52 | };
53 |
54 | export const handler = middleware(dnsHandler);
55 | export default handler;
56 |
--------------------------------------------------------------------------------
/api/legacy-rank.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import unzipper from 'unzipper';
3 | import csv from 'csv-parser';
4 | import fs from 'fs';
5 | import middleware from './_common/middleware.js';
6 |
7 | // Should also work with the following sources:
8 | // https://www.domcop.com/files/top/top10milliondomains.csv.zip
9 | // https://tranco-list.eu/top-1m.csv.zip
10 | // https://www.domcop.com/files/top/top10milliondomains.csv.zip
11 | // https://radar.cloudflare.com/charts/LargerTopDomainsTable/attachment?id=525&top=1000000
12 | // https://statvoo.com/dl/top-1million-sites.csv.zip
13 |
14 | const FILE_URL = 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip';
15 | const TEMP_FILE_PATH = '/tmp/top-1m.csv';
16 |
17 | const rankHandler = async (url) => {
18 | let domain = null;
19 |
20 | try {
21 | domain = new URL(url).hostname;
22 | } catch (e) {
23 | throw new Error('Invalid URL');
24 | }
25 |
26 | // Download and unzip the file if not in cache
27 | if (!fs.existsSync(TEMP_FILE_PATH)) {
28 | const response = await axios({
29 | method: 'GET',
30 | url: FILE_URL,
31 | responseType: 'stream'
32 | });
33 |
34 | await new Promise((resolve, reject) => {
35 | response.data
36 | .pipe(unzipper.Extract({ path: '/tmp' }))
37 | .on('close', resolve)
38 | .on('error', reject);
39 | });
40 | }
41 |
42 | // Parse the CSV and find the rank
43 | return new Promise((resolve, reject) => {
44 | const csvStream = fs.createReadStream(TEMP_FILE_PATH)
45 | .pipe(csv({
46 | headers: ['rank', 'domain'],
47 | }))
48 | .on('data', (row) => {
49 | if (row.domain === domain) {
50 | csvStream.destroy();
51 | resolve({
52 | domain: domain,
53 | rank: row.rank,
54 | isFound: true,
55 | });
56 | }
57 | })
58 | .on('end', () => {
59 | resolve({
60 | skipped: `Skipping, as ${domain} is not present in the Umbrella top 1M list.`,
61 | domain: domain,
62 | isFound: false,
63 | });
64 | })
65 | .on('error', reject);
66 | });
67 | };
68 |
69 | export const handler = middleware(rankHandler);
70 | export default handler;
71 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Sitemap.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row, { ExpandableRow } from 'web-check-live/components/Form/Row';
4 | import colors from 'web-check-live/styles/colors';
5 |
6 | const cardStyles = `
7 | max-height: 50rem;
8 | overflow-y: auto;
9 | a {
10 | color: ${colors.primary};
11 | }
12 | small {
13 | margin-top: 1rem;
14 | opacity: 0.5;
15 | display: block;
16 | a { color: ${colors.primary}; }
17 | }
18 | `;
19 |
20 | const SitemapCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
21 | const normalSiteMap = props.data.url || props.data.urlset?.url || null;
22 | const siteMapIndex = props.data.sitemapindex?.sitemap || null;
23 |
24 | const makeExpandableRowData = (site: any) => {
25 | const results = [];
26 | if (site.lastmod) { results.push({lbl: 'Last Modified', val: site.lastmod[0]}); }
27 | if (site.changefreq) { results.push({lbl: 'Change Frequency', val: site.changefreq[0]}); }
28 | if (site.priority) { results.push({lbl: 'Priority', val: site.priority[0]}); }
29 | return results;
30 | };
31 |
32 | const getPathFromUrl = (url: string) => {
33 | try {
34 | const urlObj = new URL(url);
35 | return urlObj.pathname;
36 | } catch (e) {
37 | return url;
38 | }
39 | };
40 |
41 | return (
42 |
43 | {
44 | normalSiteMap && normalSiteMap.map((subpage: any, index: number) => {
45 | return ( )
46 | })
47 | }
48 | { siteMapIndex &&
49 | This site returns a sitemap index, which is a list of sitemaps.
50 |
}
51 | {
52 | siteMapIndex && siteMapIndex.map((subpage: any, index: number) => {
53 | return ({getPathFromUrl(subpage.loc[0])}
);
54 | })
55 | }
56 |
57 | );
58 | }
59 |
60 | export default SitemapCard;
61 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/MailConfig.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 | import Heading from 'web-check-live/components/Form/Heading';
5 | import colors from 'web-check-live/styles/colors';
6 |
7 | const cardStyles = ``;
8 |
9 | const MailConfigCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
10 | const mailServer = props.data;
11 | const txtRecords = (mailServer.txtRecords || []).join('').toLowerCase() || '';
12 | return (
13 |
14 | Mail Security Checklist
15 |
16 |
17 |
18 |
19 |
20 | { mailServer.mxRecords && MX Records }
21 | { mailServer.mxRecords && mailServer.mxRecords.map((record: any, index: number) => (
22 |
23 | {record.exchange}
24 | {record.priority ? `Priority: ${record.priority}` : ''}
25 |
26 | ))
27 | }
28 | { mailServer.mailServices.length > 0 && External Mail Services }
29 | { mailServer.mailServices && mailServer.mailServices.map((service: any, index: number) => (
30 |
31 | ))
32 | }
33 |
34 | { mailServer.txtRecords && Mail-related TXT Records }
35 | { mailServer.txtRecords && mailServer.txtRecords.map((record: any, index: number) => (
36 |
37 | {record}
38 |
39 | ))
40 | }
41 |
42 | );
43 | }
44 |
45 | export default MailConfigCard;
46 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/SocialTags.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row from 'web-check-live/components/Form/Row';
4 | import colors from 'web-check-live/styles/colors';
5 |
6 | const cardStyles = `
7 | .banner-image img {
8 | width: 100%;
9 | border-radius: 4px;
10 | margin: 0.5rem 0;
11 | }
12 | .color-field {
13 | border-radius: 4px;
14 | &:hover {
15 | color: ${colors.primary};
16 | }
17 | }
18 | `;
19 |
20 | const OgBanner = ({ ogImage, ogUrl }: { ogImage: string; ogUrl?: string }): JSX.Element => {
21 | const urlCover = ogImage.startsWith("/") && ogUrl ? `${ogUrl}${ogImage}` : ogImage;
22 | return (
23 |
24 |
25 |
26 | );
27 | };
28 |
29 | const SocialTagsCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
30 | const tags = props.data;
31 | return (
32 |
33 | { tags.title &&
}
34 | { tags.description &&
}
35 | { tags.keywords &&
}
36 | { tags.canonicalUrl &&
}
37 | { tags.themeColor &&
38 | Theme Color
39 | {tags.themeColor}
40 |
}
41 | { tags.twitterSite &&
42 | Twitter Site
43 | {tags.twitterSite}
44 |
}
45 | { tags.author &&
}
46 | { tags.publisher &&
}
47 | { tags.generator &&
}
48 | {tags.ogImage && }
49 |
50 | );
51 | }
52 |
53 | export default SocialTagsCard;
54 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/Cookies.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import { ExpandableRow } from 'web-check-live/components/Form/Row';
3 | import type { Cookie } from 'web-check-live/utils/result-processor';
4 |
5 | export const parseHeaderCookies = (cookiesHeader: string[]): Cookie[] => {
6 | if (!cookiesHeader || !cookiesHeader.length) return [];
7 | const cookies = cookiesHeader.flatMap(cookieHeader => {
8 | return cookieHeader.split(/,(?=\s[A-Za-z0-9]+=)/).map(cookieString => {
9 | const [nameValuePair, ...attributePairs] = cookieString.split('; ').map(part => part.trim());
10 | const [name, value] = nameValuePair.split('=');
11 | const attributes: Record = {};
12 | attributePairs.forEach(pair => {
13 | const [attributeName, attributeValue = ''] = pair.split('=');
14 | attributes[attributeName] = attributeValue;
15 | });
16 | return { name, value, attributes };
17 | });
18 | });
19 | return cookies;
20 | };
21 |
22 | const CookiesCard = (props: { data: any, title: string, actionButtons: any}): JSX.Element => {
23 | const headerCookies = parseHeaderCookies(props.data.headerCookies) || [];
24 | const clientCookies = props.data.clientCookies || [];
25 | return (
26 |
27 | {
28 | headerCookies.map((cookie: any, index: number) => {
29 | const attributes = Object.keys(cookie.attributes).map((key: string) => {
30 | return { lbl: key, val: cookie.attributes[key] }
31 | });
32 | return (
33 |
34 | )
35 | })
36 | }
37 | {
38 | clientCookies.map((cookie: any) => {
39 | const nameValPairs = Object.keys(cookie).map((key: string) => { return { lbl: key, val: cookie[key] }});
40 | return (
41 |
42 | );
43 | })
44 | }
45 |
46 | );
47 | }
48 |
49 | export default CookiesCard;
50 |
--------------------------------------------------------------------------------
/src/pages/account/index.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import BaseLayout from '@layouts/Base.astro';
3 | import NavBar from '@components/scafold/Nav.astro';
4 | import Footer from '@components/scafold/Footer.astro';
5 | import Icon from '@components/molecules/Icon.svelte';
6 |
7 | ---
8 |
9 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
Account management is currently under development.
23 |
24 | Once complete, you will be able to login to your account to manage API
25 | access, save reports, enable website change notificiations and more!
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
80 |
--------------------------------------------------------------------------------
/api/linked-pages.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import cheerio from 'cheerio';
3 | import urlLib from 'url';
4 | import middleware from './_common/middleware.js';
5 |
6 | const linkedPagesHandler = async (url) => {
7 | const response = await axios.get(url);
8 | const html = response.data;
9 | const $ = cheerio.load(html);
10 | const internalLinksMap = new Map();
11 | const externalLinksMap = new Map();
12 |
13 | // Get all links on the page
14 | $('a[href]').each((i, link) => {
15 | const href = $(link).attr('href');
16 | const absoluteUrl = urlLib.resolve(url, href);
17 |
18 | // Check if absolute / relative, append to appropriate map or increment occurrence count
19 | if (absoluteUrl.startsWith(url)) {
20 | const count = internalLinksMap.get(absoluteUrl) || 0;
21 | internalLinksMap.set(absoluteUrl, count + 1);
22 | } else if (href.startsWith('http://') || href.startsWith('https://')) {
23 | const count = externalLinksMap.get(absoluteUrl) || 0;
24 | externalLinksMap.set(absoluteUrl, count + 1);
25 | }
26 | });
27 |
28 | // Sort by most occurrences, remove supplicates, and convert to array
29 | const internalLinks = [...internalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]);
30 | const externalLinks = [...externalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]);
31 |
32 | // If there were no links, then mark as skipped and show reasons
33 | if (internalLinks.length === 0 && externalLinks.length === 0) {
34 | return {
35 | statusCode: 400,
36 | body: {
37 | skipped: 'No internal or external links found. '
38 | + 'This may be due to the website being dynamically rendered, using a client-side framework (like React), and without SSR enabled. '
39 | + 'That would mean that the static HTML returned from the HTTP request doesn\'t contain any meaningful content for Web-Check to analyze. '
40 | + 'You can rectify this by using a headless browser to render the page instead.',
41 | },
42 | };
43 | }
44 |
45 | return { internal: internalLinks, external: externalLinks };
46 | };
47 |
48 | export const handler = middleware(linkedPagesHandler);
49 | export default handler;
50 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/SiteFeatures.tsx:
--------------------------------------------------------------------------------
1 | import { Card } from 'web-check-live/components/Form/Card';
2 | import colors from 'web-check-live/styles/colors';
3 | import Row from 'web-check-live/components/Form/Row';
4 | import Heading from 'web-check-live/components/Form/Heading';
5 |
6 | const styles = `
7 | .content {
8 | max-height: 50rem;
9 | overflow-y: auto;
10 | }
11 |
12 | .scan-date {
13 | font-size: 0.8rem;
14 | margin-top: 0.5rem;
15 | opacity: 0.75;
16 | }
17 | `;
18 |
19 | const formatDate = (timestamp: number): string => {
20 | if (isNaN(timestamp) || timestamp <= 0) return 'No Date';
21 |
22 | const date = new Date(timestamp * 1000);
23 |
24 | if (isNaN(date.getTime())) return 'Unknown';
25 |
26 | const formatter = new Intl.DateTimeFormat('en-GB', {
27 | day: 'numeric',
28 | month: 'long',
29 | year: 'numeric',
30 | hour: '2-digit',
31 | minute: '2-digit',
32 | hour12: true
33 | });
34 |
35 | return formatter.format(date);
36 | }
37 |
38 |
39 |
40 | const SiteFeaturesCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => {
41 | const features = props.data;
42 | return (
43 |
44 |
45 | { (features?.groups || []).filter((group: any) => group.categories.length > 0).map((group: any, index: number) => (
46 |
47 | {group.name}
48 | { group.categories.map((category: any, subIndex: number) => (
49 | //
50 |
51 | {category.name}
52 | {category.live} Live {category.dead ? `(${category.dead} dead)` : ''}
53 |
54 | ))
55 | }
56 |
57 | ))
58 | }
59 |
60 | Last scanned on {formatDate(features.last)}
61 |
62 | );
63 | }
64 |
65 | export default SiteFeaturesCard;
66 |
--------------------------------------------------------------------------------
/public/assets/badges/sponsor.svg:
--------------------------------------------------------------------------------
1 | Sponsor: Alicia Sykes Sponsor Sponsor Alicia Sykes Alicia Sykes
--------------------------------------------------------------------------------
/public/assets/badges/github.svg:
--------------------------------------------------------------------------------
1 | GitHub: Lissy93/Web Check GitHub GitHub Lissy93/Web Check Lissy93/Web Check
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/WhoIs.tsx:
--------------------------------------------------------------------------------
1 |
2 | import styled from '@emotion/styled';
3 | import type { Whois } from 'web-check-live/utils/result-processor';
4 | import colors from 'web-check-live/styles/colors';
5 | import { Card } from 'web-check-live/components/Form/Card';
6 | import Heading from 'web-check-live/components/Form/Heading';
7 |
8 | const Row = styled.div`
9 | display: flex;
10 | justify-content: space-between;
11 | padding: 0.25rem;
12 | &:not(:last-child) { border-bottom: 1px solid ${colors.primaryTransparent}; }
13 | span.lbl { font-weight: bold; }
14 | span.val {
15 | max-width: 200px;
16 | white-space: nowrap;
17 | overflow: hidden;
18 | text-overflow: ellipsis;
19 | }
20 | `;
21 |
22 | const formatDate = (dateString: string): string => {
23 | const date = new Date(dateString);
24 | const formatter = new Intl.DateTimeFormat('en-GB', {
25 | day: 'numeric',
26 | month: 'long',
27 | year: 'numeric'
28 | });
29 | return formatter.format(date);
30 | }
31 |
32 | const DataRow = (props: { lbl: string, val: string }) => {
33 | const { lbl, val } = props;
34 | return (
35 |
36 | {lbl}
37 | {val}
38 |
39 | );
40 | };
41 |
42 | const ListRow = (props: { list: string[], title: string }) => {
43 | const { list, title } = props;
44 | return (
45 | <>
46 | {title}
47 | { list.map((entry: string, index: number) => {
48 | return (
49 | { entry }
50 | )}
51 | )}
52 | >
53 | );
54 | }
55 |
56 | const WhoIsCard = (props: { data: Whois, title: string, actionButtons: any }): JSX.Element => {
57 | const whois = props.data;
58 | const { created, updated, expires, nameservers } = whois;
59 | return (
60 |
61 | { created && }
62 | { updated && }
63 | { expires && }
64 | { nameservers && }
65 |
66 | );
67 | }
68 |
69 | export default WhoIsCard;
70 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Results/SecurityTxt.tsx:
--------------------------------------------------------------------------------
1 |
2 | import { Card } from 'web-check-live/components/Form/Card';
3 | import Row, { Details } from 'web-check-live/components/Form/Row';
4 | import colors from 'web-check-live/styles/colors';
5 |
6 | const cardStyles = `
7 | small {
8 | margin-top: 1rem;
9 | opacity: 0.5;
10 | display: block;
11 | a { color: ${colors.primary}; }
12 | }
13 | summary {
14 | padding: 0.5rem 0 0 0.5rem !important;
15 | cursor: pointer;
16 | font-weight: bold;
17 | }
18 | pre {
19 | background: ${colors.background};
20 | padding: 0.5rem 0.25rem;
21 | border-radius: 4px;
22 | overflow: auto;
23 | }
24 | `;
25 |
26 | const getPagePath = (url: string): string => {
27 | try {
28 | return new URL(url).pathname;
29 | } catch (error) {
30 | return url;
31 | }
32 | }
33 |
34 | const SecurityTxtCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => {
35 | const securityTxt = props.data;
36 | return (
37 |
38 |
39 | { securityTxt.isPresent && (
40 | <>
41 |
42 |
43 | {securityTxt.fields && Object.keys(securityTxt.fields).map((field: string, index: number) => {
44 | if (securityTxt.fields[field].includes('http')) return (
45 |
46 | {field}
47 | {getPagePath(securityTxt.fields[field])}
48 |
49 | );
50 | return (
51 |
52 | );
53 | })}
54 |
55 | View Full Policy
56 | {securityTxt.content}
57 |
58 | >
59 | )}
60 | {!securityTxt.isPresent && (
61 | Having a security.txt ensures security researchers know how and where to safely report vulnerabilities.
62 | )}
63 |
64 | );
65 | }
66 |
67 | export default SecurityTxtCard;
68 |
--------------------------------------------------------------------------------
/src/web-check-live/components/Form/Heading.tsx:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled';
2 | import colors from 'web-check-live/styles/colors';
3 | import { TextSizes } from 'web-check-live/styles/typography';
4 | import type { ReactNode } from 'react';
5 |
6 | interface HeadingProps {
7 | as?: 'h1' | 'h2' | 'h3' | 'h4' | 'p';
8 | align?: 'left' | 'center' | 'right';
9 | color?: string;
10 | size?: 'xSmall' | 'small' | 'medium' | 'large' | 'xLarge';
11 | inline?: boolean;
12 | children: ReactNode;
13 | id?: string;
14 | className?: string;
15 | };
16 |
17 | const StyledHeading = styled.h1`
18 | margin: 0.5rem 0;
19 | text-shadow: 2px 2px 0px ${colors.bgShadowColor};
20 | display: flex;
21 | flex-wrap: wrap;
22 | gap: 1rem;
23 | align-items: center;
24 | font-size: ${TextSizes.medium};
25 | img { // Some titles have an icon
26 | width: 2.5rem;
27 | border-radius: 4px;
28 | }
29 | a { // If a title is a link, keep title styles
30 | color: inherit;
31 | text-decoration: none;
32 | display: flex;
33 | }
34 | ${props => {
35 | switch (props.size) {
36 | case 'xSmall': return `font-size: ${TextSizes.xSmall};`;
37 | case 'small': return `font-size: ${TextSizes.small};`;
38 | case 'medium': return `font-size: ${TextSizes.large};`;
39 | case 'large': return `font-size: ${TextSizes.xLarge};`;
40 | case 'xLarge': return `font-size: ${TextSizes.xLarge};`;
41 | }
42 | }};
43 | ${props => {
44 | switch (props.align) {
45 | case 'left': return 'text-align: left;';
46 | case 'right': return 'text-align: right;';
47 | case 'center': return 'text-align: center; justify-content: center;';
48 | }
49 | }};
50 | ${props => props.color ? `color: ${props.color};` : '' }
51 | ${props => props.inline ? 'display: inline;' : '' }
52 | `;
53 |
54 | const makeAnchor = (title: string): string => {
55 | return title.toLowerCase().replace(/[^\w\s]|_/g, "").replace(/\s+/g, "-");
56 | };
57 |
58 | const Heading = (props: HeadingProps): JSX.Element => {
59 | const { children, as, size, align, color, inline, id, className } = props;
60 | return (
61 |
62 | {children}
63 |
64 | );
65 | }
66 |
67 | export default Heading;
68 |
--------------------------------------------------------------------------------