IntraWeb 17 One
Crea la aplicación.
Olvídate de la fontanería
Crea una sola aplicación. IntraWeb One separa el frontend y el backend por ti y los conecta automáticamente. Sin glue code. Sin capa de API. Sin tareas de integración.





LA CADENA DE HERRAMIENTAS
Basta de fatiga de herramientas
El desarrollo web moderno empieza hoy con árboles de dependencias, pipelines de build y una pequeña montaña de código ajeno. IntraWeb 17 FE elimina el lastre, para que tu proyecto empiece por tu aplicación.
- Totalmente integrado en un entorno profesional: VS Code
- Desarrolla 100 % sin conexión, sin depender de la nube
- Depuración nativa profesional, sin malabares con sourcemaps
- El control de versiones GIT / SVN funciona exactamente como esperas
- No es hosting ni SaaS: eres dueño de cada byte generado
LA CADENA DE HERRAMIENTAS
Basta de fatiga de herramientas
El desarrollo web moderno empieza hoy con árboles de dependencias, pipelines de build y una pequeña montaña de código ajeno. IntraWeb 17 FE elimina el lastre, para que tu proyecto empiece por tu aplicación.
- Totalmente integrado en un entorno profesional: VS Code
- Desarrolla 100 % sin conexión, sin depender de la nube
- Depuración nativa profesional, sin malabares con sourcemaps
- El control de versiones GIT / SVN funciona exactamente como esperas
- No es hosting ni SaaS: eres dueño de cada byte generado
Compruébalo tú mismo
En qué se diferencia de las opciones habituales

namespace GuessTemplate {
export class Index extends IndexGen {
public Count = 0;
// Must init to a value so it has a type and exists.
public Guess = NaN;
public Msg = '';
protected MagicNo = Math.floor((Math.random() * 100)+ 1);
public WhenPageLoaded(): void {
const xMagicNo = this.Page.WebParam('MagicNo');
if (xMagicNo)this.MagicNo = parseInt(xMagicNo);
}
public WhenGuessButtonClicked(e: MouseEvent): void {
if (e && e.shiftKey){
IntraWeb.Dialogs.ShowMessage('The magic number is: ' + this.MagicNo);
return;
}
this.Msg = '';
if (isNaN(this.Guess)) {
// Need to retrieve value from Edit itself when its an invalid number.
this.Msg = this.GuessEdit.Text.Value + ' is not a valid number.';
}else if (this.Guess < 1 || this.Guess > 100) {
this.Msg = this.Guess + ' is not in the range of 1 to 100.';
}else {
this.Count++;
if (this.Guess < this.MagicNo) {
this.Msg = this.Guess + ' is too low.';
}else if (this.Guess > this.MagicNo) {
this.Msg = this.Guess + ' is too high.';
}else if (this.Guess === this.MagicNo) {
IntraWeb.Dialogs.ShowMessage('Congratulations! You guessed the magic number.');
this.GuessButton.Enabled.Value = false;
}
}
this.GuessEdit.Focus();
this.Guess = NaN;
}
}
}import { useState, useRef, useEffect } from 'react'
const logo = '/Logo.png'
function App() {
const [guess, setGuess] = useState('')
const [msg, setMsg] = useState('')
const [count, setCount] = useState(0)
const [disabled, setDisabled] = useState(false)
const magicNo = useRef(Math.floor(Math.random() * 100) + 1)
const inputRef = useRef(null)
useEffect(() => {
const params = new URLSearchParams(window.location.search)
const magic = params.get('MagicNo')
if (magic) magicNo.current = parseInt(magic)
inputRef.current?.focus()
}, [])
function handleGuess(e) {
if (e && e.shiftKey) {
alert('The magic number is: ' + magicNo.current)
return
}
const num = parseInt(guess)
if (isNaN(num)) {
setMsg(guess + ' is not a valid number.')
} else if (num < 1 || num > 100) {
setMsg(num + ' is not in the range of 1 to 100.')
} else {
setCount(c => c + 1)
if (num < magicNo.current) {
setMsg(num + ' is too low.')
} else if (num > magicNo.current) {
setMsg(num + ' is too high.')
} else {
alert('Congratulations! You guessed the magic number.')
setMsg('')
setDisabled(true)
}
}
setGuess('')
inputRef.current?.focus()
}
function handleKeyDown(e) {
if (e.key === 'Enter' && !disabled) {
handleGuess(e)
}
}
return (
<div className="Card">
<div className="Logo">
<img src={logo} alt="Logo" />
</div>
<h1>Guess the Number</h1>
<p>I'm thinking of a number between 1 and 100. Can you guess it?</p>
<div className="Input">
<input
ref={inputRef}
type="number"
placeholder="Enter your guess..."
value={guess}
onChange={e => setGuess(e.target.value)}
onKeyDown={handleKeyDown}
disabled={disabled}
/>
</div>
<div className="Button">
<button onClick={handleGuess} disabled={disabled}>
Guess
</button>
</div>
<div className="Msg">{msg}</div>
{count > 0 && <div className="Counter">Attempts: {count}</div>}
<div className="FrameworkBadge">React</div>
</div>
)
}
export default App
namespace GuessTemplate {
export class Index extends IndexGen {
public Count = 0;
// Must init to a value so it has a type and exists.
public Guess = NaN;
public Msg = '';
protected MagicNo = Math.floor((Math.random() * 100)+ 1);
public WhenPageLoaded(): void {
const xMagicNo = this.Page.WebParam('MagicNo');
if (xMagicNo)this.MagicNo = parseInt(xMagicNo);
}
public WhenGuessButtonClicked(e: MouseEvent): void {
if (e && e.shiftKey){
IntraWeb.Dialogs.ShowMessage('The magic number is: ' + this.MagicNo);
return;
}
this.Msg = '';
if (isNaN(this.Guess)) {
// Need to retrieve value from Edit itself when its an invalid number.
this.Msg = this.GuessEdit.Text.Value + ' is not a valid number.';
}else if (this.Guess < 1 || this.Guess > 100) {
this.Msg = this.Guess + ' is not in the range of 1 to 100.';
}else {
this.Count++;
if (this.Guess < this.MagicNo) {
this.Msg = this.Guess + ' is too low.';
}else if (this.Guess > this.MagicNo) {
this.Msg = this.Guess + ' is too high.';
}else if (this.Guess === this.MagicNo) {
IntraWeb.Dialogs.ShowMessage('Congratulations! You guessed the magic number.');
this.GuessButton.Enabled.Value = false;
}
}
this.GuessEdit.Focus();
this.Guess = NaN;
}
}
}<template>
<div class="Card">
<div class="Logo">
<img src="/Logo.png" alt="Logo" />
</div>
<h1>Guess the Number</h1>
<p>I'm thinking of a number between 1 and 100. Can you guess it?</p>
<div class="Input">
<input
ref="inputRef"
v-model="guess"
type="number"
placeholder="Enter your guess..."
:disabled="disabled"
@keydown.enter="handleGuess"
/>
</div>
<div class="Button">
<button @click="handleGuess" :disabled="disabled">Guess</button>
</div>
<div class="Msg">{{ msg }}</div>
<div v-if="count > 0" class="Counter">Attempts: {{ count }}</div>
<div class="FrameworkBadge">Vue</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const guess = ref('')
const msg = ref('')
const count = ref(0)
const disabled = ref(false)
const inputRef = ref(null)
const params = new URLSearchParams(window.location.search)
const magicNo = params.get('MagicNo')
? parseInt(params.get('MagicNo'))
: Math.floor(Math.random() * 100) + 1
onMounted(() => {
inputRef.value?.focus()
})
function handleGuess(e) {
if (e?.shiftKey) {
alert('The magic number is: ' + magicNo)
return
}
const num = parseInt(guess.value)
if (isNaN(num)) {
msg.value = guess.value + ' is not a valid number.'
} else if (num < 1 || num > 100) {
msg.value = num + ' is not in the range of 1 to 100.'
} else {
count.value++
if (num < magicNo) {
msg.value = num + ' is too low.'
} else if (num > magicNo) {
msg.value = num + ' is too high.'
} else {
alert('Congratulations! You guessed the magic number.')
msg.value = ''
disabled.value = true
}
}
guess.value = ''
inputRef.value?.focus()
}
</script>
namespace GuessTemplate {
export class Index extends IndexGen {
public Count = 0;
// Must init to a value so it has a type and exists.
public Guess = NaN;
public Msg = '';
protected MagicNo = Math.floor((Math.random() * 100)+ 1);
public WhenPageLoaded(): void {
const xMagicNo = this.Page.WebParam('MagicNo');
if (xMagicNo)this.MagicNo = parseInt(xMagicNo);
}
public WhenGuessButtonClicked(e: MouseEvent): void {
if (e && e.shiftKey){
IntraWeb.Dialogs.ShowMessage('The magic number is: ' + this.MagicNo);
return;
}
this.Msg = '';
if (isNaN(this.Guess)) {
// Need to retrieve value from Edit itself when its an invalid number.
this.Msg = this.GuessEdit.Text.Value + ' is not a valid number.';
}else if (this.Guess < 1 || this.Guess > 100) {
this.Msg = this.Guess + ' is not in the range of 1 to 100.';
}else {
this.Count++;
if (this.Guess < this.MagicNo) {
this.Msg = this.Guess + ' is too low.';
}else if (this.Guess > this.MagicNo) {
this.Msg = this.Guess + ' is too high.';
}else if (this.Guess === this.MagicNo) {
IntraWeb.Dialogs.ShowMessage('Congratulations! You guessed the magic number.');
this.GuessButton.Enabled.Value = false;
}
}
this.GuessEdit.Focus();
this.Guess = NaN;
}
}
}// app.html
<div class="Card">
<div class="Logo">
<img src="Logo.png" alt="Logo" />
</div>
<h1>Guess the Number</h1>
<p>I'm thinking of a number between 1 and 100. Can you guess it?</p>
<div class="Input">
<input
#inputRef
[ngModel]="guess()"
(ngModelChange)="guess.set($event)"
type="number"
placeholder="Enter your guess..."
[disabled]="disabled()"
(keydown.enter)="handleGuess($event)"
/>
</div>
<div class="Button">
<button (click)="handleGuess($event)" [disabled]="disabled()">Guess</button>
</div>
<div class="Msg">{{ msg() }}</div>
@if (count() > 0) {
<div class="Counter">Attempts: {{ count() }}</div>
}
<div class="FrameworkBadge">Angular</div>
</div>
// app.ts
import { Component, signal, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-root',
imports: [FormsModule],
templateUrl: './app.html',
styleUrl: './app.scss'
})
export class App implements AfterViewInit {
@ViewChild('inputRef') inputRef!: ElementRef<HTMLInputElement>;
readonly guess = signal('');
readonly msg = signal('');
readonly count = signal(0);
readonly disabled = signal(false);
private readonly magicNo: number;
constructor() {
const params = new URLSearchParams(window.location.search);
const fromQuery = params.get('MagicNo');
this.magicNo = fromQuery
? parseInt(fromQuery, 10)
: Math.floor(Math.random() * 100) + 1;
}
ngAfterViewInit(): void {
this.inputRef.nativeElement.focus();
}
handleGuess(event?: Event): void {
if ((event as KeyboardEvent | MouseEvent | undefined)?.shiftKey) {
alert('The magic number is: ' + this.magicNo);
return;
}
const raw = this.guess();
const num = parseInt(raw, 10);
if (isNaN(num)) {
this.msg.set(raw + ' is not a valid number.');
} else if (num < 1 || num > 100) {
this.msg.set(num + ' is not in the range of 1 to 100.');
} else {
this.count.update(c => c + 1);
if (num < this.magicNo) {
this.msg.set(num + ' is too low.');
} else if (num > this.magicNo) {
this.msg.set(num + ' is too high.');
} else {
alert('Congratulations! You guessed the magic number.');
this.msg.set('');
this.disabled.set(true);
}
}
this.guess.set('');
this.inputRef.nativeElement.focus();
}
}
Bloques
HTML personalizado
para WordPress
Una de las formas más visuales de integrar IntraWeb en un sitio WordPress existente: diseña el bloque en IntraWeb, publica los archivos generados y coloca la app dentro de WordPress con el bloque nativo «HTML personalizado».
Del diseñador de IntraWeb a una página WordPress en vivo
Crea el bloque de forma visual, publica los archivos generados y monta la app IntraWeb en funcionamiento dentro de WordPress con un bloque nativo «HTML personalizado».
Te lo mostramos con el ejemplo de una sección de reservasDiseña y publica el bloque de IntraWeb
Construye la interfaz de forma visual en el diseñador de IntraWeb y publica en el servidor los archivos HTML, CSS, JavaScript y de configuración generados. En este ejemplo, el bloque es un formulario de reserva que puede guardar los datos enviados.
Diseñador de IntraWeb
Archivos del proyecto publicados
Añade el HTML personalizado y conecta la app
En WordPress, añade el bloque HTML personalizado integrado justo donde debe aparecer la aplicación IntraWeb. Después pega un pequeño fragmento que carga la app publicada.
HTML personalizado de WordPress
Conecta el bloque
El formulario de IntraWeb ya funciona dentro de WordPress
El formulario aparece integrado como una sección más de la página de WordPress. WordPress controla el diseño de la página, mientras que IntraWeb mantiene la lógica de la aplicación limpia, separada y bajo el control del desarrollador.
Más de tres décadas de ingeniería web práctica: desde las primeras herramientas comerciales hasta IntraWeb hoy
Atozed Software: El original pionero web
Ya estábamos aquí antes de que
la Web fuera “cool”
En 1994, los navegadores eran primitivos y JavaScript no existía. Mientras el mundo aún peleaba con el acceso por módem, Chad Z. ya distribuía las primeras herramientas comerciales de desarrollo web del mundo. Antes de ASP, antes de PHP y antes de las guerras de frameworks, ya conectábamos la lógica de negocio con internet.
Internet Application
Gateway
Esta captura granulada es un trozo de historia. Muestra el nacimiento de Internet Application Gateway (IAG), el predecesor de IntraWeb. En una época en la que la mayoría de los sistemas dinámicos eran código en bruto que escupía cadenas de HTML, IAG hacía de pasarela entre la lógica de negocio y HTTP.

Más de 30 años de tradición en ingeniería
Desde IAG a mediados de los 90 y Web Solution Builder en 1996 hasta el IntraWeb de hoy, nuestra historia es una línea continua de rigor de ingeniería. No perseguimos modas porque entendemos los fundamentos.
Más de tres décadas de ingeniería web práctica: desde las primeras herramientas comerciales hasta IntraWeb hoy
Atozed Software: El original pionero web
Ya estábamos aquí antes de que la Web fuera “cool”
En 1994, los navegadores eran primitivos y JavaScript no existía. Mientras el mundo aún peleaba con el acceso por módem, Chad Z. ya distribuía las primeras herramientas comerciales de desarrollo web del mundo. Antes de ASP, antes de PHP y antes de las guerras de frameworks, ya conectábamos la lógica de negocio con internet.
Internet Application Gateway
Esta captura granulada es un trozo de historia. Muestra el nacimiento de Internet Application Gateway (IAG), el predecesor de IntraWeb. En una época en la que la mayoría de los sistemas dinámicos eran código en bruto que escupía cadenas de HTML, IAG hacía de pasarela entre la lógica de negocio y HTTP.

Más de 30 años de tradición en ingeniería
Desde IAG a mediados de los 90 y Web Solution Builder en 1996 hasta el IntraWeb de hoy, nuestra historia es una línea continua de rigor de ingeniería.
Sé de los primeros en construir así.
Únete a la beta de IntraWeb 17 FE. Contacto directo con el equipo de ingeniería. Licencia Studio gratuita durante el primer año tras el lanzamiento. Opiniones sinceras, sin NDA.
o simplemente
Únete a nuestro canal de Telegram