Ir al contenido
Docxcelerate

Fundamentos

Estático y dinámico

Qué se resuelve en tu máquina, qué necesita el motor y por qué la línea está donde está.

Todo nodo de contenido es estático o dinámico. Esa distinción decide de dónde sale su texto y cuánto cuesta.

Nunca lo declaras. Hay un helper por cada clase, y el modo se deduce de las opciones que le des.

Nodos estáticos

Dale a un párrafo un render y podrá producirse a partir de tus datos, así que se resuelve en local:

paragraph<OfferData>({
  id: "offer",
  render: (data) =>
    `Your place starts on ${data.startDate}, at ${data.college}.`,
});

Se ejecuta en la vista previa, en las pruebas y en una compilación — sin conexión, al instante y gratis. Si todos los nodos de un documento son estáticos, no necesitas el motor en absoluto.

Nodos dinámicos

Dale en su lugar prompts, más un marcador de posición para que la vista previa siga siendo legible, y pasa a ser dinámico:

paragraph<OfferData>({
  id: "tutor-note",
  placeholder: (data) => `A note from ${data.interviewer}.`,
  generalPrompt: (data) =>
    `Write two warm sentences about ${data.applicantName}'s interview.`,
});

El mismo helper, con otras obligaciones. image y graph funcionan igual — src y data son sus miembros de resolución local.

Por qué se infiere

Un nodo que tiene render siempre puede producirse en local; uno que solo tiene prompts, nunca. Declarar el modo junto a esas opciones sería una segunda fuente de verdad que podría contradecirlas — un staticParagraph con un generalPrompt, o al revés, con alguna regla de precedencia decidiendo cuál gana.

En vez de eso, las opciones son la verdad y mode se deriva de ellas. Aportar a la vez un render y un generalPrompt es un error de compilación, no un cara o cruz en tiempo de ejecución.

mode sigue existiendo en el DocumentModel compilado y en document.json — el motor necesita saber qué nodos resolver. Es salida, no entrada.

Hay cuatro ranuras de prompt disponibles. Solo generalPrompt es obligatoria:

RanuraPropósito
generalPromptLo que el nodo debe decir
infoPromptContexto que el modelo debe tener pero no repetir
negativePromptLo que hay que evitar
systemPromptInstrucciones de rol y de tono

Lo que ves en local

Compilar para la vista previa resuelve los nodos dinámicos a sus marcadores de posición, no a texto generado:

const document = await buildProjectPreviewDocument(project);
// dynamic nodes -> placeholder text

Esto es deliberado. La vista previa se mantiene determinista y gratuita, de modo que puedes iterar sobre la estructura y el estilo sin que salga ni una sola petición de tu máquina. El marcador de posición es además una disciplina útil: si un documento resulta ilegible con los marcadores puestos, su estructura está haciendo demasiado poco trabajo.

Qué ocurre en el momento de la petición

El artefacto de subida conserva los valores del momento de la petición como tokens del tipo {{data.residentName}} para poder resolverlos más tarde. Enviarlo al motor devuelve el documento terminado con los nodos dinámicos rellenados.

El motor es un servicio aparte y gratuito que alojas tú — deliberadamente no forma parte del paquete de npm, de modo que instalar el framework nunca arrastra nada que quiera claves de API ni red. Apunta un workspace al tuyo:

dxcl init my-documents --api-endpoint https://documents.example.com/api/letters
dxcl init my-documents --no-api-endpoint

Puedes cambiar upload.endpoint en docxcelerate.config.json en cualquier momento.

Por qué la línea está aquí

Separar por nodo en lugar de por documento mantiene genuinamente útil la mitad gratuita del toolkit. Un documento enteramente estático es un documento completo y funcional sin ningún servicio detrás. Optas por la mitad alojada solo para los párrafos concretos que necesitan texto generado — y puedes ver exactamente cuáles son leyendo la plantilla.


Editar esta página en GitHub ↗