From 325a37cdea02fe860186781a60588c1583c37865 Mon Sep 17 00:00:00 2001 From: chibbyalucard <> Date: Tue, 6 May 2025 00:02:28 +0100 Subject: [PATCH 1/3] Add support for blockquote alerts in layout files Signed-off-by: chibbyalucard --- README.md | 154 ++++++++++++++++-- .../index.md | 10 +- .../index.md | 37 +++-- .../docs/getting-further/script-security.md | 5 +- ...somethings-not-working-what-should-i-do.md | 5 +- site/layouts/page/download.html | 13 ++ site/layouts/partials/blockquote-alert.html | 43 +++++ site/layouts/shortcodes/blockquote-alert.html | 9 + 8 files changed, 241 insertions(+), 35 deletions(-) create mode 100644 site/layouts/partials/blockquote-alert.html create mode 100644 site/layouts/shortcodes/blockquote-alert.html diff --git a/README.md b/README.md index 11b4b12cf..43a382601 100644 --- a/README.md +++ b/README.md @@ -122,24 +122,156 @@ icon: > [!NOTE] > You can highlight important information in your articles or docs using different types of callouts (also known as admonitions – or alerts, as used in [the Hugo docs](https://gohugo.io/render-hooks/blockquotes/#alerts)). -The examples below use the same syntax as in Github Markdown. The template responsible for rendering them is at `site/layouts/_default/_markup/render-blockquote.html` +For compatibility with both content and layout files, we use a mix of shortcodes and partials to display blockquote alerts. Partials work in layout, but not content files. Shortcodes work in content, but not layout files. Use the partial in layout files, and the shortcode (which internally calls the partial) in content files. +The partial is at `site/layouts/partials/blockquote-alert.html`, and the shortcode is at `site/layouts/shortcodes/blockquote-alert.html`. + +There are five available alert types as shown in the examples below: + +- note +- tip +- important +- warning +- caution + +Omit the `title` parameter to keep the alert type as the default title (for example, a note alert will have "Note" as its title): + +```md + + +{{< blockquote-alert type="note" title="Optional custom title">}} +Useful information that users should know, even when skimming content. +{{< /blockquote-alert >}} + +{{< blockquote-alert type="tip" title="Optional custom title">}} +Helpful advice for doing things better or more easily. +{{< /blockquote-alert >}} + +{{< blockquote-alert type="important" title="Optional custom title">}} +Key information users need to know to achieve their goal. +{{< /blockquote-alert >}} + +{{< blockquote-alert type="warning" title="Optional custom title">}} +Urgent info that needs immediate user attention to avoid problems. +{{< /blockquote-alert >}} + +{{< blockquote-alert type="caution" title="Optional custom title">}} +Advises about risks or negative outcomes. +{{< /blockquote-alert >}} ``` -> [!NOTE] -> Useful information that users should know, even when skimming content. -> [!TIP] -> Helpful advice for doing things better or more easily. +In layout files, call the partial directly. Just like shortcode content, anything passed to the `content` parameter is parsed as Markdown. To pass raw HTML instead, use the `html` parameter. Again, the title parameter is optional and will default to the alert type: -> [!IMPORTANT] -> Key information users need to know to achieve their goal. +```html + + + + +{{ partial "blockquote-alert.html" (dict + "type" "note" + "title" "Optional custom title" + "content" "Useful information that users should know, even when skimming content." +) }} + +{{ partial "blockquote-alert.html" (dict + "type" "tip" + "title" "Optional custom title" + "content" "Helpful advice for doing things better or more easily." +) }} + +{{ partial "blockquote-alert.html" (dict + "type" "important" + "title" "Optional custom title" + "content" "Key information users need to know to achieve their goal." +) }} + +{{ partial "blockquote-alert.html" (dict + "type" "warning" + "title" "Optional custom title" + "content" "Urgent info that needs immediate user attention to avoid problems." +) }} + +{{ partial "blockquote-alert.html" (dict + "type" "caution" + "title" "Optional custom title" + "content" "Advises about risks or negative outcomes." +) }} +``` + +In addition to simple string content as shown above, you can also pass in complex nested content with multiple paragraphs and elements: -> [!WARNING] -> Urgent info that needs immediate user attention to avoid problems. +```md + + +{{< blockquote-alert type="tip" title="Optional custom Title" >}} +This is a tip with **bold text** and _italic_ text. + +This is a second paragraph in the same alert. + +- List item 1 +- List item 2 +{{< /blockquote-alert >}} +``` + +You can do similar in partials. These are all valid options. Additionally, you can assign content to a variable before passing it in, which helps with formatting in longer templates: + +```html + + +{{ $alertContent := `This is a tip with **bold text** and _italic_ text. + +This is a second paragraph in the same alert. + +- List item 1 +- List item 2 +`}} + +{{ partial "blockquote-alert.html" (dict + "type" "tip" + "title" "Optional custom title" + "content" $alertContent +) }} + + +{{ $alertContent := add + "This is a tip with **bold text** and _italic_ text.\n\n" + "This is a second paragraph in the same alert.\n" + "- List item 1\n" + "- List item 2\n\n" + "`Here's some text in backticks.`" +}} + +{{ partial "blockquote-alert.html" (dict + "type" "tip" + "title" "Optional custom title" + "content" $alertContent +) }} + + +{{ partial "blockquote-alert" (dict + "type" "caution" + "title" "Be Careful!" + "html" "

This is a caution message.

It has multiple paragraphs.

" +) }} +``` + + +> [!IMPORTANT] +> When working with complex content, make sure to handle line breaks properly within the strings passed to the `content` or `html` parameters. For example, the following will throw a parse error (`html: overlay: parse failed unterminated quoted string in action`): -> [!CAUTION] -> Advises about risks or negative outcomes. ``` +{{ partial "blockquote-alert" (dict + "type" "caution" + "title" "Be Careful!" + "html" "

This is a caution message.

+

It has multiple paragraphs.

" +) }} +``` + +To avoid this, you can use either of the following options: + +- Keep everything on a single line +- Use string concatenation (whether in a variable or directly) #### Layouts For controlling what HTML is rendered, you need to work with the site templates. In the directory, `site/layouts/`, you'll find a number of HTML files with various template tags. The first file to check out is `site/layouts/_default/baseof.html` - this is the base layout Hugo uses to build your site that templates extend. Hugo has a lookup order for associating a content entry to a template. A single entry whose type is post (`type: post`), Hugo will look for a layout in `site/layouts/post/single.html`, and if that does not exist, it will fallback to `site/layouts/_default/single.html`. diff --git a/site/content/blog/2025-04-02-zap-updates-march-2025/index.md b/site/content/blog/2025-04-02-zap-updates-march-2025/index.md index 321abd820..4158a53c7 100644 --- a/site/content/blog/2025-04-02-zap-updates-march-2025/index.md +++ b/site/content/blog/2025-04-02-zap-updates-march-2025/index.md @@ -15,8 +15,9 @@ authors: ## Highlights -> [!IMPORTANT] -> The big news last month was the release of [2.16.1](/blog/2025-03-25-zap-2-16-1/)! +{{< blockquote-alert type="important">}} +The big news last month was the release of [2.16.1](/blog/2025-03-25-zap-2-16-1/)! +{{< /blockquote-alert >}} As part of this release the [Script Console](/docs/desktop/addons/script-console/) now uses the main [Output](/docs/desktop/ui/tabs/output/) tab instead of its own "Script Output" panel. @@ -45,8 +46,9 @@ The following significant changes have been made to this website: * A new [Script Security](/docs/getting-further/script-security/) advanced guide * Even more [Authentication Tests](/docs/scans/auth/) -> [!NOTE] -> We now have the option to highlight important information, as demonstrated here! +{{< blockquote-alert type="note">}} +We now have the option to highlight important information, as demonstrated here! +{{< /blockquote-alert >}} ## GitHub Pulse Here are some statistics for the two main ZAP repositories: diff --git a/site/content/blog/2025-04-09-portswigger-labs-broken-brute-force-protection-ip-block/index.md b/site/content/blog/2025-04-09-portswigger-labs-broken-brute-force-protection-ip-block/index.md index e83b43dae..1178f2c67 100644 --- a/site/content/blog/2025-04-09-portswigger-labs-broken-brute-force-protection-ip-block/index.md +++ b/site/content/blog/2025-04-09-portswigger-labs-broken-brute-force-protection-ip-block/index.md @@ -61,12 +61,13 @@ Copy-paste the lab URL into the *URL to explore* field and launch your browser w ![launch-test-site-ZAP-configured-browser.png](images/launch-test-site-ZAP-configured-browser.png) -> [!NOTE] -> If you have any issues launching your browser from ZAP, see the following pages for help. ZAP uses add-ons to enhance its core features, including ones which provide webdrivers for interfacing with supported browsers. These are installed by default and expose some configurable options: -> -> 1. [How can I fix 'browser was not found'?](/faq/how-can-i-fix-browser-was-not-found/) - ZAP Docs (FAQ) -> 2. [Manual Explore](/docs/desktop/addons/quick-start/#manual-explore) - ZAP Docs -> 3. [Selenium](/docs/desktop/addons/selenium/) - ZAP Docs +{{< blockquote-alert type="note">}} +If you have any issues launching your browser from ZAP, see the following pages for help. ZAP uses add-ons to enhance its core features, including ones which provide webdrivers for interfacing with supported browsers. These are installed by default and expose some configurable options: + +1. [How can I fix 'browser was not found'?](/faq/how-can-i-fix-browser-was-not-found/) - ZAP Docs (FAQ) +2. [Manual Explore](/docs/desktop/addons/quick-start/#manual-explore) - ZAP Docs +3. [Selenium](/docs/desktop/addons/selenium/) - ZAP Docs +{{< /blockquote-alert >}} Assuming you’ve opened the lab in a browser configured to proxy through ZAP, let’s try to log in with a random password. We want to capture a POST request we can work with in ZAP. I’ll try “randompass”. We’re notified that this is an “Incorrect password”, which is expected: @@ -96,8 +97,9 @@ After one minute, we can indeed make more login attempts. The idea is that if we If we enter our own credentials, `wiener:peter`, on every third login attempt, the IP block never activates. Each successful login resets the counter tracking the number of failed login attempts. We can keep going until we’ve tried enough passwords from our wordlist to find the right one for Carlos' account. -> [!NOTE] -> This bypass — taking advantage of a logic flaw to reset the failure counter — enables us to brute-force Carlos’ password and successfully solve this lab. Although not the point of the lab, we can also wait out the IP block since we’re dealing with only a few credentials. This is covered in “Method 2: Wait Out the IP Block”. +{{< blockquote-alert type="note">}} +This bypass — taking advantage of a logic flaw to reset the failure counter — enables us to brute-force Carlos’ password and successfully solve this lab. Although not the point of the lab, we can also wait out the IP block since we’re dealing with only a few credentials. This is covered in “Method 2: Wait Out the IP Block”. +{{< /blockquote-alert >}} What about changing our IP address? I used the [`X-Forwarded-For`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) header successfully in another lab. But the server here appears to block IPs based on the client's actual IP address (determined by the network layer rather than HTTP headers from the application layer), which makes sense in the context of rate-limiting. Rotating IP addresses via a proxy or VPN could work, but we won’t explore that here. @@ -564,8 +566,9 @@ All functions, except the `log` function, are part of a required interface that ![implementation-error.png](images/implementation-error.png) -> [!NOTE] -> Refer to the default templates for the interfaces required for each script type. You can find these in the Templates section of the Scripts tab. They include documentation comments describing each function and its parameters. You can also create new scripts from the templates. +{{< blockquote-alert type="note">}} +Refer to the default templates for the interfaces required for each script type. You can find these in the Templates section of the Scripts tab. They include documentation comments describing each function and its parameters. You can also create new scripts from the templates. +{{< /blockquote-alert >}} You can save the file now. Also, check that the script is enabled, as disabled scripts won’t be available for selection when needed. If you missed the *Enable* checkbox earlier, you can right-click the filename in the *Scripts* tab and select *Enable Script(s)*. @@ -583,10 +586,11 @@ After you open the *Add Payload* dialog, you can add the Payload Generator scrip Save the payload and return to the main Fuzzer dialog. Then, run the Fuzzer with *Start Fuzzer*. -> [!IMPORTANT] -> You might notice that even though the payloads are generated correctly (as the logs in the script output panel show), the requests are sent in the wrong order. This causes an unexpected IP block early on. As a result, most of the requests are rejected with the message: `You have made too many incorrect login attempts. Please try again in 1 minute(s).` -> -> This is due to the Fuzzer’s concurrency settings. You can enable sequential execution by setting the number of execution threads to 1. However, this slows down the Fuzzer a great deal. An alternative is to throttle requests with a small delay of 100–200 milliseconds. See [Options Fuzzer screen](/docs/desktop/addons/fuzzer/options/) for more detail. +{{< blockquote-alert type="important">}} +You might notice that even though the payloads are generated correctly (as the logs in the script output panel show), the requests are sent in the wrong order. This causes an unexpected IP block early on. As a result, most of the requests are rejected with the message: `You have made too many incorrect login attempts. Please try again in 1 minute(s).` + +This is due to the Fuzzer’s concurrency settings. You can enable sequential execution by setting the number of execution threads to 1. However, this slows down the Fuzzer a great deal. An alternative is to throttle requests with a small delay of 100–200 milliseconds. See [Options Fuzzer screen](/docs/desktop/addons/fuzzer/options/) for more detail. +{{< /blockquote-alert >}} You can skip over the next section and head to [Have Username, Got Password](#have-username-got-password). @@ -715,8 +719,9 @@ You can optionally move the script to the top of the processor list. Then, run t Once the Fuzzer is done, we can inspect the results. We’re looking for indications of a successful login. So, we’ll sort the results in descending order using the status code column (simply “*Code”* in the UI). -> [!NOTE] -> Both of these solutions are valid. As you might have noticed if you’ve solved a lab more than once, different lab instances can have different password solutions. So, you could see different passwords than shown below. +{{< blockquote-alert type="note">}} +Both of these solutions are valid. As you might have noticed if you’ve solved a lab more than once, different lab instances can have different password solutions. So, you could see different passwords than shown below. +{{< /blockquote-alert >}} ### Method 1: Interleave Wordlists With Valid Credentials diff --git a/site/content/docs/getting-further/script-security.md b/site/content/docs/getting-further/script-security.md index e1dc54f69..37e49aff0 100644 --- a/site/content/docs/getting-further/script-security.md +++ b/site/content/docs/getting-further/script-security.md @@ -22,8 +22,9 @@ For more details on ZAP’s security posture see the ### Script Capabilities As noted on the [Script Console](/docs/desktop/addons/script-console/) page: -> [!WARNING] -> Scripts run with the same permissions as ZAP, so do not run any scripts that you do not trust! +{{< blockquote-alert type="warning">}} +Scripts run with the same permissions as ZAP, so do not run any scripts that you do not trust! +{{< /blockquote-alert >}} All scripts can call other scripts and any command line tools that are accessible to them based on OS permissions. Scripts can access any online services unless restricted by firewalls or similar. diff --git a/site/content/faq/somethings-not-working-what-should-i-do.md b/site/content/faq/somethings-not-working-what-should-i-do.md index 5ff3b50b5..0201378c6 100644 --- a/site/content/faq/somethings-not-working-what-should-i-do.md +++ b/site/content/faq/somethings-not-working-what-should-i-do.md @@ -63,5 +63,6 @@ You can chat with the ZAP team on [Slack](/slack/), if you have not already join You can raise issues (bugs or new features) at the [issue tracker](https://github.com/zaproxy/zaproxy/issues/new/choose). -> [!WARNING] -> Please do not ask questions as issues - they will be closed and you will be redirected to the [ZAP user group](https://groups.google.com/group/zaproxy-users). +{{< blockquote-alert type="warning">}} +Please do not ask questions as issues - they will be closed and you will be redirected to the [ZAP user group](https://groups.google.com/group/zaproxy-users). +{{< /blockquote-alert >}} diff --git a/site/layouts/page/download.html b/site/layouts/page/download.html index a0023ce6b..087ecc2a9 100644 --- a/site/layouts/page/download.html +++ b/site/layouts/page/download.html @@ -75,6 +75,19 @@

{{ .title }}

Next to it, if you trust the downloaded installer, you can click Open anyway. + + + + + + + + {{ partial "blockquote-alert.html" (dict + "type" "warning" + "html" "

This is a caution message.

It has multiple paragraphs.

" + ) }} + + diff --git a/site/layouts/partials/blockquote-alert.html b/site/layouts/partials/blockquote-alert.html new file mode 100644 index 000000000..68776c7c5 --- /dev/null +++ b/site/layouts/partials/blockquote-alert.html @@ -0,0 +1,43 @@ +{{ $emojis := dict +"caution" ":bangbang:" +"important" ":information_source:" +"note" ":memo:" +"tip" ":bulb:" +"warning" ":warning:" +}} + +{{ $type := .type | default "note" }} +{{ $title := .title | default "" }} +{{ $content := .content | default "" }} +{{ $html := .html | default "" }} + +{{/* Handle inner content from shortcodes */}} +{{ if .inner }} +{{ $content = .inner }} +{{ end }} + +{{ if $type }} +
+

+ {{ transform.Emojify (index $emojis $type) }} + {{ if $title }} + {{ $title }} + {{ else }} + {{ or (i18n $type) (title $type) }} + {{ end }} +

+
+ {{ if $html }} + {{ $html | safeHTML }} + {{ else if $content }} + {{ $content | markdownify }} + {{ else }} + {{ i18n "no-content" }} + {{ end }} +
+
+{{ else }} +
+ {{ $content | markdownify }} +
+{{ end }} \ No newline at end of file diff --git a/site/layouts/shortcodes/blockquote-alert.html b/site/layouts/shortcodes/blockquote-alert.html new file mode 100644 index 000000000..a2c584ed7 --- /dev/null +++ b/site/layouts/shortcodes/blockquote-alert.html @@ -0,0 +1,9 @@ +{{ $type := .Get "type" | default "note" }} +{{ $title := .Get "title" | default "" }} +{{ $inner := .Inner }} + +{{ partial "blockquote-alert" (dict + "type" $type + "title" $title + "inner" $inner +) }} From d9915c23d8e5c6c88963aed1f1f853ba78cb5631 Mon Sep 17 00:00:00 2001 From: chibbyalucard <> Date: Mon, 16 Jun 2025 23:17:19 +0100 Subject: [PATCH 2/3] Use partial for blockquote alert Signed-off-by: chibbyalucard --- site/layouts/page/download.html | 51 +++++++++++---------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/site/layouts/page/download.html b/site/layouts/page/download.html index 087ecc2a9..9da53483b 100644 --- a/site/layouts/page/download.html +++ b/site/layouts/page/download.html @@ -54,40 +54,23 @@

{{ .title }}

{{ end }} -
-

- ⚠️ Warning - The ZAP releases are currently unsigned -

-
-

- On Windows, you will see a message like: - - ZAP_<version>_windows.exe isn't commonly downloaded. - Make sure you trust ZAP_<version>_windows.exe before you open it. -
- To circumvent this warning, you would need to click on ... and then Keep, - then Show more and then Keep anyway. -

- On macOS, you will see a message like: - "ZAP.app" cannot be opened because the developer cannot be verified.
- To circumvent this warning, you would need to go to System Preferences > Security & Privacy - at the bottom of the dialog. You will see a message saying that "ZAP" was blocked. - Next to it, if you trust the downloaded installer, you can click Open anyway. -

-
- - - - - - - - {{ partial "blockquote-alert.html" (dict - "type" "warning" - "html" "

This is a caution message.

It has multiple paragraphs.

" - ) }} - - + {{ $alertContent := add + "On **Windows**, you will see a message like: " + "`ZAP__windows.exe isn't commonly downloaded. Make sure you trust ZAP__windows.exe before you open it.`\n\n" + "To circumvent this warning, you would need to click on **...** and then **Keep**, then " + "**Show more** and then **Keep anyway**.\n\n" + "On **macOS**, you will see a message like: " + "`\"ZAP.app\" cannot be opened because the developer cannot be verified.`\n\n" + "To circumvent this warning, you would need to go to **System Preferences** > **Security & Privacy** at " + "the bottom of the dialog. You will see a message saying that\"ZAP\" was blocked. Next to it, if you trust the " + "downloaded installer, you can click **Open anyway**." + }} + + {{ partial "blockquote-alert.html" (dict + "type" "warning" + "title" "Warning - The ZAP releases are currently unsigned" + "content" $alertContent + ) }} From 05ad88dbfeb23e1ab1f9f452e5a8667b3c9f9dfe Mon Sep 17 00:00:00 2001 From: chibbyalucard <> Date: Sun, 29 Jun 2025 18:04:38 +0100 Subject: [PATCH 3/3] Edit README Signed-off-by: chibbyalucard --- README.md | 56 +++++++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 43a382601..ec2cd4a26 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ There are five available alert types as shown in the examples below: - warning - caution -Omit the `title` parameter to keep the alert type as the default title (for example, a note alert will have "Note" as its title): +You can pass in simple string content or complex content with multiple paragraphs and nested elements. Omit the `title` parameter to keep the alert type as the default title (for example, a note alert will have "Note" as its title): ```md @@ -145,6 +145,13 @@ Useful information that users should know, even when skimming content. {{< blockquote-alert type="tip" title="Optional custom title">}} Helpful advice for doing things better or more easily. + +This is some **bold text** and _italic_ text. + +This is a third paragraph in the same alert, followed by list items below. + +- List item 1 +- List item 2 {{< /blockquote-alert >}} {{< blockquote-alert type="important" title="Optional custom title">}} @@ -160,7 +167,7 @@ Advises about risks or negative outcomes. {{< /blockquote-alert >}} ``` -In layout files, call the partial directly. Just like shortcode content, anything passed to the `content` parameter is parsed as Markdown. To pass raw HTML instead, use the `html` parameter. Again, the title parameter is optional and will default to the alert type: +In layout files, call the partial directly. Anything passed to the `content` parameter is parsed as Markdown. To pass raw HTML instead, use the `html` parameter. Again, the title parameter is optional and will default to the alert type: ```html @@ -185,35 +192,21 @@ In layout files, call the partial directly. Just like shortcode content, anythin "content" "Key information users need to know to achieve their goal." ) }} -{{ partial "blockquote-alert.html" (dict + + {{ partial "blockquote-alert.html" (dict "type" "warning" "title" "Optional custom title" - "content" "Urgent info that needs immediate user attention to avoid problems." + "html" "

Urgent info that needs immediate user attention to avoid problems.

" ) }} -{{ partial "blockquote-alert.html" (dict - "type" "caution" - "title" "Optional custom title" - "content" "Advises about risks or negative outcomes." +{{ partial "blockquote-alert" (dict + "type" "caution" + "title" "Optional custom title" + "html" "

Advises about risks or negative outcomes.

" ) }} ``` -In addition to simple string content as shown above, you can also pass in complex nested content with multiple paragraphs and elements: - -```md - - -{{< blockquote-alert type="tip" title="Optional custom Title" >}} -This is a tip with **bold text** and _italic_ text. - -This is a second paragraph in the same alert. - -- List item 1 -- List item 2 -{{< /blockquote-alert >}} -``` - -You can do similar in partials. These are all valid options. Additionally, you can assign content to a variable before passing it in, which helps with formatting in longer templates: +You can assign content to a variable before passing it to the partial, which helps with formatting in longer templates: ```html @@ -232,7 +225,7 @@ This is a second paragraph in the same alert. "content" $alertContent ) }} - + {{ $alertContent := add "This is a tip with **bold text** and _italic_ text.\n\n" "This is a second paragraph in the same alert.\n" @@ -246,16 +239,8 @@ This is a second paragraph in the same alert. "title" "Optional custom title" "content" $alertContent ) }} - - -{{ partial "blockquote-alert" (dict - "type" "caution" - "title" "Be Careful!" - "html" "

This is a caution message.

It has multiple paragraphs.

" -) }} ``` - > [!IMPORTANT] > When working with complex content, make sure to handle line breaks properly within the strings passed to the `content` or `html` parameters. For example, the following will throw a parse error (`html: overlay: parse failed unterminated quoted string in action`): @@ -268,10 +253,7 @@ This is a second paragraph in the same alert. ) }} ``` -To avoid this, you can use either of the following options: - -- Keep everything on a single line -- Use string concatenation (whether in a variable or directly) +To avoid this, you can either keep everything on a single line or use string concatenation. #### Layouts For controlling what HTML is rendered, you need to work with the site templates. In the directory, `site/layouts/`, you'll find a number of HTML files with various template tags. The first file to check out is `site/layouts/_default/baseof.html` - this is the base layout Hugo uses to build your site that templates extend. Hugo has a lookup order for associating a content entry to a template. A single entry whose type is post (`type: post`), Hugo will look for a layout in `site/layouts/post/single.html`, and if that does not exist, it will fallback to `site/layouts/_default/single.html`.