In Technology Preview 118, Safari introduced a feature called Local Overrides. It enables web developers to customize network request and response activities from within the Safari developer tools.

Let’s see how to use Local Overrides in Safari and discover how this can be of great help when creating front-end applications consuming a REST API and more general Jamstack workflows.

What are we going to build

Here is a hypothetical situation where you as a web developer have been tasked with crafting a front-end experience powered by some kind of remote API — the Star Wars API’s (fictional) new endpoint to retrieve a list of all known rebels. Your job is to display the list of rebel names as it will be returned by a (not yet existing) endpoint https://swapi.dev/api/rebels.

You have also received an example JSON payload that illustrates the shape of the remote API’s response when it will be completed:

{"results":[{"name":"Sabine"},{"name":"Ezra"},{"name":"Kanan"}]}

Let’s begin 🚀

Example Application

Let’s start by creating a very simple web page with the purpose of loading and showing a list of rebels as they would be returned by the Star Wars API (SWAPI). (Remember, this endpoint doesn’t exist yet!)

To realise this, I will use Vite which is a fast and straightforward build tool for modern JavaScript apps (feel free to use your favourite tool or none at all!)

To scaffold the app, let’s execute the following commands in Terminal:

npm init vite@latest safari-web-dev -- --template vanilla
cd safari-web-dev
npm install
npm run dev

The last command starts the development server, making our app reachable at http://localhost:3000.

Hello world 🎉, Safari showing the default Vite start page

The REST API endpoint we are going to query is located at https://swapi.dev/api/rebels. Let’s edit main.js so that it:

To load the data from the REST API we can use the fetch api:

const response = await fetch("https://swapi.dev/api/rebels");
const list = await response.json();

To display the list of rebels on the page, we are going to create an unordered list element as a child to the #app div tag already present on the page.

const ul = document.createElement("ul");
for (const rebel of list.results) {
  const li = document.createElement("li");
  li.innerText = rebel.name;
  ul.appendChild(li);
}
document.querySelector("#app").appendChild(ul);

Remember the /rebels endpoint doesn’t exist yet. If we just try to request it as is, we’d get an error (HTTP 404, not found):

Safari’s Network inspector showing the HTTP response from the endpoint is error 404, not found

Now comes the cool part, let’s tell Safari about our future API!

Local Overrides

Safari’s Local Overrides allows us to simply instruct the browser about what a certain request or response to/from a given endpoint should be and all subsequent uses of that endpoint provide the override content! So in case of overriding a server response, Safari will simply return the override content as if it is the actual server response 😍!

In the Sources inspector, in the lower-left area, there is a plus button, which expands a menu allowing us to create a new Local Override. Since we want to mimic what the remote API would respond to, the type of override we are creating is Response. We also need to configure the response headers — the type of content we are receiving (Content-Type: application/json) as well as a correct CORS header configuration (Access-Control-Allow-Origin *).

Now you can reload the page for our web app to receive the provided override content as if it’s coming from the server!

Notes