# Chrome DevTools can connect to your local workspace automatically

The request for `/.well-known/appspecific/com.chrome.devtools.json` is used by
Chrome DevTools to discover a local workspace.

When a page is served from `localhost`, DevTools can read this JSON file and
offer to connect the page to the project folder. This makes edits in the Sources
panel save back to local files.

From the route you need to return the following JSON:

```json
{
  "workspace": {
    "root": "/Users/you/projects/example",
    "uuid": "53b029bb-c989-4dca-969b-835fecec3717"
  }
}
```

The UUID should be stable for the workspace. The `root` is an absolute path on
your computer. This feature is intended for local development, so returning
`404` in production is sensible.

## Serve it from a route

You can generate the response in your development server. In the examples below,
`process.cwd()` assumes that the server is started from the project root.
Replace it with the correct absolute path if it is not.

Generate a UUID once and keep it unchanged for the project:

```shell
uuidgen
```

If you don't have `uuidgen` in your system, use node:

```shell
node -e "console.log(require('node:crypto').randomUUID())"
```

### React Router

In React Router framework mode, add a
[resource route](https://reactrouter.com/how-to/resource-routes) to
`app/routes.ts`. Registering it only during development makes the URL return
`404` in production:

```ts
import { type RouteConfig, route } from '@react-router/dev/routes'

const routes = [
  route('/', 'routes/home.tsx'),
  // more routes...
] satisfies RouteConfig

if (process.env['NODE_ENV'] === 'development') {
  routes.push(
    route(
      '/.well-known/appspecific/com.chrome.devtools.json',
      'routes/devtools.ts'
    )
  )
}

export default routes
```

Then create `app/routes/devtools.ts`. A route module without a default component
is a resource route, and its `loader` handles `GET` requests:

```ts
import { uuid } from './constants.ts'

export function loader() {
  return Response.json({
    workspace: {
      root: process.cwd(),
      uuid: '7d6db5d9-b947-40bb-9f21-5ccdb4ef3b0c',
    },
  })
}
```

### Hono

Hono's [`c.json()`](https://hono.dev/docs/api/context#json) sets the JSON
content type for the response:

```ts
if (process.env['NODE_ENV'] === 'development') {
  app.get('/.well-known/appspecific/com.chrome.devtools.json', c =>
    c.json({
      workspace: {
        root: process.cwd(),
        uuid: '7d6db5d9-b947-40bb-9f21-5ccdb4ef3b0c',
      },
    })
  )
}
```

### Express

With Express, define a `GET` handler and send the object with
[`res.json()`](https://expressjs.com/en/api.html#res.json):

```ts
if (process.env['NODE_ENV'] === 'development') {
  app.get('/.well-known/appspecific/com.chrome.devtools.json', (_req, res) => {
    res.json({
      workspace: {
        root: process.cwd(),
        uuid: '7d6db5d9-b947-40bb-9f21-5ccdb4ef3b0c',
      },
    })
  })
}
```

See
[Automatic workspace connection in Chrome DevTools](https://developer.chrome.com/docs/devtools/automatic-workspaces/).
