Tutorial: Construir una Aplicacion Web

HarbourBuilder incluye un componente TWebServer integrado que le permite servir paginas web y APIs JSON directamente desde su aplicacion. En este tutorial construira una aplicacion web TODO simple con una interfaz de escritorio GUI y una interfaz basada en navegador funcionando lado a lado.

Paso 1: Crear el Proyecto

  1. Cree un nuevo proyecto llamado TodoWebApp mediante Archivo → Nuevo Proyecto.
  2. Abra main.prg en el Editor de Codigo.
  3. Construiremos un formulario de escritorio para gestionar tareas y un servidor web que expone los mismos datos.

Paso 2: Configurar el Servidor Web

Coloque un TWebServer desde la pestania de paleta Internet en el formulario, o creelo en codigo. Establezca el puerto y defina sus rutas.

#include "hbbuilder.ch"

static aTodos := {}  // Lista de tareas compartida

function Main()

   local oForm, oServer, oBrw, oGet, oBtnAdd
   local cTask := ""

   // --- Configuracion del servidor web ---
   DEFINE WEBSERVER oServer PORT 8080

   oServer:Route( "GET",  "/",          { |oReq, oRes| ServeHomePage( oReq, oRes ) } )
   oServer:Route( "GET",  "/api/todos",  { |oReq, oRes| GetTodosJSON( oReq, oRes ) } )
   oServer:Route( "POST", "/api/todos",  { |oReq, oRes| AddTodoJSON( oReq, oRes ) } )
   oServer:Route( "DELETE", "/api/todos/:id", { |oReq, oRes| DeleteTodoJSON( oReq, oRes ) } )

   oServer:Start()

   // --- Interfaz de escritorio ---
   DEFINE FORM oForm TITLE "Aplicacion TODO (Escritorio + Web en puerto 8080)" ;
      SIZE 600, 500 FONT "Segoe UI", 10

   @ 10, 10 BROWSE oBrw ;
      OF oForm SIZE 560, 350 ;
      HEADERS { "#", "Tarea", "Estado" } ;
      WIDTHS  { 40, 350, 100 }

   @ 380, 10 GET oGet VAR cTask OF oForm SIZE 400, 24

   @ 380, 420 BUTTON oBtnAdd PROMPT "Anadir Tarea" ;
      OF oForm SIZE 100, 32 ;
      ACTION ( AAdd( aTodos, { oGet:GetValue(), "pendiente" } ), ;
              RefreshGrid( oBrw ), oGet:SetValue( "" ) )

   RefreshGrid( oBrw )

   oForm:OnClose := { || oServer:Stop(), .T. }

   ACTIVATE FORM oForm CENTERED

return nil
Escritorio + Web en un solo ejecutable

El TWebServer se ejecuta en un hilo en segundo plano, por lo que su formulario de escritorio permanece completamente interactivo. Tanto la GUI como el navegador ven el mismo arreglo aTodos. Los cambios de cualquier lado son inmediatamente visibles para el otro.

Paso 3: Servir una Pagina HTML

La ruta raiz / sirve una pagina HTML completa. Use oRes:SendHTML() para devolver contenido HTML.

static function ServeHomePage( oReq, oRes )

   local cHTML := '<!DOCTYPE html>' + ;
      '<html><head><title>Aplicacion TODO</title>' + ;
      '<style>body{font-family:sans-serif;max-width:600px;margin:2em auto}' + ;
      'input{padding:8px;width:70%} button{padding:8px 16px}' + ;
      'li{padding:4px 0}</style></head><body>' + ;
      '<h1>Lista de Tareas</h1>' + ;
      '<input id="task" placeholder="Nueva tarea...">' + ;
      '<button onclick="addTask()">Anadir</button>' + ;
      '<ul id="list"></ul>' + ;
      '<script>' + ;
      'async function load(){let r=await fetch("/api/todos");' + ;
      'let d=await r.json();let h="";' + ;
      'd.forEach((t,i)=>h+="<li>"+t[0]+" ["+t[1]+"] " + ;
      '+"<a href=# onclick=del("+i+")>x</a></li>");' + ;
      'document.getElementById("list").innerHTML=h}' + ;
      'async function addTask(){let v=document.getElementById("task").value;' + ;
      'await fetch("/api/todos",{method:"POST",' + ;
      'headers:{"Content-Type":"application/json"},' + ;
      'body:JSON.stringify({task:v})});load()}' + ;
      'async function del(i){await fetch("/api/todos/"+i,' + ;
      '{method:"DELETE"});load()}' + ;
      'load();</script></body></html>'

   oRes:SendHTML( cHTML )

return nil

Paso 4: Devolver JSON para la API

Las rutas de API usan oRes:SendJSON() para devolver datos estructurados que el JavaScript del navegador (o cualquier cliente HTTP) puede consumir.

static function GetTodosJSON( oReq, oRes )

   oRes:SendJSON( hb_jsonEncode( aTodos ) )

return nil

static function AddTodoJSON( oReq, oRes )

   local hBody := hb_jsonDecode( oReq:cBody )

   AAdd( aTodos, { hBody[ "task" ], "pendiente" } )
   oRes:SendJSON( '{"status":"ok"}' )

return nil

static function DeleteTodoJSON( oReq, oRes )

   local nId := Val( oReq:Param( "id" ) ) + 1

   if nId >= 1 .and. nId <= Len( aTodos )
      ADel( aTodos, nId )
      ASize( aTodos, Len( aTodos ) - 1 )
   endif

   oRes:SendJSON( '{"status":"ok"}' )

return nil

Paso 5: Actualizar la Cuadricula de Escritorio

static function RefreshGrid( oBrw )

   local aData := {}, n

   for n := 1 to Len( aTodos )
      AAdd( aData, { n, aTodos[ n ][ 1 ], aTodos[ n ][ 2 ] } )
   next

   oBrw:SetArray( aData )
   oBrw:Refresh()

return nil

Paso 6: Compilar y Probar

  1. Presione F9 para compilar y ejecutar.
  2. Aparece el formulario de escritorio con una lista de tareas vacia. Anada algunas tareas usando la GUI.
  3. Abra un navegador y navegue a http://localhost:8080.
  4. Ver las mismas tareas renderizadas como HTML. Anada o elimine tareas desde el navegador.
  5. Vuelva al escritorio — los datos se comparten en tiempo real.

Descripcion General de la Arquitectura

graph TB subgraph "Un Solo Ejecutable HarbourBuilder" A["Interfaz de Escritorio
TForm + TBrowse"] --- C["Datos Compartidos
Arreglo aTodos"] B["TWebServer
Puerto 8080"] --- C end D["Navegador
http://localhost:8080"] -->|"HTTP GET/POST/DELETE"| B A -->|"Acceso directo al arreglo"| C style A fill:#58a6ff,stroke:#388bfd,color:#0d1117 style B fill:#3fb950,stroke:#2ea043,color:#0d1117 style C fill:#d2a8ff,stroke:#bc8cff,color:#0d1117 style D fill:#f0883e,stroke:#d18616,color:#0d1117
Servir archivos estaticos

Para aplicaciones web mas grandes, use oServer:Static( "/assets", "./www" ) para servir archivos CSS, JavaScript e imagenes desde una carpeta local en lugar de incrustar HTML en cadenas.

Siguiente paso

Listo para anadir inteligencia a su aplicacion? Continue al tutorial de Integracion de IA para conectarse a LLMs locales y ejecutar inferencia directamente desde su aplicacion.

En Esta Página

Primeros Pasos Paleta de Componentes Funciones del IDE Tutoriales Referencia Plataformas Paso 1: Crear el Proyecto Paso 2: Configurar el Servidor Web Paso 3: Servir una Pagina HTML Paso 4: Devolver JSON para la API Paso 5: Actualizar la Cuadricula de Escritorio Paso 6: Compilar y Probar Descripcion General de la Arquitectura