Infrastructure
· 17 checks — DNS, redirects, IPv6, crawlability, URL variants, and domain intelligence rolled into one auditable list.BDNSSECUnsigned (DNSSEC not deployed)REVIEW
BCAA RecordsNo CAA records (any CA may issue certificates)REVIEW
CReverse DNSAction0/4 IPs match cert SANREVIEW
CCrawlabilityActionrobots.txt present, sitemap with 0 URLsREVIEW
Search engines may not be able to parse the sitemap. Fix XML validation errors.
An unparseable sitemap is silently ignored by Google — the URLs it advertises are never queued for crawl.
Learn more ▾ ▴
Google's sitemap parser is strict about XML validity. A single unescaped `&` or unclosed tag invalidates the whole file. Run your sitemap through a validator (Search Console's Sitemaps report flags it) and fix the offending entry. Most generators escape correctly; mistakes usually come from manually-written entries.
Source: sitemaps.org / Google Search Central
An empty sitemap provides no value. Add <url> entries for your pages.
An empty sitemap signals 'no content to index' to Google — actively harmful versus having no sitemap at all.
Learn more ▾ ▴
Google compares URLs in the sitemap against URLs it has crawled. An empty sitemap on a site with thousands of pages signals abandonment. Either populate it correctly (most CMSes auto-generate) or delete the file and let Google crawl normally.
Source: Google Search Central / sitemaps.org
Add a 'Sitemap:' directive to robots.txt so search engines can discover your sitemap.
robots.txt omits Sitemap: directive — crawlers must fetch /sitemap.xml by convention; reliable but missing the explicit hint.
Source: sitemaps.org
<!doctype html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Juvel — منتجات طبيعية ومستحضرات تجميل فاخرة من قلب الطبيعة" />
<link rel="icon" type="image/png" href="./images/logo.png" />
<link rel="apple-touch-icon" href="./images/logo.png" />
<link rel="preload" as="image" href="./images/hero.webp" fetchpriority="high" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700;900&family=Marcellus&display=swap"
rel="stylesheet"
/>
<title>Juvel | جوفيل — جمالك من الطبيعة</title>
<script type="module" crossorigin>(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))i(l);new MutationObserver(l=>{for(const u of l)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&i(d)}).observe(document,{childList:!0,subtree:!0});function s(l){const u={};return l.integrity&&(u.integrity=l.integrity),l.referrerPolicy&&(u.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?u.credentials="include":l.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function i(l){if(l.ep)return;l.ep=!0;const u=s(l);fetch(l.href,u)}})();var $h={exports:{}},Br={};var ty;function g4(){if(ty)return Br;ty=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function s(i,l,u){var d=null;if(u!==void 0&&(d=""+u),l.key!==void 0&&(d=""+l.key),"key"in l){u={};for(var f in l)f!=="key"&&(u[f]=l[f])}else u=l;return l=u.ref,{$$typeof:t,type:i,key:d,ref:l!==void 0?l:null,props:u}}return Br.Fragment=e,Br.jsx=s,Br.jsxs=s,Br}var ny;function x4(){return ny||(ny=1,$h.exports=g4()),$h.exports}var o=x4(),Bh={exports:{}},ge={};var sy;function y4(){if(sy)return ge;sy=1;var t=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),s=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),l=Symbol.for("react.profiler"),u=Symbol.for("react.consumer"),d=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),p=Symbol.for("react.memo"),x=Symbol.for("react.lazy"),y=Symbol.for("react.activity"),b=Symbol.iterator;function w(D){return D===null||typeof D!="object"?null:(D=b&&D[b]||D["@@iterator"],typeof D=="function"?D:null)}var j={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},N=Object.assign,_={};function k(D,J,ne){this.props=D,this.context=J,this.refs=_,this.updater=ne||j}k.prototype.isReactComponent={},k.prototype.setState=function(D,J){if(typeof D!="object"&&typeof D!="function"&&D!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,D,J,"setState")},k.prototype.forceUpdate=function(D){this.updater.enqueueForceUpdate(this,D,"forceUpdate")};function R(){}R.prototype=k.prototype;function M(D,J,ne){this.props=D,this.context=J,this.refs=_,this.updater=ne||j}var T=M.prototype=new R;T.constructor=M,N(T,k.prototype),T.isPureReactComponent=!0;var F=Array.isArray;function I(){}var E={H:null,A:null,T:null,S:null},L=Object.prototype.hasOwnProperty;function q(D,J,ne){var re=ne.ref;return{$$typeof:t,type:D,key:J,ref:re!==void 0?re:null,props:ne}}function G(D,J){return q(D.type,J,D.props)}function me(D){return typeof D=="object"&&D!==null&&D.$$typeof===t}function xe(D){var J={"=":"=0",":":"=2"};return"$"+D.replace(/[=:]/g,function(ne){return J[ne]})}var Ce=/\/+/g;function ut(D,J){return typeof D=="object"&&D!==null&&D.key!=null?xe(""+D.key):J.toString(36)}function W(D){switch(D.status){case"fulfilled":return D.value;case"rejected":throw D.reason;default:switch(typeof D.status=="string"?D.then(I,I):(D.status="pending",D.then(function(J){D.status==="pending"&&(D.status="fulfilled",D.value=J)},function(J){D.status==="pending"&&(D.status="rejected",D.reason=J)})),D.status){case"fulfilled":return D.value;case"rejected":throw D.reason}}throw D}function B(D,J,ne,re,ye){var we=typeof D;(we==="undefined"||we==="boolean")&&(D=null);var Me=!1;if(D===null)Me=!0;else switch(we){case"bigint":case"string":case"number":Me=!0;break;case"object":switch(D.$$typeof){case t:case e:Me=!0;break;case x:return Me=D._init,B(Me(D._payload),J,ne,re,ye)}}if(Me)return ye=ye(D),Me=re===""?"."+ut(D,0):re,F(ye)?(ne="",Me!=null&&(ne=Me.replace(Ce,"$&/")+"/"),B(ye,J,ne,"",function(Yi){return Yi})):ye!=null&&(me(ye)&&(ye=G(ye,ne+(ye.key==null||D&&D.key===ye.key?"":(""+ye.key).replace(Ce,"$&/")+"/")+Me)),J.push(ye)),1;Me=0;var At=re===""?".":re+":";if(F(D))for(var We=0;We<D.length;We++)re=D[We],we=At+ut(re,We),Me+=B(re,J,ne,we,ye);else if(We=w(D),typeof We=="function")for(D=We.call(D),We=0;!(re=D.next()).done;)re=re.value,we=At+ut(re,We++),Me+=B(re,J,ne,we,ye);else if(we==="object"){if(typeof D.then=="function")return B(W(D),J,ne,re,ye);throw J=String(D),Error("Objects are not valid as a React child (found: "+(J==="[object Object]"?"object with keys {"+Object.keys(D).join(", ")+"}":J)+"). If you meant to render a collection of children, use an array instead.")}return Me}function X(D,J,ne){if(D==null)return D;var re=[],ye=0;return B(D,re,"","",function(we){return J.call(ne,we,ye++)}),re}function ee(D){if(D._status===-1){var J=D._result;J=J(),J.then(function(ne){(D._status===0||D._status===-1)&&(D._status=1,D._result=ne)},function(ne){(D._status===0||D._status===-1)&&(D._status=2,D._result=ne)}),D._status===-1&&(D._status=0,D._result=J)}if(D._status===1)return D._result.default;throw D._result}var de=typeof reportError=="function"?reportError:function(D){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var J=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof D=="object"&&D!==null&&typeof D.message=="string"?String(D.message):String(D),error:D});if(!window.dispatchEvent(J))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",D);return}console.error(D)},ke={map:X,forEach:function(D,J,ne){X(D,function(){J.apply(this,arguments)},ne)},count:function(D){var J=0;return X(D,function(){J++}),J},toArray:function(D){return X(D,function(J){return J})||[]},only:function(D){if(!me(D))throw Error("React.Children.only expected to receive a single React element child.");return D}};return ge.Activity=y,ge.Children=ke,ge.Component=k,ge.Fragment=s,ge.Profiler=l,ge.PureComponent=M,ge.StrictMode=i,ge.Suspense=g,ge.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=E,ge.__COMPILER_RUNTIME={__proto__:null,c:function(D){return E.H.useMemoCache(D)}},ge.cache=function(D){return function(){return D.apply(null,arguments)}},ge.cacheSignal=function(){return null},ge.cloneElement=function(D,J,ne){if(D==null)throw Error("The argument must be a React element, but you passed "+D+".");var re=N({},D.props),ye=D.key;if(J!=null)for(we in J.key!==void 0&&(ye=""+J.key),J)!L.call(J,we)||we==="key"||we==="__self"||we==="__source"||we==="ref"&&J.ref===void 0||(re[we]=J[we]);var we=arguments.length-2;if(we===1)re.children=ne;else if(1<we){for(var Me=Array(we),At=0;At<we;At++)Me[At]=arguments[At+2];re.children=Me}return q(D.type,ye,re)},ge.createContext=function(D){return D={$$typeof:d,_currentValue:D,_currentValue2:D,_threadCount:0,Provider:null,Consumer:null},D.Provider=D,D.Consumer={$$typeof:u,_context:D},D},ge.createElement=function(D,J,ne){var re,ye={},we=null;if(J!=null)for(re in J.key!==void 0&&(we=""+J.key),J)L.call(J,re)&&re!=="key"&&re!=="__self"&&re!=="__source"&&(ye[re]=J[re]);var Me=arguments.length-2;if(Me===1)ye.children=ne;else if(1<Me){for(var At=Array(Me),We=0;We<Me;We++)At[We]=arguments[We+2];ye.children=At}if(D&&D.defaultProps)for(re in Me=D.defaultProps,Me)ye[re]===void 0&&(ye[re]=Me[re]);return q(D,we,ye)},ge.createRef=function(){return{current:null}},ge.forwardRef=function(D){return{$$typeof:f,render:D}},ge.isValidElement=me,ge.lazy=function(D){return{$$typeof:x,_payload:{_status:-1,_result:D},_init:ee}},ge.memo=function(D,J){return{$$typeof:p,type:D,compare:J===void 0?null:J}},ge.startTransition=function(D){var J=E.T,ne={};E.T=ne;try{var re=D(),ye=E.S;ye!==null&&ye(ne,re),typeof re=="object"&&re!==null&&typeof re.then=="function"&&re.then(I,de)}catch(we){de(we)}finally{J!==null&&ne.types!==null&&(J.types=ne.types),E.T=J}},ge.unstable_useCacheRefresh=function(){return E.H.useCacheRefresh()},ge.use=function(D){return E.H.use(D)},ge.useActionState=function(D,J,ne){return E.H.useActionState(D,J,ne)},ge.useCallback=function(D,J){return E.H.useCallback(D,J)},ge.useContext=function(D){return E.H.useContext(D)},ge.useDebugValue=function(){},ge.useDeferredValue=function(D,J){return E.H.useDeferredValue(D,J)},ge.useEffect=function(D,J){return E.H.useEffect(D,J)},ge.useEffectEvent=function(D){return E.H.useEffectEvent(D)},ge.useId=function(){return E.H.useId()},ge.useImperativeHandle=function(D,J,ne){return E.H.useImperativeHandle(D,J,ne)},ge.useInsertionEffect=function(D,J){return E.H.useInsertionEffect(D,J)},ge.useLayoutEffect=function(D,J){return E.H.useLayoutEffect(D,J)},ge.useMemo=function(D,J){return E.H.useMemo(D,J)},ge.useOptimistic=function(D,J){return E.H.useOptimistic(D,J)},ge.useReducer=function(D,J,ne){return E.H.useReducer(D,J,ne)},ge.useRef=function(D){return E.H.useRef(D)},ge.useState=function(D){return E.H.useState(D)},ge.useSyncExternalStore=function(D,J,ne){return E.H.useSyncExternalStore(D,J,ne)},ge.useTransition=function(){return E.H.useTransition()},ge.version="19.2.6",ge}var ay;function cm(){return ay||(ay=1,Bh.exports=y4()),Bh.exports}var A=cm(),Vh={exports:{}},Vr={},qh={exports:{}},Hh={};var iy;function b4(){return iy||(iy=1,(function(t){function e(B,X){var ee=B.length;B.push(X);e:for(;0<ee;){var de=ee-1>>>1,ke=B[de];if(0<l(ke,X))B[de]=X,B[ee]=ke,ee=de;else break e}}function s(B){return B.length===0?null
BTLS Certificate Expiry & Recommendations88 days until leaf cert expires — 3 issues to addressREVIEW
Certificate validity
Recommended actions
- Enable HSTS: Strict-Transport-Security: max-age=31536000; includeSubDomains
- Enable DNSSEC on your domain for DNS spoofing protection
- Enable OCSP stapling on your TLS server to remove a CA roundtrip and protect user privacy
BCDN & DeliveryCloudflare PagesREVIEW
BCDN Cache ObservabilityNo CDN cache-status headers in the responseREVIEW
BOperational Status PageNo status page link detectedREVIEW
A+DNS Records2 A records, 38 ms lookupPASS
| A | 172.66.44.158, 172.66.47.98 |
| AAAA | 2606:4700:310c::ac42:2f62, 2606:4700:310c::ac42:2c9e |
| CNAME | — |
| NS | rose.ns.cloudflare.com, memphis.ns.cloudflare.com |
| MX | — |
| TXT | — |
| CAA | Lookup not available with standard resolver |
SPF helps prevent email spoofing. Add a TXT record starting with 'v=spf1'.
Without SPF, receiving servers can't validate sending IPs — your domain is easier to spoof in phishing.
Learn more ▾ ▴
SPF complements DMARC. Both should be published. SPF records list authorized sending IPs (e.g., `v=spf1 include:_spf.google.com ~all` for Google Workspace). After publishing, verify in Google Postmaster Tools or mxtoolbox.
Source: RFC 7208 (SPF)
A+Subdomain TakeoverNo subdomain takeover risk detectedPASS
A+Multi-Resolver DNS SpeedMean 18ms across 3 resolvers (spread 19ms)PASS
A+Redirect ChainNo redirects — direct accessPASS
https://juvel.pages.dev
177 ms · HTTP/1.1 FINAL
| # | URL | Status | Time | Protocol | Server |
|---|---|---|---|---|---|
| 1 | https://juvel.pages.dev | 200 | 177 ms | HTTP/1.1 | cloudflare |
A+IPv6 ReadinessIPv6 reachable (17 ms)PASS
A+URL Variantswww/non-www, trailing slash, HTTP→HTTPSPASS
www / non-www
HTTP → HTTPS
Consistent
A+HTTP Probe TimingTotal 225 ms — DNS, TCP, TLS, TTFB, content transfer breakdownPASS
Connection waterfall
A+Health Check EndpointHealth endpoint at https://juvel.pages.dev/health (HTTP 200)PASS
Domain IntelligenceDomain intelligence data not availableINFO
RDAP and WHOIS lookup both failed