Enrutamiento y Cabecera Responsive en SvelteKit: Configuración Inicial para Tu Blog
En esta segunda parte de nuestro tutorial sobre Svelte 5 y SvelteKit, exploraremos cómo funciona el enrutamiento para organizar nuestro blog, configuraremos opciones iniciales clave y crearemos una cabecera responsive
para nuestro blog para que se pueda visualizar correctamente tanto en navegadores de escritorio como en navegadores de smartphone.
Antes de empezar 🛑 y como siempre, si te has perdido alguno de los tutoriales de esta serie, aquí te dejo todos los tutoriales escritos hasta ahora:
- Crea una Web Fullstack con Svelte 5 y SvelteKit
- Enrutamiento y Cabecera Responsive en SvelteKit: Configuración Inicial para Tu Blog 📍
- Siguiente parte en construcción 👷
Configuraciones iniciales
Crear alias
El primer paso que vamos a realizar antes de empezar a desarrollar nuestro proyecto, es añadir unas configuraciones iniciales.
Para ello lo primero que vamos a hacer es crearnos unos alias. De esta manera podremos acceder de forma sencilla a distintos archivos de nuestro proyecto sin tener que escribir rutas inmensas.
Para mejorar la organización de nuestro proyecto, añadiremos alias en el archivo svelte.config.js
. Estos alias nos permitirán importar componentes y assets
de manera más sencilla, utilizando nombres cortos en lugar de rutas largas y relativas.
Abrimos el archivo svelte.config.js
y, dentro del objeto config
, localizamos la clave kit
. Allí añadiremos una nueva clave llamada alias
, en la que definiremos nuestros alias personalizados para los componentes y los assets.
A continuación, el código modificado quedará así:
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter(),
alias: {
"$components": "src/lib/components",
"$assets": "src/lib/assets",
}
}
};
export default config;
$components
: Este alias apunta a la carpeta donde se encontrarán nuestros componentes reutilizables, ubicada en src/lib/components
. Podremos usarlos en el código escribiendo algo como:
import MyComponent from '$components/MyComponent.svelte';
$assets
: Este alias apunta a la carpeta src/lib/assets
, que generalmente contiene recursos estáticos como imágenes, fuentes o estilos. Su uso será similar:
import logo from '$assets/logo.png';
Con esta configuración, reducimos errores, mejoramos la legibilidad del código y hacemos que las rutas sean más manejables, especialmente en proyectos grandes.
Una vez añadidos los alias, necesitaremos lanzar el siguiente comando para que los reconozca:
npm run check
Añadir assets
El siguiente paso que necesitamos hacer es descargar las imágenes que necesitaremos para nuestro proyecto. Las podéis encontrar aquí, en el repositorio del proyecto assets. Cread la carpeta src/lib/assets
y añadir las imágenes manteniendo el mismo nombre para evitar errores.
Archivo de estilos general
Ahora vamos a añadir una hoja de estilos que nos servirán de estilos base para todo el proyecto.
Para ello, dentro de la carpeta src/
creamos un archivo llamado app.css y añadimos el siguiente código:
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
text-decoration: none;
list-style: none;
}
body {
font-family: "Open Sans", sans-serif;
}
Cargar la familia tipográfica
Para añadir la tipografía que utilizaremos en nuestro proyecto, abrimos el archivo src/app.html
y añadimos las siguientes líneas dentro de la etiqueta <head>
:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet"/>
Enrutamiento en Svelte 5 y SvelteKit: Cómo gestionar las páginas de nuestro blog
En SvelteKit, el sistema de enrutamiento se basa en la estructura de carpetas y archivos dentro de la carpeta src/routes
. Cada archivo o carpeta dentro de esta define una ruta en tu aplicación.
- La página de inicio de tu proyecto está representada por el archivo
src/routes/+page.svelte
. Este archivo corresponde a la ruta raíz (/
) de tu aplicación. - Para definir nuevas rutas, simplemente debes crear una carpeta con el nombre de la ruta y dentro de esta un archivo llamado
+page.svelte
. Por ejemplo, si quieres crear una ruta/sobre-mi
, sigue estos pasos:- Crea una carpeta llamada
sobre-mi
dentro desrc/routes
. - Dentro de la carpeta
sobre-mi
, crea un archivo+page.svelte
.
- Crea una carpeta llamada
De esta forma, la estructura sería la siguiente:
src/
└── routes/
├── +page.svelte (Ruta: /)
└── sobre-mi/
└── +page.svelte (Ruta: /sobre-mi)
De momento, nuestro proyecto va a tener las rutas de contacto, login y registro, así que el siguiente paso es añadirlas:
src/
└── routes/
├── +page.svelte (Ruta: /)
└── contacto/
└── +page.svelte (Ruta: /contacto)
└── login/
└── +page.svelte (Ruta: /login)
└── registro/
└── +page.svelte (Ruta: /registro)
Dentro de cada archivo, vamos a añadir un título principal de momento en que añadiremos un texto para diferenciar una de otra. Yo lo he hecho así:
<!-- src/routes/+page.svelte -->
<h1>Inicio</h1>
<!-- src/routes/contacto/+page.svelte -->
<h1>Contacto</h1>
<!-- src/routes/login/+page.svelte -->
<h1>Login</h1>
<!-- src/routes/registro/+page.svelte -->
<h1>Registro</h1>
Cabecera de nuestro blog
La cabecera de nuestro blog será un elemento común a todas las páginas. Para evitar duplicar el código o el componente en cada archivo +page.svelte
, podemos aprovechar el sistema de layouts
de SvelteKit.
En lugar de repetir la cabecera, crearemos un archivo llamado +layout.svelte
dentro de la carpeta src/routes
. Este archivo actuará como un componente envolvente que será compartido por todas las páginas de la misma jerarquía y las que estén anidadas dentro de esa ruta.
Para visualizar su funcionamiento, creamos el archivo src/routes/+layout.svelte
y añadimos el siguiente contenido:
<h1>Cabecera</h1>
Al visualizar nuestra web después de implementar el layout, notarás que actualmente solo se muestra la cabecera en todas las páginas. Esto sucede porque aún no hemos especificado cómo combinar la cabecera con el contenido de cada página.
Para solucionarlo, debemos actualizar el archivo src/routes/+layout.svelte
con el siguiente código:
<script lang="ts">
import '../app.css';
let { children } = $props();
</script>
<h1>Cabecera</h1>
{@render children()}
Explicación del código:
- Uso de TypeScript:
- En la etiqueta
<script lang="ts">
hemos indicado que queremos usar TypeScript para aprovechar sus ventajas, como el tipado estático.
- En la etiqueta
- Importación de estilos globales:
- Importamos el archivo
app.css
que configuramos anteriormente para aplicar los estilos generales de la web.
- Importamos el archivo
- Propiedades del layout:
- Utilizamos
$props()
para obtener las propiedades del layout, de las cuales extraemoschildren
. Esta propiedad representa el contenido del archivo+page.svelte
correspondiente a la ruta actual.
- Utilizamos
- Estructura HTML:
- Añadimos el título de la cabecera con una etiqueta
<h1>
, que se mostrará en todas las páginas. - Para incluir el contenido específico de cada página, usamos la directiva
{@render children()}
. Esto asegura que el contenido de cada+page.svelte
se renderice junto con el layout.
- Añadimos el título de la cabecera con una etiqueta
Ahora, cada página de nuestra aplicación mostrará la cabecera compartida junto con su propio contenido, combinando ambos de manera eficiente y sin necesidad de repetir código.
Creación del primer componente, la cabecera del blog
El siguiente paso será crear nuestro primer componente, que representará la cabecera del blog.
Para organizar el proyecto, comenzaremos creando una carpeta llamada components
dentro de src/lib
. Dentro de esta carpeta, añadiremos otra carpeta llamada layout
, donde guardaremos todos los componentes compartidos entre las diferentes páginas de nuestra aplicación.
A continuación, en la ruta src/lib/components/layout
, crearemos un archivo llamado Header.svelte
. Este archivo será el encargado de contener y definir la estructura de la cabecera del blog.
En Svelte, los archivos .svelte
siguen una estructura ordenada: primero se incluye el código JavaScript o TypeScript dentro de etiquetas <script>
, luego el código HTML y, por último, los estilos CSS dentro de etiquetas <style>
. Este enfoque organiza el contenido y facilita su lectura y mantenimiento.
Para ver su funcionamiento, crearemos el contenido del archivo Header.svelte
. Empezaremos añadiendo el código TypeScript, que será lo primero en el archivo. Abre Header.svelte
y agrega el siguiente código:
<script lang="ts">
import Menu from '$assets/menu.png';
import Logo from '$assets/logo.png';
import HeaderImg from '$assets/header.png';
import { page } from '$app/stores';
</script>
En este bloque de código hacemos lo siguiente:
- Importamos las imágenes que utilizaremos en la cabecera (
Menu
,Logo
yHeaderImg
) desde la carpetaassets
usando el alias que creamos anteriormente. - Importamos
page
desde$app/stores
, que nos permitirá acceder a información sobre la ruta actual.
Justo a continuación, añadimos el código HTML después de la etiqueta de cierre </script>:
<header>
<div class="content-nav">
<div class="menu container">
<a href="/" class="logo">
<img src={Logo} alt="Logo" />
</a>
<input type="checkbox" id="menu" />
<label for="menu">
<img src={Menu} class="menu-icon" alt="Menu responsive" />
</label>
<nav class="navbar">
<ul>
<li class:border-navbar={$page.url.pathname === '/'}><a href="/">Inicio</a></li>
<li class:border-navbar={$page.url.pathname === '/contacto'}>
<a href="/contacto">Contacto</a>
</li>
<li class:border-navbar={$page.url.pathname === '/login'}><a href="/login">Login</a></li>
<li class:border-navbar={$page.url.pathname === '/registro'}><a href="/registro">Registro</a></li>
</ul>
</nav>
</div>
</div>
<div class="content-second-header">
<a href="/">
<img id="image-header" src={HeaderImg} alt="Cabecera cosasdedevs" />
</a>
<h1>Artítulos y tutoriales del mundo tech</h1>
</div>
</header>
En este fragmento de código, podemos ver varias características de Svelte que voy a explicar a continuación.
<img src={Logo} alt="Logo" />
<img src={Menu} class="menu-icon" alt="Menu responsive" />
<img id="image-header" src={HeaderImg} alt="Cabecera cosasdedevs" />
En Svelte, las expresiones entre llaves {}
permiten utilizar valores dinámicos en el HTML. En este código:
{Logo}
, {Menu}
y {HeaderImg}
: Son los recursos que importamos antes y que hacen referencia a las imágenes que necesitamos en nuestro blog.
<nav class="navbar">
<ul>
<li class:border-navbar={$page.url.pathname === '/'}><a href="/">Inicio</a></li>
<li class:border-navbar={$page.url.pathname === '/contacto'}>
<a href="/contacto">Contacto</a>
</li>
<!-- Más rutas -->
</ul>
</nav>
El bloque <nav>
contiene una lista de enlaces que apunta a diferentes páginas del sitio. Para destacar visualmente la ruta en la que nos encontramos, podemos usar la funcionalidad class:
de Svelte. Esta permite añadir dinámicamente una clase CSS según una condición. En este caso, la clase border-navbar
se aplica si una expresión lógica devuelve true
.
La validación se realiza comprobando la ruta actual con $page.url.pathname
. Si la ruta coincide con el valor esperado (por ejemplo, '/'
o '/contacto'
), se añade la clase border-navbar
. De lo contrario, esta no se aplica. Esto permite resaltar automáticamente el enlace correspondiente en la cabecera según la página en la que estemos.
Por ejemplo, cuando estamos en la página de inicio (/
), el enlace "Inicio" tendrá la clase border-navbar
y si estamos en la página de contacto (/contacto
), la clase se aplicará al enlace "Contacto".
Por último, añadimos los estilos a continuación del código HTML:
<style>
.container {
max-width: 1000px;
margin: 0 auto;
}
.content-second-header {
display: flex;
flex-direction: column;
align-items: center;
margin: 3rem 0;
padding: 0 10px;
}
.content-second-header img {
max-width: 100%;
}
.content-second-header h1 {
margin-top: 1rem;
text-align: center;
}
.content-nav {
background-color: black;
min-height: 61px;
}
.menu {
position: absolute;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
font-size: 25px;
color: #f7a800;
text-transform: uppercase;
font-weight: bold;
}
.logo img {
width: 40px;
}
.menu .navbar ul li {
position: relative;
float: left;
transition: 0.3s;
}
.border-navbar {
box-shadow: inset 0px -10px 0px 0px #ffffff; /* Sombra dentro del elemento */
}
.menu .navbar ul li:hover {
background-color: white;
}
.menu .navbar ul li a {
font-size: 18px;
padding: 20px;
color: white;
display: block;
font-weight: bold;
transition: 0.3s;
}
.menu .navbar ul li a:hover {
color: #0f0f0f;
}
#menu {
display: none;
}
.menu-icon {
width: 25px;
}
.menu label {
cursor: pointer;
display: none;
}
@media (max-width: 800px) {
.content-second-header h1 {
font-size: 1.2rem;
}
.content-nav {
min-height: 70px;
}
.menu {
top: 0;
padding: 20px;
}
.menu label {
display: initial;
}
.menu .navbar {
position: absolute;
top: 100%;
left: 0;
right: 0;
background-color: black;
display: none;
}
.menu .navbar ul li {
width: 100%;
}
#menu:checked ~ .navbar {
display: initial;
}
}
</style>
El siguiente paso será mover el archivo src/lib/index.ts
a src/lib/components/index.ts
. De esta manera, lo utilizaremos como un archivo de referencia central para gestionar todos los componentes. Una vez que lo hayamos movido, añadimos el siguiente código:
export {default as Header} from '$components/layout/Header.svelte';
Este cambio organiza mejor nuestros archivos y permite importar los componentes de forma más limpia en otras partes del proyecto, facilitando su gestión y reutilización. Al hacerlo, ahora podemos acceder al componente Header
desde cualquier lugar, utilizando la ruta import { Header } from '$components';
como vamos a ver a continuación.
Por último, vamos a abrir el archivo src\routes\+layout.svelte
y reemplazar el código existente por el siguiente para importar y utilizar nuestro componente Header
:
<script lang="ts">
import { Header } from '$components';
import '../app.css';
let { children } = $props();
</script>
<Header />
{@render children()}
En este código, primero importamos el componente Header
desde $components
y después añadimos nuestro componente como si se tratase de una etiqueta HTML, después añadimos el renderizado de la página en la que nos encontramos.
Si por ejemplo fuera un pie de página, para que se viera correctamente deberíamos ponerlo después de {@render children()}
.
Si todo ha ido bien, deberíais poder visualizar esto:
Y eso es todo por este tutorial. Recordad que cualquier duda podéis escribirla en la caja de comentarios y también os dejo el enlace a la rama que corresponde a este tutorial por si tenéis cualquier problema:
Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.
Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.
Nos leemos 👋.