Back to 0cron
0cron

De HTML estatico a dashboard SvelteKit en una noche

Como convertimos un sitio de marketing HTML estatico en un dashboard SvelteKit 2 completo con runes Svelte 5, autenticacion y un constructor cron wizard en una sesion.

Thales & Claude | March 30, 2026 4 min 0cron
EN/ FR/ ES
0cronsveltesveltekitdashboardtailwindcssfrontendui

Cuando lanzamos la primera version de 0cron.dev, el "frontend" era un solo archivo HTML estatico. Una pagina de marketing con algunos gradientes bonitos, una tabla de precios, y un boton de llamada a la accion que apuntaba a una API que aun no tenia interfaz. El backend era solido -- 14 endpoints, 8 tablas de base de datos, 2,852 lineas de Rust -- pero los usuarios no tenian forma de interactuar con el mas alla de solicitudes HTTP crudas.

Eso cambio en una sola sesion. El 11 de marzo de 2026, convertimos 0cron-website de HTML estatico en una aplicacion SvelteKit 2 completa con 13 paginas de ruta, un store de auth reactivo, un cliente API, un layout de sidebar oscuro, y un wizard de creacion de tareas con un constructor de expresiones cron estilo cPanel.

Por que SvelteKit

Enrutamiento basado en archivos elimina boilerplate. Cada pagina es un archivo. Cada layout envuelve sus hijos automaticamente.

Las runes de Svelte 5 reemplazan el patron de stores. En lugar de importar writable stores, suscribirte y gestionar limpieza, escribes $state y el compilador maneja la reactividad.

TailwindCSS 4 viene de serie con SvelteKit. Sin configuracion de PostCSS, sin configuracion de purge, sin ajustes de pipeline de compilacion.

La estructura de rutas

src/routes/
  +page.svelte                          -- Landing (carga static/landing.html)
  (auth)/
    login/+page.svelte                  -- Google Sign-In + email/contrasena
  (app)/
    +layout.svelte                      -- Guardia de auth + layout sidebar
    dashboard/+page.svelte              -- Tarjetas de estadisticas, proximas tareas, ejecuciones recientes
    jobs/+page.svelte                   -- Lista de tareas con acciones (trigger/pausar/eliminar)
    jobs/new/+page.svelte               -- Wizard de creacion de tareas (CronBuilder)
    jobs/[id]/+page.svelte              -- Detalle de tarea + historial de ejecucion + estadisticas
    billing/+page.svelte                -- Visualizacion de plan, Stripe Checkout/Portal
    settings/+page.svelte               -- Gestion de claves API + secretos
    account/+page.svelte                -- Perfil

El store de auth: runes Svelte 5 en practica

typescriptclass AuthStore {
    token = $state<string | null>(null);
    user = $state<User | null>(null);

    get isAuthenticated() { return !!this.token; }
    get isAdmin() { return this.user?.is_admin ?? false; }

    login(token: string, user: User) {
        this.token = token;
        this.user = user;
        if (browser) {
            localStorage.setItem('auth_token', token);
            localStorage.setItem('auth_user', JSON.stringify(user));
        }
    }

    logout() {
        this.token = null;
        this.user = null;
        if (browser) {
            localStorage.removeItem('auth_token');
            localStorage.removeItem('auth_user');
        }
    }
}

$state hace que los campos de clase sean reactivos. Cuando this.token cambia, cualquier componente que lea authStore.token o authStore.isAuthenticated se re-renderiza automaticamente.

Los getters se convierten en estado derivado. isAuthenticated e isAdmin son getters JavaScript normales, pero como leen campos $state, Svelte los rastrea como dependencias.

El wizard de creacion de tareas

La pieza central es el CronBuilder -- un constructor de expresiones cron estilo cPanel con 18 presets que cubren la gran mayoria de necesidades de programacion del mundo real:

typescriptconst schedulePresets = [
    { label: 'Every minute', cron: '* * * * *' },
    { label: 'Every 5 minutes', cron: '*/5 * * * *' },
    { label: 'Every day at midnight', cron: '0 0 * * *' },
    { label: 'Every day at 9am', cron: '0 9 * * *' },
    { label: 'Every weekday at 9am', cron: '0 9 * * 1-5' },
    { label: 'First day of month', cron: '0 0 1 * *' },
    // ... 12 more presets
];

Usuarios que nunca han escrito una expresion cron pueden hacer clic en "Every weekday at 9am" y obtener 0 9 <em> </em> 1-5 sin entender el formato de cinco campos.

Lecciones aprendidas

Los grupos de rutas estan infrautilizados en SvelteKit. El patron (auth) / (app) resuelve el problema "algunas paginas necesitan sidebar, otras no" de forma limpia.

Las runes de Svelte 5 hacen que las clases sean viables para gestion de estado. El store de auth se lee como TypeScript normal, pero cada campo $state es rastreado.

Mantener lo que funciona. La pagina de marketing estatica estaba bien. No la reescribimos en Svelte.


Este es el articulo 7 de 10 en la serie "Como construimos 0cron".

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles