Crear paneles
Referencia de panel.json
Cada campo de panel.json, las reglas con las que se revisa, los ids y nombres que se rechazan, y los límites de un paquete.
El paquete
Un paquete es una carpeta, o un zip una vez publicado, con panel.json en la raíz. Lleva todo el comportamiento del panel como archivos web y nada que se ejecute en la computadora. Solo son obligatorios panel.json y las páginas que nombra; el resto es lo que carguen tus páginas.
pomodoro-plus/
panel.json
index.html
extras.html
app.js
app.css
assets/
bell.webp
inter.woff2
icon.svg
README.mdindex.htmles la página que abre el panel (con cualquier nombre, el que digacontributes.panel.entry).extras.htmles opcional: la página que muestra Extras al abrir su fila.README.mdes para quien lea el paquete. Deska no lo muestra.
Un panel.json completo
{
"schema": 1,
"id": "pomodoro-plus",
"name": "Pomodoro Plus",
"version": "1.2.0",
"description": "A focus timer with breaks and a daily count.",
"author": "pasho",
"icon": "icon.svg",
"color": "#e66b4f",
"category": "productivity",
"permissions": ["notify"],
"network": ["api.example.com"],
"sdk": 1,
"contributes": {
"panel": { "entry": "index.html", "scope": "workspace", "size": { "width": 360, "height": 280 } },
"extras": { "title": "Pomodoro Plus", "view": "extras.html" }
}
}Deska lee cada campo cuando cargas la carpeta, y deska.dev los vuelve a leer todos cuando publicas. Todos los problemas se reportan juntos, para que corrijas el manifiesto de una sola vez.
Campos
| Campo | Obligatorio | Regla |
|---|---|---|
schema | Sí | 1. Un número mayor se rechaza con “This package needs a newer Deska.” |
id | Sí | De 3 a 40 letras minúsculas, dígitos y guiones, empezando y terminando con una letra o un dígito. Consulta El id. |
name | Sí | Hasta 40 caracteres. |
version | Sí | Semver, como 1.2.0 o 1.2.0-beta.1, hasta 64 caracteres. Consulta Versiones. |
description | Sí | Una línea, hasta 140 caracteres. |
author | Sí | El nombre que la gente ve como autor, hasta 40 caracteres. |
icon | No | La ruta de un .svg, .png o .webp dentro del paquete. La Biblioteca de paneles lo dibuja en la tarjeta del panel. |
color | No | #rrggbb, como #e66b4f. Se guarda en minúsculas. |
category | No | productivity, media, dev, ambient u other, el valor por defecto. |
permissions | No | Una lista de notify, open-url y clipboard-write. Uno desconocido rechaza el paquete; uno repetido se guarda una vez. |
network | No | Hasta 20 nombres de host a los que el panel puede conectarse por https. Consulta Sitios. |
embeds | No | Hasta 10 nombres de host cuyas páginas el panel puede mostrar a través de Deska. Necesita "sdk": 2. Consulta Páginas de otros sitios. |
signedInEmbeds | No | true pide que las páginas de embeds mantengan la sesión de la persona en esos sitios, en una sesión propia del panel. Necesita embeds. Consulta Mantener la sesión. |
sdk | No | La versión del SDK para la que se escribió el panel: 1, el valor por defecto cuando falta, o 2 para embeds. Una mayor que la que entiende esta versión de Deska se rechaza igual que schema. |
contributes | Sí | Dónde aparece el panel, con al menos panel. Consulta Lugares. |
Cualquier otro campo de primer nivel rechaza el paquete, así que un error de tipeo como permission nunca pasa en silencio. Los textos se recortan en los extremos, y name, description, author y el título de Extras no pueden tener caracteres de control, de ancho cero o bidireccionales, ni la mitad de un carácter sin su otra mitad. Los emoji completos están bien.
El id
El id nombra al panel en todas partes: la carpeta donde se desempaca en cada computadora, su almacenamiento, su ficha y su página en deska.dev. La primera versión publicada lo reserva para tu cuenta, y solo esa cuenta puede publicar más versiones con él.
Deska rechaza un id que no se pueda usar en todos los sistemas donde corre:
- Un nombre que Windows reserva para un dispositivo:
con,prn,aux,nul, decom0acom9y delpt0alpt9. constructor.
Al publicar, deska.dev también rechaza los ids que se leerían como propios de Deska. Una carpeta cargada con uno de ellos sigue funcionando mientras construyes:
- Cualquier id que empiece con
dev-(el nombre que Deska usa para las carpetas cargadas) o condeska-. - Deska y Dex (
deska,dex,ask-dex), los agentes de programación y sus creadores (claude,codex,cursor,opencode,antigravity,gemini,openai,anthropicy similares). - Los paneles incluidos y sus tarjetas de la Biblioteca de paneles, como
terminal,browser,editor,todo,pomodoro,music,youtube,spotifyosticky-note. - Los lugares de Deska y palabras que suenan oficiales:
extras,library,community,settings,official,sdk,api,admin, yapply, una página de deska.dev bajo/panels.
focus-timer o team-clocks. Aparece en la dirección del panel en deska.dev y no cambia una vez publicado.Nombres que se leen como Deska
Cada panel de la comunidad dice que lo hizo alguien que no es Deska, así que su name, su author y el title de Extras no pueden hacerse pasar por Deska. Al publicar, deska.dev rechaza uno que contenga la palabra “Dex”, o una palabra que empiece con “Deska”, y nombra cada campo que hay que cambiar.
- Las palabras se leen como las lee una persona: con mayúsculas o minúsculas, con acentos, con letras parecidas de otros alfabetos, letras de ancho completo o estilizadas, dígitos en lugar de letras (3, 4 y 5 por e, a y s) y letras separadas una por una.
- Cuenta una parte de una palabra en camelCase: “DexTimer” y “MyDeska” se rechazan, “DeskApp” pasa.
- Dex nunca cuenta al final de una palabra, así que MangaDex, Rolodex, Dexter y Codex pasan.
- Un autor puede llamarse Dex, mientras Dex no sea todo su nombre.
Versiones
version es semver: tres números enteros sin ceros a la izquierda, y una preversión opcional después de un guion (1.4.0, 2.0.0-rc.1). No se aceptan metadatos de compilación después de un signo más.
- Una versión publicada nunca cambia. Para cambiar algo, sube la versión.
- Cada versión nueva debe ser mayor que la anterior. Los números se comparan como números de cualquier largo, y una preversión va antes que su versión final:
1.2.0-beta.2va antes que1.2.0. - Mientras construyes, la versión no se compara con nada: una carpeta cargada no tiene una versión publicada.
Permisos
Sin ningún permiso, un panel puede dibujar, guardar sus propios datos, seguir el tema, saber si se ve, poner su título y, si declara una, llenar su fila de Extras. Pide solo lo que usas: la gente lee la lista antes de instalar.
| Permiso | Qué permite | La gente ve |
|---|---|---|
notify | deska.notify: un aviso en Deska, con el nombre del panel, como máximo uno cada diez segundos. | Enviar notificaciones |
open-url | deska.openUrl: un enlace https en el navegador, desde un clic en el panel. Deska le pregunta a la persona la primera vez para cada sitio. | Abrir enlaces |
clipboard-write | deska.clipboard.write y deska.clipboard.writeImage: texto, o una imagen PNG o JPEG, al portapapeles, desde un clic en el panel. Sin él, los propios comandos de copiar de la página tampoco hacen nada. | Copiar al portapapeles |
Cada versión pide sus propios permisos. A quien instaló una anterior se le vuelve a preguntar antes de una actualización que pida más. No existe un permiso para leer el portapapeles, los archivos, el micrófono, la cámara ni la ubicación. Guardar archivos con deska.files y guardar uno con deska.files.save no necesitan ninguno: los archivos son del propio panel, y el diálogo de guardar es el consentimiento de la persona.
Sitios
network lista los hosts a los que el panel puede conectarse, y puede llegar a esos y a ningún otro: fetch, imágenes, fuentes, audio y video vienen del paquete o de estos hosts, por https. Un panel con la lista vacía no puede conectarse a internet.
- Un nombre de host simple, en minúsculas y con al menos un punto:
api.example.com. Sin esquema, ruta, puerto, comodines ni direcciones IP. - Solo nombres exactos.
example.comno cubreapi.example.com; lista cada host. Si un servicio usa muchos hosts, lista los que usa, como hace Net Radio con seis réplicas de streaming. - Como máximo 20. Un host repetido se guarda una vez.
La gente ve cada host en la página del panel. La pregunta antes de instalar también los nombra, o los primeros cinco y cuántos más cuando son siete o más. Una actualización que agrega un host nombra cada host nuevo.
Páginas de otros sitios
embeds lista los hosts cuyas páginas el panel puede mostrar, como un reproductor de video o un mapa. El panel nunca las enmarca por su cuenta: se lo pide a Deska con deska.embed, y Deska dibuja un marco propio sobre el panel. Consulta el sandbox para ver qué permite ese marco.
{
"embeds": ["www.youtube-nocookie.com"],
"sdk": 2
}- Las mismas reglas de host que
network: un nombre de host simple, en minúsculas y exacto, sin esquema, ruta, puerto, comodines ni direcciones IP. - Como máximo 10. Un host repetido se guarda una vez.
- Nunca los sitios de Deska, ni un host de inicio de sesión o de pago, con todos los hosts que cuelgan de ellos: deska.dev, clerk.com, accounts.google.com, appleid.apple.com, login.microsoftonline.com, github.com, gitlab.com, stripe.com, paypal.com y algunos más. Una copia enmarcada de una página de inicio de sesión es como se roban contraseñas.
- Un paquete que declara
embedsnecesita"sdk": 2. embedsno cubrenetwork: lista un host en los dos cuando el panel también le hace pedidos.
La gente ve estos hosts en la página del panel, y la pregunta antes de instalar dice que el panel mostrará páginas de ellos. Una actualización que agrega un host vuelve a preguntar. Publicar una versión con embeds necesita una cuenta que Deska aprobó para publicar.
Instalada desde la Library, una versión muestra estas páginas solo cuando Deska revisó y aprobó exactamente esa versión. Cada versión nueva espera su propia aprobación, y Deska puede retirar una aprobación. Una carpeta que cargas en Build a panel las muestra mientras la construyes.
Mantener la sesión
Las páginas de otros sitios corren sin sesión por defecto. Un panel que necesita lo que la persona ve en un sitio, como su calendario, pone "signedInEmbeds": true: sus páginas mantienen entonces la sesión de la persona en esos sitios, en una sesión propia de este panel, separada de la app, de los paneles de navegador y de cualquier otro panel. Necesita hosts en embeds, y solo tiene efecto cuando Deska verificó exactamente esa versión para eso; hasta entonces, o si Deska la aprueba sin sesión, las páginas se muestran sin sesión. La página del panel dice que lo pide.
Deska también puede bloquear un sitio para todos los paneles a la vez. Una computadora deja de conectarse a él y de mostrarlo en su siguiente revisión, diga lo que diga panel.json, y una versión que lo nombra en network o embeds no se puede publicar.
Lugares
contributes.panel
Obligatorio: el panel en el escritorio.
entry: la ruta de una página.htmldel paquete.scope:workspace, el valor por defecto, permite que un proyecto tenga todas las copias que la persona agregue.globalmantiene una por proyecto: agregarlo otra vez trae al frente la que ya está abierta. Úsalo para algo que nunca debería correr dos veces, como una radio.size: opcional, el tamaño con el que abre un panel nuevo, conwidthyheightenteros de 120 a 4000.
contributes.extras
Opcional: una fila en el popover Extras.
title: el nombre de la fila, hasta 40 caracteres.view: opcional, una página.htmlque se abre dentro del popover. Sin ella, el popover muestra la página de entrada del panel.
Las claves desconocidas dentro de contributes se ignoran con una advertencia, así que un lugar que aprenda una versión más nueva de Deska nunca deja a una anterior sin tu panel. Consulta Extras para ver qué muestra la fila.
Límites del paquete
- Un paquete pesa como máximo 5 MB comprimido, y se desempaca en 20 MB y 500 archivos como máximo.
- Tipos de archivo:
html,js,mjs,css,json,svg,png,jpg,jpeg,webp,gif,woff2,mdytxt. Cualquier otro rechaza el paquete, incluidoswasm,mp3yttf. - Las rutas son relativas y de 200 caracteres como máximo, sin
.., sin segmentos vacíos ni., sin barra invertida y nada dentro de__deska/, donde vive el SDK. - Cada nombre debe poder escribirse en Windows: ninguno de
: * ? " < > |, ningún nombre que termine en punto o espacio, ningún nombre de dispositivo comocon.htmlocom1.js, y no dos rutas que solo difieran en mayúsculas. - Solo archivos normales: los enlaces simbólicos y archivos especiales se rechazan.
__MACOSX/y los archivos ocultos como.DS_Storeo.gitse omiten, no se rechazan. Un zip hecho de la carpeta misma (pomodoro-plus/panel.json) se lee como si se hubiera hecho desde dentro.- Cada página y el ícono que nombra panel.json deben estar en el paquete.
Lo que dicen las revisiones
Deska lista cada problema en la página de la carpeta cargada en Crear un panel, los primeros cincuenta y cuántos más hay. Los mensajes están en inglés aunque la app esté en español; estos son los más comunes:
| Mensaje | Solución |
|---|---|
| Unknown field "…". | Quita o renombra el campo; solo se leen los campos de arriba. |
| "id" is 3 to 40 lowercase letters, digits and dashes… | Pásalo a minúsculas y cambia espacios o guiones bajos por guiones. |
| "id" cannot be "…". Pick another. | El id es un nombre de dispositivo o constructor. |
| "version" must be a semver version such as 1.0.0. | Usa tres números: 0.1.0. |
| "…" is N characters; the limit is M. | Acorta el nombre, la descripción, el autor o el título de Extras. |
| "…" holds invisible or control characters. | Vuelve a escribir el texto; un nombre pegado puede traer un espacio de ancho cero. |
| "…" is not a host name (no scheme, port, wildcard or IP address). | Escribe api.example.com, no https://api.example.com/v1. |
| Unknown permission "…". Known: notify, open-url, clipboard-write. | Revisa cómo está escrito. |
| "contributes.panel.entry" must point at an .html page. | Apúntalo a una página, como index.html. |
| … is named in panel.json but is not in the package. | Agrega el archivo o corrige la ruta; las rutas distinguen mayúsculas. |
| …: this kind of file is not allowed in a package. | Quítalo, o conviértelo a un tipo permitido. |
| A package holds at most 500 files; this one has N. | Carga la carpeta donde está panel.json, no la raíz de un proyecto. |
| … cannot be shown inside a panel: it is a sign-in, payment or Deska page. | Quita el host de embeds; nunca se permite. |
| A package with "embeds" needs "sdk": 2 or later. | Agrega "sdk": 2 a panel.json. |
| "signedInEmbeds" needs hosts under "embeds". | Lista los sitios en embeds, o quita signedInEmbeds. |
| Deska blocked … for every panel, so a package may not reach it or show its pages. | Quita el host de network y de embeds. |
| This package needs a newer Deska. | Pon schema en 1 y sdk en 1, o en 2 con embeds, o actualiza Deska. |