Learn more about Svelte

Revolutionize Your Development with Svelte

Svelte is a radical new approach to building user interfaces. Unlike traditional frameworks that do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when you build your app, resulting in highly optimized vanilla JavaScript that updates the DOM directly.

Why Svelte is Changing the Game for Web Development:

  • Write Less Code: Svelte’s elegant, intuitive syntax requires significantly less boilerplate than other frameworks. This means faster development, fewer bugs, and more maintainable codebases that are easier for teams to understand and extend.

  • No Virtual DOM Overhead: By compiling your components to highly optimized vanilla JavaScript that surgically updates the DOM, Svelte eliminates the overhead of runtime libraries and virtual DOM diffing, resulting in exceptional performance even on low-powered devices.

  • Truly Reactive by Design: Svelte’s reactivity is built directly into the language, automatically updating the DOM when your component state changes without requiring explicit state management libraries or hooks. This makes reactive programming intuitive and accessible.

  • Built-in Animation and Transitions: Svelte includes powerful built-in transition and animation systems that make creating smooth, engaging user interfaces straightforward, without requiring additional libraries or complex choreography.

  • SvelteKit for Full-Stack Development: Paired with SvelteKit, Svelte offers a complete solution for building full-stack web applications with features like server-side rendering, API routes, and advanced routing, all with the same elegant developer experience.

Svelte empowers businesses to create faster, more engaging web experiences with less code and complexity. Its compiler-based approach results in smaller bundle sizes and better runtime performance, which directly translates to improved user engagement, higher conversion rates, and better SEO rankings.

Interactive Demos

TodoTools.svelte

<script>
  let todos = [
    { id: 1, text: 'Learn Svelte fundamentals', completed: true },
    { id: 2, text: 'Build a cool demo app', completed: true },
    { id: 3, text: 'Integrate it with Astro', completed: false },
    { id: 4, text: 'Add transitions and animations', completed: false },
  ];
  let newTodoText = '';

  function addTodo() {
    if (newTodoText.trim()) {
      todos = [...todos, { id: Date.now(), text: newTodoText, completed: false }];
      newTodoText = '';
    }
  }

  function removeTodo(id) {
    todos = todos.filter(todo => todo.id !== id);
  }

  function clearCompleted() {
    todos = todos.filter(todo => !todo.completed);
  }

  $: remaining = todos.filter(todo => !todo.completed).length;
</script>

<div class="w-full h-full p-4 font-sans text-base-content">
  <div class="flex justify-between items-center mb-4">
    <h1 class="text-2xl font-bold">Svelte Todos</h1>
    {#if remaining > 0}
      <span class="badge badge-secondary">{remaining} remaining</span>
    {:else}
      <span class="badge badge-success">All done! ✨</span>
    {/if}
  </div>

  <form on:submit|preventDefault={addTodo} class="flex gap-2 mb-4">
    <input
      type="text"
      bind:value={newTodoText}
      placeholder="Add a new task..."
      class="input input-bordered w-full"
    />
    <button type="submit" class="btn btn-primary">Add</button>
  </form>

  <ul class="space-y-2 mb-4 h-48 overflow-y-auto pr-2">
    {#each todos as todo (todo.id)}
      <li class="flex items-center justify-between bg-base-200 p-3 rounded-md transition-colors duration-300 hover:bg-base-300">
        <label class="flex items-center cursor-pointer">
          <input type="checkbox" bind:checked={todo.completed} class="checkbox checkbox-primary mr-4" />
          <span class:line-through={todo.completed} class:opacity-50={todo.completed} class="transition-all">
            {todo.text}
          </span>
        </label>
        <button on:click={() => removeTodo(todo.id)} class="btn btn-ghost btn-xs">🗑️</button>
      </li>
    {/each}
  </ul>

  {#if todos.some(t => t.completed)}
    <div class="text-center border-t border-base-300 pt-4">
      <button on:click={clearCompleted} class="btn btn-sm btn-outline btn-warning">Clear Completed</button>
    </div>
  {/if}
</div>

DevTools.svelte

<script>
  // import { Chart } from 'svelte-echarts'; // Temporarily disabled due to build issues
  import { init, use } from 'echarts/core';
  import { LineChart, BarChart, PieChart } from 'echarts/charts';
  import { TooltipComponent, LegendComponent, GridComponent, TitleComponent } from 'echarts/components';
  import { CanvasRenderer } from 'echarts/renderers';
  import { onMount } from 'svelte';
  import { fade } from 'svelte/transition';

  use([TooltipComponent, LegendComponent, GridComponent, LineChart, BarChart, PieChart, CanvasRenderer, TitleComponent]);

  let mounted = false;

  let projectData = [
    {
      title: "Project Completion Rate",
      options: {
        tooltip: { trigger: 'axis' },
        legend: { data: ['Completion %'], textStyle: { color: '#9ca3af' } },
        xAxis: { type: 'category', data: ['Q1', 'Q2', 'Q3', 'Q4'], axisLabel: { color: '#9ca3af' } },
        yAxis: { type: 'value', axisLabel: { color: '#9ca3af' }, max: 100 },
        series: [{ name: 'Completion %', data: [85, 92, 78, 95], type: 'line', smooth: true }]
      },
      chartType: 'line',
    },
    {
      title: "Lines of Code by Language",
      options: {
        tooltip: { trigger: 'item' },
        legend: { top: '5%', left: 'center', textStyle: { color: '#9ca3af' } },
        series: [
          {
            name: 'Lines of Code',
            type: 'pie',
            radius: ['40%', '70%'],
            avoidLabelOverlap: false,
            itemStyle: { borderRadius: 10, borderColor: 'hsl(var(--b1))', borderWidth: 2 },
            label: { show: false, position: 'center' },
            emphasis: { label: { show: true, fontSize: '20', fontWeight: 'bold' } },
            labelLine: { show: false },
            data: [
              { value: 12000, name: 'TypeScript' },
              { value: 8500, name: 'Svelte' },
              { value: 6000, name: 'Astro' },
              { value: 4500, name: 'CSS' }
            ]
          }
        ]
      }
    },
    {
      title: "Bug Resolution Time (Hours)",
      options: {
        tooltip: { trigger: 'axis' },
        legend: { data: ['Time (h)'], textStyle: { color: '#9ca3af' } },
        xAxis: { type: 'category', data: ['Jan', 'Feb', 'Mar', 'Apr'], axisLabel: { color: '#9ca3af' } },
        yAxis: { type: 'value', axisLabel: { color: '#9ca3af' } },
        series: [{ name: 'Time (h)', data: [12, 8, 15, 7], type: 'bar' }]
      },
      sortOrder: 'asc',
    }
  ];

  function toggleChartType(index) {
    const currentType = projectData[index].chartType;
    projectData[index].chartType = currentType === 'line' ? 'bar' : 'line';
    projectData[index].options.series[0].type = projectData[index].chartType;
    projectData = [...projectData]; // Trigger reactivity
  }

  function sortBugData(index) {
    const currentOrder = projectData[index].sortOrder;
    const newOrder = currentOrder === 'asc' ? 'desc' : 'asc';
    projectData[index].sortOrder = newOrder;

    const seriesData = projectData[index].options.series[0].data;
    const axisData = projectData[index].options.xAxis.data;
    
    const zipped = axisData.map((item, i) => [item, seriesData[i]]);

    zipped.sort((a, b) => newOrder === 'asc' ? a[1] - b[1] : b[1] - a[1]);

    projectData[index].options.xAxis.data = zipped.map(item => item[0]);
    projectData[index].options.series[0].data = zipped.map(item => item[1]);
    projectData = [...projectData]; // Trigger reactivity
  }

  function randomizeData(index) {
    const chart = projectData[index];
    if (chart.options.series[0].type === 'line' || chart.options.series[0].type === 'bar') {
      const newData = chart.options.series[0].data.map(() => Math.round(Math.random() * 100));
      chart.options.series[0].data = newData;
    } else if (chart.options.series[0].type === 'pie') {
      const newData = chart.options.series[0].data.map(item => ({
        ...item,
        value: Math.round(Math.random() * 10000) + 2000
      }));
      chart.options.series[0].data = newData;
    }
    projectData = [...projectData]; // Trigger reactivity
  }

  onMount(() => {
    mounted = true;
  });
</script>

<div class="w-full h-full p-4 bg-base-200 rounded-lg shadow-inner">
  {#if mounted}
    <div in:fade={{ duration: 500 }} class="carousel w-full h-full rounded-box">
      {#each projectData as chart, i}
        <div id={`slide${i + 1}`} class="carousel-item relative w-full flex flex-col p-4">
          <h3 class="text-lg font-semibold text-center mb-2">{chart.title}</h3>
          <div class="flex-grow h-64">
            <Chart {init} options={chart.options} />
          </div>
          <div class="absolute flex justify-between transform -translate-y-1/2 left-5 right-5 top-1/2">
            <a href={`#slide${i === 0 ? projectData.length : i}`} class="btn btn-circle btn-sm">❮</a> 
            <a href={`#slide${i === projectData.length - 1 ? 1 : i + 2}`} class="btn btn-circle btn-sm">❯</a>
          </div>
          <div class="flex justify-center gap-2 pt-4">
            <button class="btn btn-xs btn-outline" on:click={() => randomizeData(i)}>
              Randomize Data
            </button>
            {#if i === 0}
              <button class="btn btn-xs btn-outline" on:click={() => toggleChartType(i)}>
                Switch to {chart.chartType === 'line' ? 'Bar' : 'Line'} Chart
              </button>
            {/if}
            {#if i === 2}
               <button class="btn btn-xs btn-outline" on:click={() => sortBugData(i)}>
                Sort {chart.sortOrder === 'asc' ? 'Descending' : 'Ascending'}
              </button>
            {/if}
          </div>
        </div> 
      {/each}
    </div>
  {/if}
</div>