diff --git a/.gitignore b/.gitignore
index b2d6de3..e6e9ac4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,4 +17,4 @@
npm-debug.log*
yarn-debug.log*
-yarn-error.log*
+yarn-error.log*
\ No newline at end of file
diff --git a/blog/2019-05-28-first-blog-post.md b/blog/2019-05-28-first-blog-post.md
deleted file mode 100644
index 02f3f81..0000000
--- a/blog/2019-05-28-first-blog-post.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-slug: first-blog-post
-title: First Blog Post
-authors:
- name: Gao Wei
- title: Docusaurus Core Team
- url: https://github.com/wgao19
- image_url: https://github.com/wgao19.png
-tags: [hola, docusaurus]
----
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
diff --git a/blog/2019-05-29-long-blog-post.md b/blog/2019-05-29-long-blog-post.md
deleted file mode 100644
index 26ffb1b..0000000
--- a/blog/2019-05-29-long-blog-post.md
+++ /dev/null
@@ -1,44 +0,0 @@
----
-slug: long-blog-post
-title: Long Blog Post
-authors: endi
-tags: [hello, docusaurus]
----
-
-This is the summary of a very long blog post,
-
-Use a `` comment to limit blog post size in the list view.
-
-
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
-
-Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
diff --git a/blog/2021-08-01-mdx-blog-post.mdx b/blog/2021-08-01-mdx-blog-post.mdx
deleted file mode 100644
index c04ebe3..0000000
--- a/blog/2021-08-01-mdx-blog-post.mdx
+++ /dev/null
@@ -1,20 +0,0 @@
----
-slug: mdx-blog-post
-title: MDX Blog Post
-authors: [slorber]
-tags: [docusaurus]
----
-
-Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
-
-:::tip
-
-Use the power of React to create interactive blog posts.
-
-```js
-
-```
-
-
-
-:::
diff --git a/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg b/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg
deleted file mode 100644
index 11bda09..0000000
Binary files a/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg and /dev/null differ
diff --git a/blog/2021-08-26-welcome/index.md b/blog/2021-08-26-welcome/index.md
deleted file mode 100644
index 9455168..0000000
--- a/blog/2021-08-26-welcome/index.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-slug: welcome
-title: Welcome
-authors: [slorber, yangshun]
-tags: [facebook, hello, docusaurus]
----
-
-[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
-
-Simply add Markdown files (or folders) to the `blog` directory.
-
-Regular blog authors can be added to `authors.yml`.
-
-The blog post date can be extracted from filenames, such as:
-
-- `2019-05-30-welcome.md`
-- `2019-05-30-welcome/index.md`
-
-A blog post folder can be convenient to co-locate blog post images:
-
-
-
-The blog supports tags as well!
-
-**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
diff --git a/blog/authors.yml b/blog/authors.yml
deleted file mode 100644
index bcb2991..0000000
--- a/blog/authors.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-endi:
- name: Endilie Yacop Sucipto
- title: Maintainer of Docusaurus
- url: https://github.com/endiliey
- image_url: https://github.com/endiliey.png
-
-yangshun:
- name: Yangshun Tay
- title: Front End Engineer @ Facebook
- url: https://github.com/yangshun
- image_url: https://github.com/yangshun.png
-
-slorber:
- name: Sébastien Lorber
- title: Docusaurus maintainer
- url: https://sebastienlorber.com
- image_url: https://github.com/slorber.png
diff --git a/docs/developer/_category_.json b/docs/developer/_category_.json
new file mode 100644
index 0000000..502009d
--- /dev/null
+++ b/docs/developer/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Developer",
+ "position": 5
+}
diff --git a/docs/developer/contribute.md b/docs/developer/contribute.md
new file mode 100644
index 0000000..54aaf01
--- /dev/null
+++ b/docs/developer/contribute.md
@@ -0,0 +1,35 @@
+---
+sidebar_position: 2
+---
+
+# Contribute
+
+Thanks for your interest in contributing to Ladder.
+
+Please take a moment to review this page before submitting your first pull request. We also strongly recommend that you check for open issues and pull requests to see if someone else is working on something similar.
+
+## Contribute rules
+
+1. Test your rule with a variety of browsers and on both mobile & desktop devices.
+
+2. Open a pull request in the [everywall/ladder-rules](https://github.com/everywall/ladder-rules) repository.
+
+> To prevent rulesets from getting disorganized, rulesets are saved in a directory structure according to the site's country.
+
+## Contribute to Ladder
+
+### New feature guidelines
+
+New features should be linked to an existing feature request. If you have ideas for a larger feature, please open an issue first.
+
+1. Fork or clone the repo
+
+2. Create a new branch to work on your bug fix or feature
+
+3. Open a pull request in the [everywall/ladder](https://github.com/everywall/ladder) repository.
+
+Ladder is a a [Go Fiber](https://gofiber.io/) application. Please see their documentation for more information about the Go Fiber framework.
+
+### Documentation
+
+The documentation for this project is located at [everywall/everywall.github.io](https://github.com/everywall/everywall.github.io). When contributing a feature, please make an accompanying pull request to update documentation, if applicable.
diff --git a/docs/developer/setup.md b/docs/developer/setup.md
new file mode 100644
index 0000000..6b1a0d5
--- /dev/null
+++ b/docs/developer/setup.md
@@ -0,0 +1,41 @@
+---
+sidebar_position: 1
+---
+
+# Setup
+
+## Development server
+
+:::info
+
+Optional: To run a development server with live-reload using [cosmtrek/air](https://github.com/cosmtrek/air)
+
+1. Install air according to the [installation instructions](https://github.com/cosmtrek/air#installation).
+
+2. Clone the project repo:
+
+```bash
+git clone git@github.com-ladddder:everywall/ladder.git
+```
+
+3. Run a development server at http://localhost:8080:
+
+```bash
+air
+```
+
+:::
+
+Run a development server at http://localhost:8080:
+
+```bash
+git clone git@github.com-ladddder:everywall/ladder.git
+git submodule update --init --recursive
+echo "dev " > handlers/VERSION
+echo "dev " > cmd/VERSION
+RULESET="./ruleset.yaml" go run cmd/main.go
+```
+
+## Tailwind CSS
+
+This project uses [pnpm](https://pnpm.io/) to build a stylesheet with the [Tailwind CSS](https://tailwindcss.com/) classes. For local development, if you modify styles in `form.html`, `playground.html`, `generate_readable_outline.html` or `error_page.html`, run `pnpm build` to generate a new stylesheet.
diff --git a/docs/install/_category_.json b/docs/install/_category_.json
new file mode 100644
index 0000000..6346441
--- /dev/null
+++ b/docs/install/_category_.json
@@ -0,0 +1,4 @@
+{
+ "label": "Install",
+ "position": 2
+}
diff --git a/docs/install/binary.md b/docs/install/binary.md
new file mode 100644
index 0000000..f2075f9
--- /dev/null
+++ b/docs/install/binary.md
@@ -0,0 +1,15 @@
+---
+sidebar_position: 2
+---
+
+# Binary
+
+:::caution
+
+If your instance will be publicly accessible, make sure to enable Basic Auth. This will prevent unauthorized users from using your proxy. If you do not enable Basic Auth, anyone can use your proxy to browse nasty/illegal stuff. And you will be responsible for it.
+
+:::
+
+1. Download the binary for your OS [here](https://github.com/everywall/ladder/releases/latest)
+2. Unpack and run the binary `./ladder -r https://t.ly/14PSf`
+3. Open Browser (Default: http://localhost:8080)
diff --git a/docs/install/docker.md b/docs/install/docker.md
new file mode 100644
index 0000000..9ac1a5d
--- /dev/null
+++ b/docs/install/docker.md
@@ -0,0 +1,36 @@
+---
+sidebar_position: 1
+---
+
+# Docker
+
+:::caution
+
+If your instance will be publicly accessible, make sure to enable Basic Auth. This will prevent unauthorized users from using your proxy. If you do not enable Basic Auth, anyone can use your proxy to browse nasty/illegal stuff. And you will be responsible for it.
+
+:::
+
+## Docker compose
+
+```yaml title="docker-compose.yaml"
+version: "3"
+services:
+ ladder:
+ image: ghcr.io/everywall/ladder:latest
+ container_name: ladder
+ build: .
+ restart: always
+ environment:
+ - PORT=8080
+ - RULESET=https://raw.githubusercontent.com/everywall/ladder-rules/main/rulesets
+ ports:
+ - "8080:8080"
+```
+
+Other environment variables can be updated as to your preferences, with details on each variable listed in [environment variables](environment-variables.md).
+
+## Docker run
+
+```bash
+docker run -p 8080:8080 -d --env RULESET=https://t.ly/DA3n6 --name ladder ghcr.io/everywall/ladder:latest
+```
diff --git a/docs/install/environment-variables.md b/docs/install/environment-variables.md
new file mode 100644
index 0000000..dd15b5f
--- /dev/null
+++ b/docs/install/environment-variables.md
@@ -0,0 +1,22 @@
+---
+sidebar_position: 4
+---
+
+# Environment variables
+
+| Variable | Description | Default Value |
+| ------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
+| `PORT` | Port to listen on | `8080` |
+| `PREFORK` | Spawn multiple server instances | `false` |
+| `USER_AGENT` | User agent to emulate | `Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)` |
+| `X_FORWARDED_FOR` | IP forwarder address | `66.249.66.1` |
+| `USERPASS` | Enables Basic Auth, format `admin:123456` | `` |
+| `LOG_URLS` | Log fetched URL's | `true` |
+| `DISABLE_FORM` | Disables URL Form Frontpage | `false` |
+| `FORM_PATH` | Path to custom Form HTML | `` |
+| `RULESET` | Path or URL to a ruleset file, accepts local directories | `https://raw.githubusercontent.com/everywall/ladder-rules/main/rulesets` or `/path/to/my/rules.yaml` or `/path/to/my/rules/` |
+| `EXPOSE_RULESET` | Make your Ruleset available to other ladders | `true` |
+| `ALLOWED_DOMAINS` | Comma separated list of allowed domains. Empty = no limitations | `` |
+| `ALLOWED_DOMAINS_RULESET` | Allow Domains from Ruleset. false = no limitations | `false` |
+
+`ALLOWED_DOMAINS` and `ALLOWED_DOMAINS_RULESET` are joined together. If both are empty, no limitations are applied.
diff --git a/docs/install/kubernetes.md b/docs/install/kubernetes.md
new file mode 100644
index 0000000..b2e5d11
--- /dev/null
+++ b/docs/install/kubernetes.md
@@ -0,0 +1,44 @@
+---
+sidebar_position: 3
+---
+
+# Kubernetes
+
+:::caution
+
+If your instance will be publicly accessible, make sure to enable Basic Auth. This will prevent unauthorized users from using your proxy. If you do not enable Basic Auth, anyone can use your proxy to browse nasty/illegal stuff. And you will be responsible for it.
+
+:::
+
+You can deploy Ladder on Kubernetes using the [Helm chart](https://github.com/everywall/ladder/tree/main/helm-chart).
+
+## Deployment prerequisites
+
+### Values
+
+Edit the values to your own preferences, with the only minimum requirement being `ingress.HOST` (line 19) being updated to your intended domain name.
+
+Other variables in `values.yaml` can be updated as to your preferences, with details on each variable listed in [environment variables](environment-variables.md).
+
+### Defaults in Kubernetes
+
+No ingress default has been specified.
+You can set this manually by adding an annotation to the ingress.yaml - if needed.
+For example, to use Traefik -
+
+```yaml
+metadata:
+ name: ladder-ingress
+ annotations:
+ kubernetes.io/ingress.class: traefik
+```
+
+## Helm Install
+
+`helm install -n --create-namespace`
+`helm install ladder .\ladder\ -n ladder --create-namespace`
+
+## Helm Upgrade
+
+`helm upgrade -n `
+`helm upgrade ladder .\ladder\ -n ladder`
diff --git a/docs/intro.md b/docs/intro.md
deleted file mode 100644
index 45e8604..0000000
--- a/docs/intro.md
+++ /dev/null
@@ -1,47 +0,0 @@
----
-sidebar_position: 1
----
-
-# Tutorial Intro
-
-Let's discover **Docusaurus in less than 5 minutes**.
-
-## Getting Started
-
-Get started by **creating a new site**.
-
-Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new)**.
-
-### What you'll need
-
-- [Node.js](https://nodejs.org/en/download/) version 18.0 or above:
- - When installing Node.js, you are recommended to check all checkboxes related to dependencies.
-
-## Generate a new site
-
-Generate a new Docusaurus site using the **classic template**.
-
-The classic template will automatically be added to your project after you run the command:
-
-```bash
-npm init docusaurus@latest my-website classic
-```
-
-You can type this command into Command Prompt, Powershell, Terminal, or any other integrated terminal of your code editor.
-
-The command also installs all necessary dependencies you need to run Docusaurus.
-
-## Start your site
-
-Run the development server:
-
-```bash
-cd my-website
-npm run start
-```
-
-The `cd` command changes the directory you're working with. In order to work with your newly created Docusaurus site, you'll need to navigate the terminal there.
-
-The `npm run start` command builds your website locally and serves it through a development server, ready for you to view at http://localhost:3000/.
-
-Open `docs/intro.md` (this page) and edit some lines: the site **reloads automatically** and displays your changes.
diff --git a/docs/tutorial-extras/_category_.json b/docs/modifiers/_category_.json
similarity index 50%
rename from docs/tutorial-extras/_category_.json
rename to docs/modifiers/_category_.json
index a8ffcc1..2f80356 100644
--- a/docs/tutorial-extras/_category_.json
+++ b/docs/modifiers/_category_.json
@@ -1,6 +1,6 @@
{
- "label": "Tutorial - Extras",
- "position": 3,
+ "label": "Modifiers",
+ "position": 4,
"link": {
"type": "generated-index"
}
diff --git a/docs/modifiers/request-modifiers.md b/docs/modifiers/request-modifiers.md
new file mode 100644
index 0000000..654155f
--- /dev/null
+++ b/docs/modifiers/request-modifiers.md
@@ -0,0 +1,51 @@
+---
+sidebar_position: 1
+description: "Request modifier functions"
+---
+
+# Request modifiers
+
+| Function | Description |
+| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `AddCacheBusterQuery()` | AddCacheBusterQuery modifies query params to add a random parameter key in order to get the upstream network stack to serve a fresh copy of the page. |
+| `DeleteOutgoingCookie(name string)` | DeleteOutgoingCookie modifies the http request's cookies header to delete a specific request cookie going to the upstream server. If the cookie does not exist, it does not do anything. |
+| `DeleteOutgoingCookies()` | DeleteOutgoingCookies removes the cookie header entirely, preventing any cookies from reaching the upstream server. |
+| `DeleteOutgoingCookiesExcept(whitelist ...string)` | DeleteOutGoingCookiesExcept prevents non-whitelisted cookies from being sent from the client to the upstream proxy server. Cookies whose names are in the whitelist are not removed. |
+| `DeleteRequestHeader(name string)` | DeleteRequestHeader modifies a specific outgoing header This is the header that the upstream server will see. |
+| `ForwardRequestHeaders()` | ForwardRequestHeaders forwards the requests headers sent from the client to the upstream server. |
+| `HideOrigin()` | HideOrigin modifies the origin header so that it is the original origin, not the proxy. |
+| `HideReferrer()` | HideReferrer modifies the referrer header so that it is the original referrer, not the proxy |
+| `MasqueradeAsBaiduBot()` | MasqueradeAsBaiduBot modifies user agent and x-forwarded for to appear to be a Baidu Spider Bot |
+| `MasqueradeAsBingBot()` | MasqueradeAsBingBot modifies user agent and x-forwarded for to appear to be a Bing Bot |
+| `MasqueradeAsDuckDuckBot()` | MasqueradeAsDuckDuckBot modifies user agent and x-forwarded for to appear to be a DuckDuckGo Bot |
+| `MasqueradeAsFacebookBot()` | MasqueradeAsFacebookBot modifies user agent and x-forwarded for to appear to be a Facebook Bot (link previews?) |
+| `MasqueradeAsGoogleBot()` | MasqueradeAsGoogleBot modifies user agent and x-forwarded for to appear to be a Google Bot |
+| `MasqueradeAsWaybackMachineBot()` | MasqueradeAsWaybackMachineBot modifies user agent and x-forwarded for to appear to be a archive.org (wayback machine) Bot |
+| `MasqueradeAsYahooBot()` | MasqueradeAsYahooBot modifies user agent and x-forwarded for to appear to be a Yahoo Bot |
+| `MasqueradeAsYandexBot()` | MasqueradeAsYandexBot modifies user agent and x-forwarded for to appear to be a Yandex Spider Bot |
+| `ModifyDomainWithRegex(matchRegex string, replacement string)` | ModifyDomainWithRegex replaces a domain with a replacement string |
+| `ModifyPathWithRegex(matchRegex string, replacement string)` | ModifyPathWithRegex replaces the path with a replacement string |
+| `ModifyQueryParams(key string, value string)` | ModifyQueryParams replaces query parameter values in URL's query params in a ProxyChain's URL. If the query param key doesn't exist, it is created. |
+| `RequestArchiveIs()` | RequestArchiveIs modifies a ProxyChain's URL to request an archived version from archive.is |
+| `RequestGoogleCache()` | RequestGoogleCache modifies a ProxyChain's URL to request its Google Cache version. |
+| `RequestWaybackMachine()` | RequestWaybackMachine modifies a ProxyChain's URL to request the wayback machine (archive.org) version. |
+| `ResolveWithGoogleDoH()` | ResolveWithGoogleDoH modifies a ProxyChain's client to make the request by resolving the URL using Google's DNS over HTTPs service. |
+| `SetOutgoingCookie(name string, val string)` | SetOutgoingCookie modifes a specific cookie name by modifying the request cookie headers going to the upstream server. If the cookie name does not already exist, it is created. |
+| `SetOutgoingCookies(cookies string)` | SetOutgoingCookies modifies a client request's cookie header to a raw Cookie string, overwriting existing cookies. |
+| `SetRequestHeader(name string, val string)` | SetRequestHeader modifies a specific outgoing header This is the header that the upstream server will see. |
+| `SpoofOrigin(url string)` | SpoofOrigin modifies the origin header if the upstream server returns a Vary header it means you might get a different response if you change this |
+| `SpoofReferrer(url string)` | SpoofReferrer modifies the referrer header. It is useful if the page can be accessed from a search engine or social media site, but not by browsing the website itself. if url is "", then the referrer header is removed. |
+| `SpoofReferrerFromBaiduSearch()` | SpoofReferrerFromBaiduSearch modifies the referrer header pretending to be from a BaiduSearch |
+| `SpoofReferrerFromBingSearch()` | SpoofReferrerFromBingSearch modifies the referrer header pretending to be from a bing search site |
+| `SpoofReferrerFromGoogleSearch()` | SpoofReferrerFromGoogleSearch modifies the referrer header pretending to be from a google search site |
+| `SpoofReferrerFromLinkedInPost()` | SpoofReferrerFromLinkedInPost modifies the referrer header pretending to be from a linkedin post |
+| `SpoofReferrerFromNaverSearch()` | SpoofReferrerFromNaverSearch modifies the referrer header pretending to be from a Naver search (popular in South Korea) |
+| `SpoofReferrerFromPinterestPost()` | SpoofReferrerFromPinterestPost modifies the referrer header pretending to be from a pinterest post |
+| `SpoofReferrerFromQQPost()` | SpoofReferrerFromQQPost modifies the referrer header pretending to be from a QQ post (popular social media in China) |
+| `SpoofReferrerFromRedditPost()` | SpoofReferrerFromRedditPost modifies the referrer header pretending to be from a reddit post |
+| `SpoofReferrerFromTumblrPost()` | SpoofReferrerFromTumblrPost modifies the referrer header pretending to be from a tumblr post |
+| `SpoofReferrerFromTwitterPost()` | SpoofReferrerFromTwitterPost modifies the referrer header pretending to be from a twitter post |
+| `SpoofReferrerFromVkontaktePost()` | SpoofReferrerFromVkontaktePost modifies the referrer header pretending to be from a vkontakte post (popular in Russia) |
+| `SpoofReferrerFromWeiboPost()` | SpoofReferrerFromWeiboPost modifies the referrer header pretending to be from a Weibo post (popular in China) |
+| `SpoofUserAgent(ua string)` | SpoofUserAgent modifies the user agent. |
+| `SpoofXForwardedFor(ip string)` | SpoofXForwardedFor modifies the X-Forwarded-For header in some cases, a forward proxy may interpret this as the source IP. |
diff --git a/docs/modifiers/response-modifiers.md b/docs/modifiers/response-modifiers.md
new file mode 100644
index 0000000..e697450
--- /dev/null
+++ b/docs/modifiers/response-modifiers.md
@@ -0,0 +1,32 @@
+---
+sidebar_position: 2
+description: "Response modifier functions"
+---
+
+# Response modifiers
+
+| Function | Description |
+| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `APIContent()` | APIContent creates an JSON representation of the article and returns it as an API response. |
+| `BlockElementRemoval(cssSelector string)` | BlockElementRemoval prevents paywall javascript from removing a particular element by detecting the removal, then immediately reinserting it. This is useful when a page will return a "fake" 404, after flashing the content briefly. If the /outline/ API works, but the regular API doesn't, try this modifier. |
+| `BlockThirdPartyScripts()` | BlockThirdPartyScripts rewrites HTML and injects JS to block all third party JS from loading. |
+| `BypassCORS()` | BypassCORS modifies response headers to prevent the browser from enforcing any CORS restrictions. This should run at the end of the chain. |
+| `BypassContentSecurityPolicy()` | BypassContentSecurityPolicy modifies response headers to prevent the browser from enforcing any CSP restrictions. This should run at the end of the chain. |
+| `DeleteIncomingCookies(_ ...string)` | DeleteIncomingCookies prevents ALL cookies from being sent from the proxy server back down to the client. |
+| `DeleteIncomingCookiesExcept(whitelist ...string)` | DeleteIncomingCookiesExcept prevents non-whitelisted cookies from being sent from the proxy server to the client. Cookies whose names are in the whitelist are not removed. |
+| `DeleteLocalStorageData()` | DeleteLocalStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteSessionStorageData and DeleteIncomingCookies |
+| `DeleteResponseHeader(key string)` | DeleteResponseHeader removes response headers from the upstream server |
+| `DeleteSessionStorageData()` | DeleteSessionStorageData deletes localstorage cookies. If the page works once in a fresh incognito window, but fails for subsequent loads, try this response modifier alongside DeleteLocalStorageData and DeleteIncomingCookies |
+| `ForwardResponseHeaders()` | ForwardResponseHeaders forwards the response headers from the upstream server to the client |
+| `GenerateReadableOutline()` | GenerateReadableOutline creates an reader-friendly distilled representation of the article. This is a reliable way of bypassing soft-paywalled articles, where the content is hidden, but still present in the DOM. |
+| `InjectScriptAfterDOMContentLoaded(js string)` | InjectScriptAfterDOMContentLoaded modifies HTTP responses to inject a JS after DOM Content is loaded (script tag in head) |
+| `InjectScriptAfterDOMIdle(js string)` | InjectScriptAfterDOMIdle modifies HTTP responses to inject a JS after the DOM is idle (ie: js framework loaded) |
+| `InjectScriptBeforeDOMContentLoaded(js string)` | InjectScriptBeforeDOMContentLoaded modifies HTTP responses to inject a JS before DOM Content is loaded (script tag in head) |
+| `ModifyIncomingScriptsWithRegex(matchRegex string, replacement string)` | ModifyIncomingScriptsWithRegex modifies all incoming javascript (application/javascript and inline `