Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Para crear un sitio con páginas de Inicio, Nosotros, Servicios, Blog y Contacto en Angular, configura varias rutas y muestra cada vista en un <router-outlet>, con una cabecera y un pie compartidos. En un proyecto nuevo, lo más práctico es usar componentes standalone y cargar las páginas de forma diferida. Eso suele producir una aplicación de una sola página (SPA) con varias URL, no un conjunto tradicional de archivos HTML independientes.
Si por «páginas completas» te refieres a secciones que ocupan toda la pantalla, también puedes darles una altura mínima de 100dvh. Este tutorial cubre ambas interpretaciones y explica cuándo elegir renderizado en el navegador, prerenderizado o renderizado en servidor.
Qué vas a construir
El resultado será un sitio organizado con rutas para Inicio, Nosotros, Servicios, Blog, Contacto y una página 404. El menú y el pie de página se mantienen mientras Angular cambia el componente dentro del área principal.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
<header>...</header>
<main>
<router-outlet />
</main>
<footer>...</footer>
En una web multipágina tradicional, cada navegación suele solicitar otro documento HTML al servidor. En la configuración habitual de Angular, el navegador carga la aplicación y el router cambia las vistas. Las URL siguen siendo distintas y pueden compartirse, pero el servidor debe estar preparado para responder correctamente cuando alguien abre o actualiza una ruta directamente.
#1 Best Overall
1. Comprueba los requisitos y crea el proyecto
Necesitas Node.js compatible con la versión de Angular que vayas a usar, npm y Angular CLI. Como las versiones compatibles cambian, consulta la documentación oficial de Angular antes de instalar. Comprueba tus herramientas con:
node --version
npm --version
ng version
Crea y ejecuta el proyecto:
npm install -g @angular/cli
ng new sitio-angular
cd sitio-angular
ng serve --open
El CLI puede presentar preguntas interactivas y sus opciones pueden variar entre versiones. Para empezar directamente con soporte de renderizado en servidor y prerenderizado, Angular permite crear un proyecto con:
ng new sitio-angular --ssr
También es posible añadir SSR a un proyecto existente con ng add @angular/ssr. No es un requisito para configurar rutas; elige esta opción si el sitio necesita HTML generado antes de llegar al navegador. Consulta las guías de prerenderizado y SSR de Angular para el flujo correspondiente a tu versión.
Recommended Free Tools
2. Organiza páginas y elementos compartidos
Para un proyecto pequeño, una estructura como esta separa las vistas de la presentación común y la lógica reutilizable:
src/app/
├── core/ # servicios singleton, guards e interceptores
├── layout/ # cabecera, pie y estructura del sitio
├── pages/ # componentes vinculados a rutas
├── shared/ # piezas reutilizables
├── app.component.ts
├── app.config.ts
└── app.routes.ts
Los proyectos nuevos de Angular suelen usar componentes standalone: cada componente declara directamente las dependencias que utiliza. Los NgModule siguen siendo relevantes en aplicaciones existentes; no hace falta migrar todo un proyecto solo para añadir páginas. Angular ofrece una migración a standalone para quienes decidan hacerlo gradualmente.
Genera las vistas que utilizarás:
ng generate component pages/home
ng generate component pages/about
ng generate component pages/services
ng generate component pages/blog
ng generate component pages/contact
ng generate component pages/not-found
Un componente de página debería tener un título principal, contenido con estructura semántica y, si carga datos, estados claros de carga y error. Por ejemplo:
import { Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-home',
standalone: true,
imports: [RouterLink],
template: `
<section class="hero">
<p>Sitio Angular</p>
<h1>Construye una web clara y mantenible</h1>
<p>Presenta tus servicios, contenido y formas de contacto.</p>
<a routerLink="/contacto">Contactar</a>
</section>
`,
})
export class HomeComponent {}
3. Configura las rutas
En src/app/app.routes.ts, declara una ruta para cada página. loadComponent importa el componente cuando se necesita y permite cargar las páginas standalone de forma diferida:
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: '',
title: 'Inicio | Mi sitio',
loadComponent: () => import('./pages/home/home.component')
.then(m => m.HomeComponent),
},
{
path: 'nosotros',
title: 'Nosotros | Mi sitio',
loadComponent: () => import('./pages/about/about.component')
.then(m => m.AboutComponent),
},
{
path: 'servicios',
title: 'Servicios | Mi sitio',
loadComponent: () => import('./pages/services/services.component')
.then(m => m.ServicesComponent),
},
{
path: 'blog',
title: 'Blog | Mi sitio',
loadComponent: () => import('./pages/blog/blog.component')
.then(m => m.BlogComponent),
},
{
path: 'contacto',
title: 'Contacto | Mi sitio',
loadComponent: () => import('./pages/contact/contact.component')
.then(m => m.ContactComponent),
},
{
path: '**',
loadComponent: () => import('./pages/not-found/not-found.component')
.then(m => m.NotFoundComponent),
},
];
La ruta comodín ** debe ir al final: captura las URL que no coinciden con las anteriores. Registra las rutas en src/app/app.config.ts:
import { ApplicationConfig } from '@angular/core';
import { provideRouter, withInMemoryScrolling } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(
routes,
withInMemoryScrolling({
scrollPositionRestoration: 'enabled',
anchorScrolling: 'enabled',
}),
),
],
};
La ruta de inicio usa una cadena vacía (''); por eso, en una navegación, conviene marcarla como activa solo cuando la coincidencia sea exacta.
4. Añade el layout y la navegación
La plantilla raíz aloja el contenido compartido y el punto donde aparece la página seleccionada:
<!-- app.component.html -->
<a class="skip-link" href="#main-content">Saltar al contenido</a>
<app-header />
<main id="main-content" tabindex="-1">
<router-outlet />
</main>
<app-footer />
La clase del componente raíz debe importar RouterOutlet, además de los componentes de cabecera y pie:
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { HeaderComponent } from './layout/header/header.component';
import { FooterComponent } from './layout/footer/footer.component';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet, HeaderComponent, FooterComponent],
templateUrl: './app.component.html',
})
export class AppComponent {}
En la cabecera usa routerLink para navegación interna, no un href que provoque una navegación de documento. Importa también RouterLinkActive para resaltar la ruta actual:
<header class="site-header">
<a class="logo" routerLink="/">Mi sitio</a>
<nav aria-label="Navegación principal">
<a routerLink="/" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }">Inicio</a>
<a routerLink="/nosotros" routerLinkActive="active">Nosotros</a>
<a routerLink="/servicios" routerLinkActive="active">Servicios</a>
<a routerLink="/blog" routerLinkActive="active">Blog</a>
<a routerLink="/contacto" routerLinkActive="active">Contacto</a>
</nav>
</header>
El componente de cabecera debe importar RouterLink y RouterLinkActive. Usa elementos semánticos, un foco visible y no señales la ruta activa solo con color. Si el menú se convierte en un control móvil desplegable, constrúyelo con un botón de verdad y comprueba navegación por teclado, estado aria-expanded y cierre con Escape cuando corresponda.
5. Aplica una base responsive
Los estilos globales van en src/styles.css; las reglas propias de una vista pueden vivir en los estilos de su componente. Una base sencilla:
Rank #3
- Brand: Wiley
- Set of 2 Volumes
- A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
:root {
--color-text: #172033;
--color-primary: #2563eb;
--content-width: 72rem;
}
* { box-sizing: border-box; }
body {
margin: 0;
color: var(--color-text);
font-family: system-ui, sans-serif;
}
img { display: block; max-width: 100%; height: auto; }
.container {
width: min(calc(100% - 2rem), var(--content-width));
margin-inline: auto;
}
.skip-link {
position: absolute;
transform: translateY(-200%);
}
.skip-link:focus { transform: translateY(0); }
Optimiza imágenes y comprueba el sitio en pantallas estrechas. Para una sección que ocupe al menos la altura visible, puedes usar:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11.full-page {
min-height: 100vh;
min-height: 100dvh;
display: grid;
place-items: center;
}
La segunda declaración aprovecha las unidades dinámicas de viewport, que pueden adaptarse mejor a las barras del navegador móvil; la primera queda como alternativa. Una página de pantalla completa es una decisión de diseño CSS: no es lo mismo que tener múltiples rutas.
6. Valida un formulario de contacto
Los formularios reactivos facilitan declarar reglas de validación y mostrar errores asociados a cada campo:
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
@Component({
selector: 'app-contact',
standalone: true,
imports: [ReactiveFormsModule],
templateUrl: './contact.component.html',
})
export class ContactComponent {
private readonly fb = inject(FormBuilder);
readonly contactForm = this.fb.nonNullable.group({
name: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email]],
message: ['', [Validators.required, Validators.minLength(20)]],
});
submit(): void {
if (this.contactForm.invalid) {
this.contactForm.markAllAsTouched();
return;
}
const value = this.contactForm.getRawValue();
// Envía value a una API o función segura.
}
}
<form [formGroup]="contactForm" (ngSubmit)="submit()">
<label for="name">Nombre</label>
<input id="name" type="text" formControlName="name">
@if (contactForm.controls.name.touched && contactForm.controls.name.invalid) {
<p role="alert">Escribe un nombre de al menos dos caracteres.</p>
}
<label for="email">Correo electrónico</label>
<input id="email" type="email" formControlName="email">
@if (contactForm.controls.email.touched && contactForm.controls.email.invalid) {
<p role="alert">Introduce un correo válido.</p>
}
<label for="message">Mensaje</label>
<textarea id="message" formControlName="message"></textarea>
<button type="submit">Enviar mensaje</button>
</form>
La validación en el navegador mejora la experiencia, pero no sustituye la validación del servidor. Angular tampoco envía el correo por sí solo: necesitas una API, una función serverless o un proveedor de formularios. No incluyas credenciales privadas en el código que se descarga al navegador.
7. Conecta una API si las páginas usan datos dinámicos
Configura HttpClient como proveedor en app.config.ts:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsimport { provideHttpClient } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
],
};
Centraliza las solicitudes en un servicio en lugar de dispersarlas por las plantillas. Gestiona en la interfaz carga, éxito y error; la URL de la API puede diferir entre desarrollo y producción. Todo valor incluido en el bundle del navegador debe considerarse público: guarda claves privadas y tokens administrativos en el servidor. Si utilizas SSR o prerenderizado, revisa además cómo y cuándo se realizan esas solicitudes.
8. Decide cómo se renderiza cada ruta
Las rutas de Angular pueden entregarse de distintas formas. La elección afecta el HTML inicial, el hosting y la actualización del contenido:
Rank #4
| Modelo | Cómo funciona | Puede encajar en |
|---|---|---|
| CSR | El navegador carga JavaScript y Angular renderiza la vista. | Paneles e interfaces autenticadas donde el SEO no sea prioritario. |
| SSR | El servidor genera HTML para cada solicitud. | Páginas que dependen del usuario, la solicitud o datos dinámicos. |
| SSG o prerenderizado | Angular genera archivos HTML durante la compilación. | Sitios corporativos, documentación y contenido relativamente estable. |
| Híbrido | Se elige una estrategia por ruta. | Sitios donde algunas páginas son estáticas y otras dinámicas. |
CSR es el comportamiento habitual si no se configura renderizado adicional. Prerenderizar puede simplificar la entrega de páginas estables mediante hosting estático; SSR puede servir cuando cada respuesta debe depender de la solicitud. Ninguna estrategia garantiza por sí sola buen rendimiento o SEO: también importan el contenido, la caché, el JavaScript, los metadatos y la configuración del servidor. Angular describe estas opciones en sus guías de estrategias de renderizado y prerenderizado.
Para un sitio estático, Angular documenta outputMode: "static": produce archivos prerenderizados y no requiere un servidor Node para servir la aplicación. Eso no elimina la posible necesidad de servicios externos para formularios, APIs o analítica. SSR, en cambio, requiere que el entorno de despliegue pueda ejecutar el servidor o runtime correspondiente.
Rutas de blog con parámetros
Una entrada de blog puede tener una URL como /blog/mi-primer-articulo. Declara una ruta con parámetro:
{
path: 'blog/:slug',
loadComponent: () => import('./pages/blog-post/blog-post.component')
.then(m => m.BlogPostComponent),
}
El componente debe leer slug y cargar la entrada correspondiente. Para prerenderizar estas páginas, los slugs deben conocerse al compilar; si el contenido se crea continuamente o depende de datos por solicitud, evalúa SSR o una estrategia adecuada a tu fuente de contenido. Un blog que deban actualizar personas no técnicas también puede necesitar un CMS: Angular no incluye por sí mismo un panel editorial ni una base de datos.
9. Define títulos y metadatos
El campo title de cada ruta ofrece títulos distintos en el navegador. Para una descripción y metadatos adicionales, usa Meta y Title:
import { Component, inject } from '@angular/core';
import { Meta, Title } from '@angular/platform-browser';
@Component({
selector: 'app-about',
standalone: true,
template: '<h1>Nosotros</h1>',
})
export class AboutComponent {
private readonly title = inject(Title);
private readonly meta = inject(Meta);
constructor() {
this.title.setTitle('Nosotros | Mi sitio');
this.meta.updateTag({
name: 'description',
content: 'Conoce la historia y el equipo de Mi sitio.',
});
this.meta.updateTag({
property: 'og:title',
content: 'Nosotros | Mi sitio',
});
}
}
El SEO no se resuelve con una etiqueta aislada. Revisa que cada página tenga un título y una descripción apropiados, un encabezado principal claro, contenido útil, enlaces internos, URLs estables e imágenes con texto alternativo. Para un sitio público considera también las URL canónicas, un sitemap y robots.txt. Si necesitas que motores y otros clientes reciban HTML inicial con contenido, verifica el resultado servido con la estrategia CSR, SSR o prerenderizado que hayas elegido; tener rutas no garantiza por sí solo que el HTML inicial sea suficiente.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →10. Compila y prepara el despliegue
Genera la compilación de producción con:
ng build
Angular CLI compila y optimiza la aplicación según el target y builder configurados. La ubicación exacta de salida depende del proyecto, la versión y si compilas una aplicación solo de navegador o una configuración SSR/prerenderizada. Usa la ruta que informa el CLI, en lugar de asumir que siempre será una carpeta concreta. Para revisar una salida estática en local puedes servir la carpeta generada con una herramienta de servidor estático, por ejemplo:
Best Value
npx serve dist/sitio-angular/browser
Ajusta esa ruta al directorio real de tu build. Un hosting de SPA debe devolver el documento de entrada para rutas que el router resuelve en el navegador. Si publicas HTML prerenderizado, configura el hosting para servir esos archivos generados. Si usas SSR, despliega también el servidor Angular en una plataforma que pueda ejecutarlo.
Por qué actualizar una ruta puede devolver 404
La navegación desde la página de inicio puede funcionar porque Angular ya está cargado. Pero al refrescar /nosotros, el navegador solicita esa URL al servidor. Si este no encuentra un archivo ni tiene una regla adecuada, responde 404 antes de que Angular pueda intervenir.
- SPA con CSR: configura un fallback del hosting a
index.html. - Prerenderizado: publica los HTML generados y configura el proveedor para servir las rutas correspondientes.
- SSR: asegúrate de que el servidor de la aplicación recibe esas solicitudes.
Un fallback a index.html soluciona la navegación de una SPA, pero no genera un HTML prerenderizado independiente para cada URL. Prueba escribiendo directamente en el navegador cada ruta pública y luego actualizándola.
Publicar en una subcarpeta
Si el sitio se sirve bajo una ruta como /mi-sitio/, el base-href debe reflejarlo al compilar:
ng build --base-href /mi-sitio/
Después comprueba que funcionan enlaces, imágenes, favicon y estilos; revisa también URL canónicas y reglas del servidor. No añadas opciones de rutas de recursos sin una necesidad concreta.
11. Errores habituales y cómo encontrarlos
- El menú cambia la URL, pero no aparece el componente: comprueba que existe
<router-outlet>, que las rutas están registradas y que el nombre exportado coincide con el usado enloadComponent. routerLinkorouter-outletaparece como desconocido: en componentes standalone, importa la directiva o componente de@angular/routerque la plantilla utiliza.- Siempre se muestra la página 404: revisa la ruta solicitada y confirma que el comodín
**está después de las rutas concretas. - Una ruta falla al actualizar o abrirse directamente: configura fallback SPA, entrega de archivos prerenderizados o SSR, según corresponda.
- Una página prerenderizada aparece sin datos: la API quizá no esté disponible durante el build, la ruta dinámica quizá no tenga parámetros conocidos o el código puede depender de
window,documento almacenamiento del navegador. El código que se ejecuta en servidor o durante prerenderizado no debe presuponer APIs exclusivas del navegador. - Los recursos fallan en producción: comprueba la URL base, las rutas de assets y el destino de compilación, especialmente si publicas en una subcarpeta.
- Se filtra una clave: cualquier valor enviado al navegador es visible; mueve secretos a un backend o función segura.
¿Cuándo conviene usar Angular?
Angular encaja cuando el sitio necesita muchas vistas reutilizables, formularios complejos, datos dinámicos, autenticación o convenciones consistentes para un equipo. Puede ser más complejidad de la necesaria para una landing estática o una web editorial pequeña: HTML tradicional o un generador estático puede entregar una solución más sencilla y con menos JavaScript. Si el contenido lo mantiene un equipo no técnico, contempla además un CMS; el framework no proporciona por sí solo herramientas editoriales.
Empieza con rutas standalone y layout compartido; luego elige el renderizado por los requisitos reales de cada página. Para contenido estable y hosting estático, evalúa prerenderizado. Para datos personalizados por solicitud, considera SSR. Para una interfaz privada donde la indexación no importa, CSR puede bastar. Angular permite combinar estrategias, pero esa flexibilidad añade decisiones de compilación y despliegue que conviene asumir solo cuando resuelven una necesidad concreta.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

