Deploy and Harden with Cloudflare Pages

Deploy a static site to Cloudflare Pages and secure it with response headers.

Introduction

30 Second Summary

A website can look polished on your computer while still being invisible to everyone else. Once it goes online, the browser can show whether the hosting service delivered it securely.

In this project, you will publish a Cloud Security Checkpoint website with Cloudflare Pages. You will inspect its HTTPS delivery before adding a browser security policy.

What You'll Build

Your finished demo opens as a dark blue four-card site at a public pages.dev address with Chrome DevTools showing the anti-framing policy in its response.

By the end of this project, you'll have:

  • A responsive checkpoint page that presents the Build, Deploy, Inspect, and Harden workflow across four clear cards.
  • A public cloud deployment that anyone can open from your shareable pages.dev address.
  • A live security audit that shows HTTPS, certificate details, and Cloudflare response headers in Chrome DevTools. The response proves your clickjacking defense with X-Frame-Options: DENY.
  • Secret Mission: Override Cloudflare's default referrer policy with Referrer-Policy: no-referrer. Prove the new value reached the browser.

Are there any prerequisites?

You need basic Windows file navigation plus the installed Visual Studio Code and Google Chrome. The project guides you through creating and verifying your Cloudflare account.

Before We Start

Before any hands-on work begins, commit to building a public Cloud Security Checkpoint that secures its Cloudflare Pages response against framing. This gives every later action a clear purpose.

Set Up Your Account and Starter Page

Your Cloud Security Checkpoint needs a verified Cloudflare account before Cloudflare Pages can publish it later.

A small HTML page in Visual Studio Code gives you a fast local check in Google Chrome.

In this step, get ready to:
  • Finish Cloudflare account verification.
  • Prepare the local project folder in Visual Studio Code.
  • Display the starter page in Google Chrome.
Verify your Cloudflare account

Cloudflare uses email verification to confirm that you control the address attached to your account. This account gives you access to the dashboard used for deployment later.

This is the only point where the project touches your login details. Your password stays on Cloudflare's account page.

  • Open Cloudflare's official Create account guide in Google Chrome.
  • Follow the Sign up page link.
  • Enter your email address in the Email field.
  • Enter your password in the Password field.
  • Select Create Account.
  • Open the verification email from Cloudflare.
  • Follow the verification link in the email.
  • Sign in to the Cloudflare dashboard with your verified account.

You'll see the Cloudflare dashboard after signing in. That is the first dependency cleared: your verified account is ready for deployment later.

Verification Email Missing?

Check the spam folder for the verification message. Confirm that the account email address has no typing mistakes.

Help me troubleshoot Cloudflare account verification. You can also share the non-sensitive error text with the NextWork community.

Prepare your project folder

A dedicated folder keeps every file for this site in one place. Visual Studio Code treats an opened folder as a workspace.

  • Press Windows logo key + E to open File Explorer.
  • Select Documents in the navigation pane.
  • Select New in the File Explorer toolbar.
  • Select Folder.
  • Type first-cloud-security-site as the folder name.
  • Press Enter.

You'll see the first-cloud-security-site folder inside Documents.

  • Press the Windows logo key to open Windows search.
  • Type Visual Studio Code.
  • Press Enter.
  • Select File in the menu bar.
  • Select Open Folder....
  • Select the Documents\first-cloud-security-site folder.
  • Select Select Folder.
  • Confirm that you trust the folder if Workspace Trust appears.

You'll see first-cloud-security-site at the top of the Explorer view. Your workspace is now ready for its first file.

Folder Missing From the Explorer View?

Check that you selected the folder inside Documents. Use File followed by Open Folder... again if Visual Studio Code shows a different folder.

Help me open my project folder in Visual Studio Code.

Render your starter page

The index.html file is the entry page for this site. Its starter document supplies browser metadata plus one visible heading.

  • Select the Explorer view in the Activity Bar.
  • Select the New File... button.
  • Enter index.html as the file name.
  • Press Enter.
  • Build the starter document by pasting this code into index.html:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cloud Security Checkpoint</title>
  </head>
  <body>
    <h1>Cloud Security Checkpoint</h1>
  </body>
</html>

What Does This Code Do?

  • The <!doctype html> declaration tells the browser to use modern HTML rules.
  • The <html lang="en"> element declares English as the page language.
  • The <head> element stores browser metadata.
  • The <title> element names the browser tab.
  • The <h1> element creates the visible page heading.
  • Save index.html by pressing Ctrl+S.

✔️ Awesome, I've got everything!

Your saved starter file is ready for the browser check.

ⓧ I'd like to double check the full code

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cloud Security Checkpoint</title>
  </head>
  <body>
    <h1>Cloud Security Checkpoint</h1>
  </body>
</html>

This reference combines the complete document metadata with the visible starter heading.

Before you open the file, what heading do you expect the browser to display?

  • Switch back to File Explorer from earlier.
  • Double-click index.html to open it in Google Chrome.

You'll see the heading Cloud Security Checkpoint on a plain white page.

You have your first visible result: the local page renders in Google Chrome.

Starter Page Not Showing?

Confirm that the file is named index.html with no extra file extension. Save the file again if Google Chrome shows an older version.

Use the Windows app picker to choose Google Chrome if another application opens the file.

Help me troubleshoot my local starter page.

Your verified account is ready. Next, you will turn the starter page into the complete four-card checkpoint.

Build the Cloud Security Checkpoint

Your starter page now opens in Google Chrome with the Cloud Security Checkpoint heading. That quick result gives you a working local preview.

A single heading cannot show the full security workflow. You will turn it into a responsive page with HTML and CSS. The finished page still lacks a public pages.dev address or a cloud response to inspect.

In this step, get ready to:
  • Replace the starter page with the complete Cloud Security Checkpoint structure.
  • Style the page with a dark responsive layout.
  • Confirm the completed page remains a local file.
Build the page structure

The page structure gives each stage of the workflow its own card. A shared shell keeps the heading, introduction, cards, and footer together.

  • Return to the open index.html tab in Visual Studio Code.
  • Select all of the existing code in index.html.
  • Replace the selected code with this page shell:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cloud Security Checkpoint</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <main class="shell">
      <p class="eyebrow">FIRST CLOUD SECURITY PROJECT</p>
      <h1>Cloud Security Checkpoint</h1>
      <p class="intro">
        Follow four visible checks for a static site: build it, deploy it,
        inspect its delivery, and define a browser security policy.
      </p>

    </main>
  </body>
</html>

What Does This Code Do?

  • The stylesheet link tells the browser to load the visual rules from styles.css.
  • The shell class groups the page content inside one layout container.
  • The eyebrow and introduction establish the four-part security workflow.
  • Save index.html.
  • Switch back to the local page in Google Chrome.
  • Refresh the page.

You will see the eyebrow and workflow introduction beneath the main heading. The content still uses basic browser styling because styles.css does not exist yet.

Missing the New Introduction?

Check that you saved index.html. Confirm that Chrome still displays the file from Documents\first-cloud-security-site.

Make sure the closing </p> tag appears before </main>.

Help me find why the updated HTML is missing from my local page.

The shell now describes the project. The next block turns the four workflow stages into separate pieces that the stylesheet can arrange.

  • Return to index.html in Visual Studio Code.
  • Place your cursor on the blank line above </main>.
  • Add the workflow cards and footer with this code:
      <section class="status-grid" aria-label="Cloud security workflow">
        <article class="card">
          <span class="step-label">BUILD</span>
          <h2>Static files ready</h2>
          <p>Create a clear page with HTML and CSS before adding cloud complexity.</p>
        </article>

        <article class="card">
          <span class="step-label">DEPLOY</span>
          <h2>Public cloud address</h2>
          <p>Upload the same files to a managed static hosting platform.</p>
        </article>

        <article class="card">
          <span class="step-label">INSPECT</span>
          <h2>Delivery made visible</h2>
          <p>Use browser developer tools to examine the connection and response.</p>
        </article>

        <article class="card">
          <span class="step-label">HARDEN</span>
          <h2>Policy made explicit</h2>
          <p>Define a response header at the hosting layer and verify the result.</p>
        </article>
      </section>

      <footer>
        Built on Windows with HTML, CSS, Chrome DevTools, and Cloudflare Pages.
      </footer>

How Is the Workflow Organized?

  • The status-grid section groups all four stages into one layout region.
  • Each card article contains one stage label and one outcome.
  • The footer records the tools behind the finished checkpoint.
  • Save index.html.
  • Switch back to the local page in Google Chrome.
  • Refresh the page.

You will see four plain workflow sections labelled BUILD, DEPLOY, INSPECT, and HARDEN. You will also see the footer beneath them.

Missing a Workflow Card?

Confirm that every <article> has a matching </article> closing tag. Keep all four articles inside the status-grid section.

Help me fix a missing or misplaced workflow card in index.html.

✔️ Awesome, I've Got Everything

Great. Save index.html before you start styling it.

ⓧ I'd Like to Double Check the Full Code

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cloud Security Checkpoint</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <main class="shell">
      <p class="eyebrow">FIRST CLOUD SECURITY PROJECT</p>
      <h1>Cloud Security Checkpoint</h1>
      <p class="intro">
        Follow four visible checks for a static site: build it, deploy it,
        inspect its delivery, and define a browser security policy.
      </p>

      <section class="status-grid" aria-label="Cloud security workflow">
        <article class="card">
          <span class="step-label">BUILD</span>
          <h2>Static files ready</h2>
          <p>Create a clear page with HTML and CSS before adding cloud complexity.</p>
        </article>

        <article class="card">
          <span class="step-label">DEPLOY</span>
          <h2>Public cloud address</h2>
          <p>Upload the same files to a managed static hosting platform.</p>
        </article>

        <article class="card">
          <span class="step-label">INSPECT</span>
          <h2>Delivery made visible</h2>
          <p>Use browser developer tools to examine the connection and response.</p>
        </article>

        <article class="card">
          <span class="step-label">HARDEN</span>
          <h2>Policy made explicit</h2>
          <p>Define a response header at the hosting layer and verify the result.</p>
        </article>
      </section>

      <footer>
        Built on Windows with HTML, CSS, Chrome DevTools, and Cloudflare Pages.
      </footer>
    </main>
  </body>
</html>
Style the responsive layout

The class names in index.html act as hooks for the page design. The stylesheet uses those hooks to create the dark background, readable spacing, and card layout.

  • Select the first-cloud-security-site folder in the Visual Studio Code Explorer sidebar.
  • Use the new-file control at the top of the Explorer sidebar.
  • Name the new file styles.css.
  • Add the page foundation with this code:
:root {
  color-scheme: dark;
  font-family: "Segoe UI", Arial, sans-serif;
  background: #071426;
  color: #eaf2ff;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  background:
    radial-gradient(circle at top left, #173b67 0, transparent 38%),
    linear-gradient(145deg, #071426, #0b1f38);
}

What Creates the Dark Foundation?

  • The root rules establish the dark colour scheme and page typography.
  • The universal selector makes element dimensions include their borders and padding.
  • The body gradients create the dark blue background across the full browser height.
  • Save styles.css.
  • Switch back to the local page in Google Chrome.
  • Refresh the page.

You will see a dark blue gradient behind light text. The browser also uses the Segoe UI font when it is available.

Still Seeing a White Background?

Confirm that styles.css sits beside index.html in the same folder. Check that the stylesheet link still uses the exact filename styles.css.

Help me diagnose why styles.css is not changing my local page.

The colour palette is working. The next rules constrain the page width and establish a clear reading order.

  • Return to styles.css in Visual Studio Code.
  • Place your cursor below the closing brace of the body rule.
  • Add the shell and introductory typography with this code:
.shell {
  width: min(100% - 2rem, 980px);
  margin: 0 auto;
  padding: 4rem 0 2rem;
}

.eyebrow {
  margin: 0 0 0.75rem;
  color: #72d9ff;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.14em;
}

h1 {
  max-width: 760px;
  margin: 0;
  font-size: clamp(2.4rem, 8vw, 5.5rem);
  line-height: 0.98;
}

.intro {
  max-width: 680px;
  margin: 1.5rem 0 2.5rem;
  color: #b9c9dc;
  font-size: 1.1rem;
  line-height: 1.7;
}

How Does the Header Adapt?

  • The shell limits the content width while preserving space along both sides.
  • The eyebrow uses colour and letter spacing to act as a compact project label.
  • The heading size scales with the browser width while staying within set limits.
  • The introduction uses a narrower line length to remain readable.
  • Save styles.css.
  • Switch back to the local page in Google Chrome.
  • Refresh the page.

You will see the content centred inside the page. The main heading is now larger than the surrounding text.

Heading Still Looks Small?

Check that the h1 rule sits outside the preceding .eyebrow braces. Confirm that the heading in index.html still uses an <h1> element.

Help me fix the shell or heading styles on my local page.

The page hierarchy is now clear. The grid rules turn the four workflow stages into the main visual feature.

  • Return to styles.css in Visual Studio Code.
  • Place your cursor below the closing brace of the .intro rule.
  • Add the grid and card styling with this code:
.status-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.card {
  min-height: 210px;
  padding: 1.5rem;
  border: 1px solid #315476;
  border-radius: 18px;
  background: rgb(12 34 58 / 88%);
  box-shadow: 0 18px 45px rgb(0 0 0 / 18%);
}

.step-label {
  display: inline-block;
  padding: 0.35rem 0.65rem;
  border-radius: 999px;
  background: #123f61;
  color: #86e2ff;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.09em;
}

What Shapes the Workflow Cards?

  • The grid places the cards into two equal columns with consistent gaps.
  • Each card gains padding, rounded corners, a border, and a soft shadow.
  • Each step label becomes a compact pill above its card heading.
  • Save styles.css.
  • Switch back to the local page in Google Chrome.
  • Refresh the page.

You will see the four stages arranged as a two-column card grid. Each card has a rounded border and a blue step label.

Cards Still Appear as Plain Text?

Confirm that the HTML section uses class="status-grid". Check that every article uses class="card".

Help me match my card class names to the CSS selectors.

The desktop card grid is complete. The final rules refine the smaller text and collapse the grid when the browser becomes narrow.

  • Return to styles.css in Visual Studio Code.
  • Place your cursor below the closing brace of the .step-label rule.
  • Add the finishing rules and the 640px responsive breakpoint with this code:
h2 {
  margin: 1.1rem 0 0.7rem;
  font-size: 1.35rem;
}

.card p {
  margin: 0;
  color: #b9c9dc;
  line-height: 1.6;
}

footer {
  margin-top: 2rem;
  color: #8298af;
  font-size: 0.9rem;
}

@media (max-width: 640px) {
  .shell {
    padding-top: 2.5rem;
  }

  .status-grid {
    grid-template-columns: 1fr;
  }
}

How Does the Mobile Layout Work?

  • The card text uses a softer colour and extra line spacing for readability.
  • The footer sits below the card grid with a smaller text size.
  • The media query changes the grid to one column on screens up to 640px wide.
  • Save styles.css.
  • Switch back to the local page in Google Chrome.
  • Refresh the page.
  • Resize the Chrome window until it is narrower than 640px.

You will see the cards move into one column as the window narrows. The top spacing also becomes smaller.

Grid Stays in Two Columns?

Confirm that the media query closes with its final brace. Check that .status-grid appears inside that media query.

Help me diagnose why the responsive card grid is not switching to one column.

✔️ Awesome, I've Got Everything

Your stylesheet is complete. Save styles.css before the final check.

ⓧ I'd Like to Double Check the Full Code

:root {
  color-scheme: dark;
  font-family: "Segoe UI", Arial, sans-serif;
  background: #071426;
  color: #eaf2ff;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  background:
    radial-gradient(circle at top left, #173b67 0, transparent 38%),
    linear-gradient(145deg, #071426, #0b1f38);
}

.shell {
  width: min(100% - 2rem, 980px);
  margin: 0 auto;
  padding: 4rem 0 2rem;
}

.eyebrow {
  margin: 0 0 0.75rem;
  color: #72d9ff;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.14em;
}

h1 {
  max-width: 760px;
  margin: 0;
  font-size: clamp(2.4rem, 8vw, 5.5rem);
  line-height: 0.98;
}

.intro {
  max-width: 680px;
  margin: 1.5rem 0 2.5rem;
  color: #b9c9dc;
  font-size: 1.1rem;
  line-height: 1.7;
}

.status-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.card {
  min-height: 210px;
  padding: 1.5rem;
  border: 1px solid #315476;
  border-radius: 18px;
  background: rgb(12 34 58 / 88%);
  box-shadow: 0 18px 45px rgb(0 0 0 / 18%);
}

.step-label {
  display: inline-block;
  padding: 0.35rem 0.65rem;
  border-radius: 999px;
  background: #123f61;
  color: #86e2ff;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.09em;
}

h2 {
  margin: 1.1rem 0 0.7rem;
  font-size: 1.35rem;
}

.card p {
  margin: 0;
  color: #b9c9dc;
  line-height: 1.6;
}

footer {
  margin-top: 2rem;
  color: #8298af;
  font-size: 0.9rem;
}

@media (max-width: 640px) {
  .shell {
    padding-top: 2.5rem;
  }

  .status-grid {
    grid-template-columns: 1fr;
  }
}
Verify the local checkpoint

The design now looks ready to share. The browser address reveals whether the site has actually reached the cloud.

Before you refresh, do you expect the finished design to give the page a public pages.dev hostname?

  • Return to the local Cloud Security Checkpoint tab in Google Chrome.
  • Refresh the page.
  • Inspect the four workflow cards.
  • Read the address shown in the browser address bar.

You will see a dark blue page with four responsive cards. Their labels are BUILD, DEPLOY, INSPECT, and HARDEN.

The address bar still points to the local index.html file. It does not contain a public pages.dev hostname.

What Does the Local Address Prove?

The finished design proves that the static files work in your browser. The local address also proves that no cloud platform is delivering the page yet.

That is the local build complete. Next, you will upload these files to Cloudflare Pages and give the checkpoint its public cloud address.

Deploy the Site with Direct Upload

Your Cloud Security Checkpoint now looks finished in Google Chrome. Its file address still keeps the result on your computer.

Cloudflare Pages gives the same files a public HTTPS address through static hosting. Direct Upload publishes the existing folder without changing its code.

In this step, get ready to:
  • Create a Cloudflare Pages Direct Upload project.
  • Publish the first-cloud-security-site folder as a production deployment.
  • Open the public pages.dev address in Google Chrome.
Start the Direct Upload project

Direct Upload accepts a single folder of prebuilt assets from your computer. It fits this project because index.html and styles.css are already complete.

  • Switch back to the signed-in Cloudflare dashboard from earlier.
  • Select Workers & Pages in the dashboard.
  • Select Create application.
  • Select Get started.
  • Select Drag and drop your files.

Why use Direct Upload?

Direct Upload publishes a local folder without adding a Git repository. That keeps this deployment focused on the files you already built.

A Direct Upload project stays on this deployment method. Switching to Git integration later requires a new project.

Upload the site folder

The folder is the deployment unit. Cloudflare serves its top-level index.html when someone opens the project address.

Cloudflare asks for a second confirmation after the folder uploads.

  • Enter first-cloud-security-yourname as your unique project name.
  • Return to File Explorer from earlier.
  • Drag the Documents\first-cloud-security-site folder into the upload area.
  • Select Deploy site.
  • Select Save and Deploy after the folder finishes uploading.
  • Wait for Cloudflare to report that the production deployment is complete.
  • Continue to the deployed project.

You'll see a completed production deployment with a public address ending in pages.dev.

Project creation or upload blocked?

Cloudflare can temporarily limit new Pages projects during an account's first 48 hours. The block lifts automatically.

If the folder is rejected, confirm that index.html and styles.css sit directly inside first-cloud-security-site.

Help me troubleshoot a blocked Cloudflare Pages project creation or folder upload. You can also share the screen you see with the NextWork community.

Open and verify the public site

The production link proves that the site has left your computer. It also gives you the cloud-hosted response needed for the next inspection.

Before you open the link, do you expect the hosted page to match your local version?

  • Select the production pages.dev link in the Cloudflare project.

You'll see the dark blue Cloud Security Checkpoint page with cards labeled BUILD, DEPLOY, INSPECT, and HARDEN. The address bar shows the public pages.dev hostname.

  • Copy the full public address from Chrome's address bar into your public pages.dev URL.

You have cleared the local-only barrier. Your Cloud Security Checkpoint is now available from a public cloud address.

Live page missing content or styles?

Confirm that index.html and styles.css were uploaded at the same folder level. A bare page usually means the stylesheet was omitted or moved.

Help me troubleshoot a Cloudflare Pages site that loads without its expected content or CSS styling.

Your public site now returns a real cloud response. Next, Chrome DevTools will reveal its HTTPS details and response headers.

Inspect HTTPS and Response Headers

Your public Cloudflare Pages site now loads in a browser. Availability is only the first part of a security review.

Chrome DevTools exposes the HTTP response headers behind the rendered page. Those headers show which platform delivered the response.

You will confirm the HTTPS origin. You will also view its certificate details.

In this step, get ready to:
  • Record the deployed page's network requests in Chrome DevTools.
  • Inspect the response headers delivered by Cloudflare.
  • View the HTTPS origin certificate details.
Record the network requests

The Network panel records every resource that the browser requests. Reloading the page while this panel is open captures a fresh delivery from the cloud.

Before you reload, predict whether the response will identify the platform that delivered your page.

  • Switch back to the deployed page in Google Chrome.
  • Press Control+Shift+J to open Chrome DevTools.
  • Select the Network tab.
  • Reload the deployed page.

You should see the Network table fill with requests from your deployed site.

The top resource should represent the main HTML document.

Network table empty?

  • Reload the page with the Network tab already selected.
  • Confirm that Chrome DevTools remains open during the reload.

Help me diagnose an empty Chrome DevTools Network table.

Inspect the response headers

The main document response carries metadata alongside the page content. Each header records one part of how the platform handled that response.

The request table can look busy on a first pass. The top document entry gives you a reliable starting point.

  • Select the top HTML document request in the Network table.
  • Select the Headers tab.
  • Scroll to Response Headers.
  • Locate Server: cloudflare.
  • Locate the Cf-Ray entry.
  • Locate the current Referrer-Policy entry.

You should see Server: cloudflare in Response Headers.

You should also see a Cf-Ray entry.

Referrer-Policy: strict-origin-when-cross-origin records the current default policy.

What do these headers prove?

  • Server: cloudflare identifies Cloudflare as the server that delivered the response.
  • Cf-Ray is a response identifier unique to Cloudflare.
  • Referrer-Policy defines how much referrer information the browser can send with later requests.

You have crossed an important checkpoint: the live response now proves that Cloudflare delivered your page with identifiable platform headers.

Headers missing?

  • Reload the deployed pages.dev page with the Network tab open.
  • Select the top request for the page itself.
  • Expand the Response Headers section.

Help me find the Cloudflare response headers in Chrome DevTools.

View the HTTPS certificate

The response headers identify the delivery platform. Chrome's security view confirms the main origin behind the encrypted connection.

This certificate view is tucked behind Chrome's command menu, so the route takes a few clicks.

  • Press Control+Shift+P to open the command menu.
  • Type privacy.
  • Select Show privacy and security.
  • Select Security in the Privacy and security panel.
  • Select Overview.

Before you open the certificate details, predict what Chrome will confirm about the main origin.

  • Select View certificate for the main origin.

You should see certificate details for the main origin serving your public site.

That completes the delivery audit: Chrome has exposed the cloud response and the certificate behind its HTTPS connection.

Certificate details not showing?

  • Return to the deployed pages.dev page.
  • Open Show privacy and security through the command menu again.
  • Select Overview before choosing View certificate.

Help me open the certificate details for my deployed Cloudflare Pages origin.

You can now prove how the browser received your site. Next, you will add an explicit anti-framing policy at the hosting layer.

Add and Verify an Anti-Framing Rule

Your deployed checkpoint is live through HTTPS. Chrome DevTools has already exposed the response Cloudflare Pages sends.

HTTPS protects the connection. An explicit HTTP response header tells browsers to reject framing by another page.

In this step, get ready to:
  • Define a global anti-framing policy in an extensionless _headers file.
  • Publish the updated folder through Direct Upload as a new production deployment.
  • Verify that the live document response contains X-Frame-Options: DENY.
Create the anti-framing policy

Cloudflare Pages reads an extensionless _headers file from the uploaded static assets. A /* path rule applies the policy across incoming URLs.

  • In Visual Studio Code's Explorer view, select New File.
  • Enter _headers as the filename.

You should see _headers beside index.html and styles.css in the Explorer.

  • Add the anti-framing rule by pasting this complete file:
/*
  X-Frame-Options: DENY

What does this policy do?

  • The /* pattern applies the rule across incoming URLs for your site.
  • The indented X-Frame-Options: DENY line tells browsers not to embed the site. That restriction helps defend against clickjacking.
  • Save _headers.
  • Confirm that Visual Studio Code lists _headers beside index.html and styles.css.

File missing or misnamed?

  • Check that the filename is exactly _headers without a file extension.
  • Move _headers beside index.html if it appears inside another folder.

Help me check why Cloudflare Pages might not recognize my _headers file.

✔️ Awesome, I've got everything!

Your _headers file is saved with the global anti-framing policy.

ⓧ I'd like to double check the full code

/*
  X-Frame-Options: DENY

What should match?

Your complete _headers file should contain this path rule followed by the indented anti-framing header.

Deploy the updated folder

The policy currently exists only in your local folder. A new production deployment carries _headers to the hosting layer.

  • Switch back to the Cloudflare dashboard from earlier.
  • Select Workers & Pages.
  • Select your existing Cloudflare Pages project.
  • Select Create a new deployment.
  • Choose the production environment.
  • Upload the complete Documents\first-cloud-security-site folder into the upload area.
  • Select Save and Deploy.
  • Wait until Cloudflare reports that the deployment is complete.

That upload closes the local-to-cloud gap. Your _headers policy is now part of the latest production deployment.

Deployment not completing?

  • Confirm that the uploaded folder contains index.html at its top level.
  • Confirm that the same folder contains _headers without a file extension.

Help me troubleshoot my Cloudflare Pages production deployment. Ask the Cloudflare Community.

Verify the live response

The local file proves that you defined the policy. The newest document response proves that Cloudflare applied it.

Before you reload, do you expect the browser to receive the anti-framing rule from the newest production deployment?

  • Switch back to the deployed pages.dev page in Google Chrome.
  • Return to the Network panel in DevTools.
  • Reload the deployed page.
  • Select the top document request.
  • Select Headers.
  • Find the anti-framing policy under Response Headers.

You should see X-Frame-Options: DENY in the live document response.

The Server: cloudflare header should remain visible. The Cf-Ray entry should remain visible.

You have closed the hardening loop. The live cloud response now carries your anti-framing rule.

Header missing from the response?

  • Confirm that you selected the top document request instead of styles.css.
  • Reload the page while Network recording is active.
  • Confirm that the newest production deployment completed after you uploaded _headers.

Help me find why X-Frame-Options is missing from my Cloudflare Pages response.

Secret mission

Tighten Referrer Privacy

Your site blocks framing, but its production response still uses Cloudflare's default referrer policy. Add a stricter privacy rule, redeploy the complete site, and prove the new value reached the browser.

Clean Up Your Resources

Clean Up Your Resources

Choose whether to keep your resources available, pause your work, or remove everything you created. Your Cloudflare Pages site costs $0 while it stays within the documented Cloudflare Free plan limits.

Resources you used:

  • Local project folder: Documents\first-cloud-security-site containing index.html, styles.css, and _headers.
  • Cloudflare Pages project: One Direct Upload project containing your production deployments plus a public pages.dev address.

Keep everything running

No action is needed. Choose this if you want your public security demo to remain available for sharing or future checks.

  • Keep the Cloudflare Pages project deployed at its public pages.dev address.
  • Keep Documents\first-cloud-security-site as your editable local copy.
  • Keep the current project within the Cloudflare Free plan limits to maintain a $0 cost.

Pause - I'll come back to this later

Pause by stopping new deployments while you take a break. Direct Upload has no automatic repository-triggered builds.

  • Close Google Chrome when you finish checking the live headers.
  • Close Visual Studio Code when you finish editing the local files.
  • Keep Documents\first-cloud-security-site so you can continue editing later.
  • Leave the latest production deployment online at its current pages.dev address.

Delete - I don't want to use this again

This option permanently removes the live project plus its deployments. Your local folder stays safe until the final cleanup action.

  • In the Cloudflare dashboard from earlier, select Workers & Pages.
  • Select your Pages project.
  • Select Settings.
  • Select Delete project.
  • Confirm that the Pages project no longer appears in Workers & Pages.
  • In File Explorer, return to Documents.
  • Permanently delete the first-cloud-security-site folder from Documents.
  • Confirm that first-cloud-security-site no longer appears in Documents.

Nice Work!

Nice Work!

You did it! Your Cloud Security Checkpoint is live on Cloudflare Pages. Its production response now carries a verified anti-framing policy.

What you learned:

  • Built a responsive Cloud Security Checkpoint that presents the Build, Deploy, Inspect, and Harden workflow in four browser-ready cards.
  • Published the finished static assets through Direct Upload at a public pages.dev address.
  • Audited the live site with Chrome DevTools. You verified HTTPS certificate details. You inspected response headers. You applied X-Frame-Options: DENY through _headers to defend the site against clickjacking.
  • Secret Mission: Overrode the default referrer policy with Referrer-Policy: no-referrer. You verified it beside X-Frame-Options: DENY on the latest production response.

Ready to quiz yourself?