agente de cliente
Browser
Lo que el servidor no puede ver: cuánto tardó de verdad la página para una persona real, qué clics no hicieron nada, y qué componente se volvió a renderizar cuatrocientas veces.
- paquete
@sixty-sh/browseren npm- funciona sobre
- Cualquier página. Alrededor de 2,4 µs de coste bloqueante por cada petición que observa.
- código
- sixty-sh/sixty-browser
Cómo instalarlo
Next, Remix, SvelteKit and friends. The key stays server-side behind a proxy route.
La instalación está escrita como un prompt para el agente de código que ya tienes abierto, no como una lista de tareas para ti. Es deliberado: nombra lo que tiene que ser cierto cuando la instalación esté terminada en vez de qué archivos editar, porque dónde va el código depende del framework y ponerlo en el sitio equivocado falla en silencio. Un agente puede leer tu repositorio y deducirlo; un párrafo en una página de documentación no.
El mismo texto es lo que devuelve install_sixty a través de el servidor MCP y lo que el colector sirve en /v1/setup?kind=browser. Hay una sola copia.
la instalación de Browser, completa
Set up @sixty-sh/browser in this project so page performance reports to sixty.
Before editing, ask the user: "Do you want privacy-masked session replay?"
Do not choose for them. If yes, use the replay-enabled init in step 3. If no,
use plain init() and do not add replay configuration.
1. Install @sixty-sh/browser.
2. Add a server-side endpoint at the path /api/drift whose GET and POST
handlers are both the same createSixtyProxy() handler from
"@sixty-sh/browser/proxy". Work out the correct
file and export style for this project's framework and router. It must run
on the server, not the client. POST receives measurements and recordings;
GET reads the Sessions policy. Omitting either method is an incomplete install.
3. Call init() from "@sixty-sh/browser" exactly once in the browser, in a
client component that is mounted on every page (the root layout is usually
right). If the user chose replay, call
init({ replay: { enabled: true } }); otherwise call init(). The default
endpoint is /api/drift.
@sixty-sh/browser owns the compatible recorder dependency, so do not install
or import rrweb separately. Replay remains privacy-masked and the Sessions
setting decides whether recordings are off, incident-only, or sampled.
4. Set these server-side environment variables (never client-exposed ones):
SIXTY_API_KEY = a secret key starting sixty_sk_ — ask me for it, I can
generate one on the Settings page. Do not invent one.
SIXTY_SERVICE = my-app
SIXTY_ENDPOINT = https://ingest.sixty.sh
5. If this project has a router that knows its route patterns, call setRoute()
from "@sixty-sh/browser" with the pattern (e.g. "/orders/[id]") on each
navigation. Without it, routes are guessed from the URL, which is close but
not exact.
Constraints — these are correctness requirements, not style preferences:
- SIXTY_API_KEY must never reach the browser. Do not prefix it with NEXT_PUBLIC_,
VITE_, or PUBLIC_, do not pass it to init(), and do not import it into any
client component. The whole point of the proxy is that the key stays server-side.
- Do not add any analytics, user id, session id, or cookie. The agent is
deliberately anonymous and must stay that way.
- Do not call init() during server rendering. It returns null there, so guard it
in an effect or a client-only component rather than at module scope.
When you are done, tell me which files you changed and how to deploy so I can
confirm data is arriving.Necesita una clave secreta — empieza por sixty_sk_ y se queda en el servidor. Genera una en la página de Ajustes cuando hayas iniciado sesión.
Qué mide
| señal | unidad | qué significa |
|---|---|---|
web_vital | ms | a page-speed metric got worse for real users |
render_storm | renders | a component re-renders many times for one interaction |
dead_interaction | of clicks | users click this and nothing observable happens |
stuck_loading | of loads never finish | a loading state is entered and never left |
client_error | of views | this error is being thrown in real users’ browsers |
auth_failures | — | The server is turning these away on permission grounds rather than failing. People see an empty page or a save that quietly does nothing. |
silent_empty | — | The query runs and succeeds, and returns no rows where it used to return plenty. Nothing reports an error, so the page just renders blank — this is what a broken permission rule looks like from the outside. |
latency | ms per call | this operation takes longer end to end than it used to |
errors | error rate | a larger fraction of calls are throwing |
runaway | calls per minute | this operation is being called far more often than anything triggers it |
Dónde se engancha
- Next, Remix, SvelteKit — Tener servidor propio significa que la clave se queda en el servidor detrás de una ruta de proxy — coge este nivel, no el de Lovable.
- Sin servidor alguno — Lovable, un hosting estático, una aplicación solo con Supabase: mira el nivel de Lovable, que usa una clave pública anclada al origen.
Qué hace solo este
- Velocidad de página por ruta y por país — LCP, INP, CLS y TTFB de visitas reales, comparados con la versión anterior y no con una ejecución de laboratorio.
- Bucles de render — Una interacción que vuelve a renderizar la página cientos de veces. Nada del lado servidor puede ver esto y no se lanza ningún error.
- Clics que no hacen nada — Un control que se pulsa y no produce ningún cambio medible — ni petición, ni navegación, ni mutación del DOM.
- Cargas que nunca terminan — Un estado de carga en el que se entra y del que no se sale nunca, que es el fallo que produce un ticket de soporte y ninguna línea de registro.
Qué no puede hacer
- No se recoge identidad de usuario de ningún tipo — sin id, sin sesión, sin cookie. Eso es una restricción de diseño y no un ajuste, así que «qué usuario vio esto» es una pregunta que este producto no puede responderle a nadie, nosotros incluidos.
- Los frames de la pila en producción apuntan a chunks empaquetados. El nombre de la operación y el mensaje son lo que identifica un error de navegador, no el número de línea.
Configuración
Todos los agentes leen las mismas cuatro variables, y DRIFT_* sigue respondiendo allí donde lo hace SIXTY_* — el producto se renombró y ese nombre no es nuestro para retirarlo de los despliegues de otra gente.
SIXTY_API_KEY | Sin ella el agente se queda inerte y lo dice. Nunca adivina, nunca reintenta contra un endpoint desconocido, y nunca lanza una excepción. |
|---|---|
SIXTY_SERVICE | Cómo llamar a este servicio. Por defecto, el nombre del proyecto donde sea legible. |
SIXTY_RELEASE | La que más importa. Se recoge automáticamente en Vercel, Render, Railway, Fly, Heroku y GitHub Actions; en cualquier otro sitio, ponla al SHA del commit. Sin ella cada medición cae en un único cubo sin nombre y no se puede hacer ninguna comparación. |
SIXTY_ENDPOINT | Dónde reportar. Por defecto http://localhost:4319, que es correcto en un portátil y erróneo en cuanto la aplicación se sirve a alguien más. |
El resto — intervalo de envío, tasa de muestreo, qué instrumentar — está en el propio README del paquete, que es donde puede seguir siendo cierto según cambia el agente.