Javascript

Building Mobile Applications with Svelte and NativeScript

Ignacio Falk
5 min read
Building Mobile Applications with Svelte and NativeScript
This article was written over 18 months ago and may contain information that is out of date. Some content may still be relevant, but please refer to official documentation for the latest information.

Have you ever wanted to build a mobile application using a language you already know?

In this tutorial, we'll learn how to start building a mobile application using Svelte and NativeScript.

What is NativeScript

NativeScript is a framework that will allow you to write Native apps using JavaScript or Typescript and, at the same time, it allows you to access platform-specific Native APIs.

Setting up your environment

The very first step to developing with NativeScript is installing all the required dependencies. If you're lucky, you'll already have everything installed. But if not, we'll see how to get it to work.

The first thing (assuming you already have Node installed) is to install NativeScript globally.

npm i -g nativescript

For this tutorial, I'll be developing an iOS application.

The best way to check if your environment is prepared is to use the command provided by NativeScript.

ns doctor ios

There's an equivalent command for android if that's your target OS.

If you are missing anything, you'll get a bunch of messages with the requirements needed.

In my case, I had to install XCode, Ruby, Some Gems, and Python libraries. Please refer to the setup guide to check what you need (macOS + iOS, for me).

It's important to have your environment ready. Otherwise, we will not be able to run our project.

✔ Getting environment information

No issues were detected.
✔ Xcode is installed and is configured properly.
✔ xcodeproj is installed and is configured properly.
✔ CocoaPods are installed.
✔ CocoaPods update is not required.
✔ CocoaPods are configured properly.
✔ Your current CocoaPods version is newer than 1.0.0.
✔ Python installed and configured correctly.
✔ The Python 'six' package is found.
✔ Xcode version 13.4.1 satisfies minimum required version 10.
✔ Getting NativeScript components versions information...
✔ Component nativescript has 8.3.2 version and is up to date.
✔ Component @nativescript/core has 8.3.2 version and is up to date.
✔ Component @nativescript/ios has 8.3.2 version and is up to date.

Starting a new project

Now that our environment is set up, let's start a new project. We are going to base this example app on this sample from the NativeScript samples page. However, we will add more to it, like including HTTP requests, and a List/Detail navigation.

ns create sveltapp --svelte
✔ Do you want to help us improve NativeScript by automatically sending anonymous usage statistics? We will not use this information to identify or contact you. … no

The command will create a Svelte + NativeScript project, and install the required dependencies.

Our folder structure will look like this:

Folder Structure

We'll be focusing on the /app folder where our JS/TS will be added.

<!-- components/Home.svelte -->
<page>
    <actionBar title="Home" />
    <gridLayout>
        <label class="info">
            <formattedString>
                <span class="fas" text="&#xf135;" />
                <span text=" {message}" />
            </formattedString>
        </label>
    </gridLayout>
</page>

<script lang="ts">
    let message: string = "Blank Svelte Native App"
</script>

<style>
    .info .fas {
        color: #3A53FF;
    }

    .info {
        font-size: 20;
        horizontal-align: center;
        vertical-align: center;
    }
</style>
<!-- App.svelte -->
<frame>
    <Home />
</frame>

<script lang="ts">
    import Home from './components/Home.svelte'
</script>

App.svelte will render the default page Home which contains a message and an icon.

You'll notice that these are not the HTML tags you're used to, and that's because these are not HTML elements. These are native elements/views. So if you were thinking of reusing your code in a web app, for example, this is not the part that you'll be able to share.

If that's what you need, make sure you extract the pieces that can be reused.

Building Our Application

Let's delete the content from Home.svelte, and let's talk about what we'll be building.

The app we will build will display a list of items, and when clicked, will navigate into a detailed view. The date for this example will be fetched from the PokeAPI.

Creating a List view

Let´s create our Home page a.k.a the list.

But first, let's create some types to be used in our list.

export type PokemonListApiResponse = {
    count: number,
    next: string | null,
    previous: string | null
    results: Array<{
        name: string,
        url: string
    }>
}

export type PokemonListItem = {
    name: string,
    image: string
}

First, we created a type for the rest API response. It will contain a list of Pokémon with a few properties. We also create a type for the model used in our view.

<script lang="ts">
 import { Template } from "svelte-native/components";
 import { PokemonListItem } from "~/types/pokemon";

 let data: PokemonListItem[] = [];

</script>

<page>
 <actionBar title="pokeAPI" />
 <stackLayout height="100%">
   <listView height="100%" items={data}>
     <Template let:item>
       <gridLayout rows="*" columns="auto, *" margin="5 10" padding="0">
         <image row="0" col="0" src={item.image} class="thumb" />
         <label row="0" col="1" text={item.name} />
       </gridLayout>
     </Template>
   </listView>
 </stackLayout>
</page>

Our page consists of a set of layouts and a list view.

Each list item will display an image and a label.

However, our view is missing data.

App shell

Integrating with PokeAPI

Let's create a service that will fetch a list of Pokémon.

// services/api.ts
import { Http } from "@nativescript/core";
import { PokemonListApiResponse, PokemonListItem } from "~/types/pokemon";

export const catchemAll = (limit = 100, offest = 0) =>
  Http.getJSON<PokemonListApiResponse>(
    `https://pokeapi.co/api/v2/pokemon?limit=100&offset=0`
  ).then(
    (res) => {
      return res.results.map((pokemon) => {
        let splitUrl = pokemon.url.split("/");
        let id = splitUrl[splitUrl.length - 2];

        return {
          ...pokemon,
          image: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png`,
        } as PokemonListItem;
      });
    }
  );

To make a request I'll use the Http API provided by NativeScript. It contains a set of methods that I recommend you to check out before deciding which one will suit better for your use case.

I'm making a little transformation to the received data, to build the URL with the sprite of each item.

Once our service is in place, we'll fetch data and display it.

By default, we will fetch 100 items starting from the first one.

I'll make a request once the item is mounted, which means I'll first render the action bar only, and when the response is received, the list will be rendered.

<script lang="ts">
  import { Template } from "svelte-native/components";
  import { onMount } from "svelte";
  import * as api from "../services/api";
  import { PokemonListItem } from "~/types/pokemon";

  let data: PokemonListItem[] = [];

  onMount(() => {
    api.catchemAll().then((items) => (data = items));
  });

</script>

<page>
  <actionBar title="pokeAPI" />
  <stackLayout height="100%">
    <listView height="100%" items={data} on:itemTap={handleTap}>
      <Template let:item>
        <gridLayout rows="*" columns="auto, *" margin="5 10" padding="0">
          <image row="0" col="0" src={item.image} class="thumb" />
          <label row="0" col="1" text={item.name} />
        </gridLayout>
      </Template>
    </listView>
  </stackLayout>
</page>

Our app should look this by now Scrolling

Much better!

Adding the Details view

For our sample application to be complete, we want to be able to navigate to a more detailed page of a Pokémon when one list item is selected.

First, we need to create our destination component: a detailed view of a Pokémon.

We will be adding fetching a description for the Pokémon, but there's a lot of information you can get from the API.

Let's add this call to the API service, and create our detailed view.

// services/api.ts
// ... other methods
export const getDescription = (id: number) => Http.getJSON(`https://pokeapi.co/api/v2/characteristic/${id}`).then(
  (result: any) => {
    let desc = result.descriptions.find(
      (description: any) => description?.language?.name == "en"
    );
    return desc?.description
  },
);
<!-- components/Details.svelte -->
<script lang="ts">
  import { onMount } from "svelte";
  import * as api from "../services/api";

  export let index: number;
  export let item: any;
  let description = "";

  onMount(() => {
    api.getDescription(index + 1).then(
      (res) => {
        description = res || "No description";
      },
      (e) => {
        description = "Error fetching data";
      }
    );
  });
</script>

<page>
  <actionBar title={item.name} class="action-bar" />
  <scrollView>
    <stackLayout>
      <image margin="0" height="250" stretch="aspectFit" src={item.image} />
      <stackLayout padding="10 20">
        <stackLayout>
          <label
            marginTop="15"
            fontSize="16"
            fontWeight="700"
            class="text-primary"
            textWrap="true"
            text="Description"
          />
          <label
            fontSize="14"
            class="text-secondary"
            textWrap="true"
            text={description || "Loading..."}
          />
        </stackLayout>
      </stackLayout>
    </stackLayout>
  </scrollView>
</page>

We will be using a set of stackLayout to build our view, display the image, add the name to the action bar, and finally show a loading message while getting the description, and an error if it fails.

Notice there are two properties exported. This means that these properties must be passed as inputs from a parent.

Bringing all together

It's time to connect the list view, and the details view.

Let's see the final Home Page:

<script lang="ts">
  import { navigate } from "svelte-native";
  import { Template } from "svelte-native/components";
  import { ItemEventData } from "@nativescript/core";
  import { onMount } from "svelte";
  import Details from "./Details.svelte";
  import * as api from "../services/api";
  import { PokemonListItem } from "~/types/pokemon";

  let data: PokemonListItem[] = [];

  onMount(() => {
    api.catchemAll().then((items) => (data = items));
  });

  function handleTap(event: ItemEventData) {
    navigate({
      page: Details,
      props: { index: event.index, item: data[event.index] },
    });
  }
</script>

<page>
  <actionBar title="pokeAPI" />
  <stackLayout height="100%">
    <listView height="100%" items={data} on:itemTap={handleTap}>
      <Template let:item>
        <gridLayout rows="*" columns="auto, *" margin="5 10" padding="0">
          <image row="0" col="0" src={item.image} class="thumb" />
          <label row="0" col="1" text={item.name} />
        </gridLayout>
      </Template>
    </listView>
  </stackLayout>
</page>

We have now included an event listener (on:itemTap), that will then call the navigate method included in svelte-native. Here, we passed the required props item and index to the Details Component.

Now we have connected both views.

We don't have to think about a back button in our details view because it's automatically there when you navigate, and add a view to the navigation stack.

The final result:

App with list and detail navigation

Success.

Publishing your app

If you want to publish the application start by running ns prepare ios --release Open the project in XCode and follow the instructions on how to publish an iOS app.

Final words

Being able to work on a native application using a language and a framework you're comfortable with can be a benefit. But there's a cost to it. Setting up the environment is not as straightforward as it could be, but thankfully, the CLI makes it a lot easier to diagnose what's required.

There's a lot more to explore in NativeScript like using plugins, but it's out of scope for this post, where we explore the usage of Svelte with NativeScript. You can check the code from this tutorial in this repo.

About the author

Ignacio Falk

Ignacio Falk

Senior Software Engineer

I love to learn new things and share what I know. Mentor, Writer, Speaker Member of the local community

Keep reading

View all posts →

Svelte 5 is Here!

Svelte 5 was finally released after a long time in development. Fortunately, we've been able to test it for some time, and now it has a stable release....

Ignacio Falk5 mins
Svelte

A Deep Dive into SvelteKit's Rendering Techniques

SvelteKit is a meta-framework for Svelte that allows you to develop pages based on their content. At its core, SvelteKit introduces three fundamental strategies out of the box, each designed to streamline the development process and ...

Jesús Padrón7 mins
SvelteSEOJavaScriptWeb Performance

Harnessing the Power of Threlte - Building Reactive Three.js Scenes in Svelte

Introduction Web development has evolved to include immersive 3D experiences through libraries like Three.js. This powerful JavaScript library enables the creation of captivating 3D scenes within browsers. Three.js: The 3D Powerhouse Three.js democratizes 3D rendering, allowing developers of all skill levels to craft interactive 3D worlds. Svelte Ecosystem: Svelte Cubed and Svelthree The Svelte ecosystem presents solutions like Svelte Cubed and Svelthree, which bridges Svelte with Three.js, offering streamlined reactivity for 3D web experiences. Introducing Threlte v6: Uniting SvelteKit 1.0, Svelte 4, and TypeScript Threlte v6 is a rendering and component library for Svelte that seamlessly integrates Three.js. By harnessing TypeScript's types, it provides a robust and delightful coding experience. In this tutorial, we'll showcase Threlte's capabilities by building an engaging website header: an auto rotating sphere that changes color on mouse down. Using Threlte v6, SvelteKit 1.0, and Three.js, we're set to create a visually stunning experience. Let's dive in! Setting up Threlte Before building our scene, we need to set up Threlte. We can scaffold a new project using the CLI or manually install Threlte in an existing project. Option 1: Scaffold a New Threlte Project Create a new SvelteKit project and install Threlte with: Option 2: Manual Installation For an existing project, select the necessary Threlte packages and install: Configuration adjustments for SvelteKit can be made in the "vite.config.js" file: With Threlte configured, we're ready to build our interactive sphere. In the next chapter, we'll lay the groundwork for our exciting 3D web experience! Exploring the Boilerplate of Threlte Upon scaffolding a new project using npm create threlte, a few essential boilerplate files are generated. In this chapter, we'll examine the code snippets from three of these files: lib/components/scene.svelte, routes/+page.svelte, and lib/components/app.svelte. 1. lib/components/scene.svelte: This file lays the foundation for our 3D scene. Here's a brief breakdown of its main elements: Perspective Camera : Sets up the camera view with a specific field of view and position, and integrates OrbitControls for auto rotation and zoom management. Directional and Ambient Lights : Defines the lighting conditions to illuminate the scene. Grid : A grid structure to represent the ground. ContactShadows : Adds shadow effects to enhance realism. Float : Wraps around 3D mesh objects and defines floating properties, including intensity and range. Various geometrical shapes like BoxGeometry, TorusKnotGeometry, and IcosahedronGeometry are included here. 2. routes/+page.svelte: This file handles the ui of the index page and imports all necessary components we need to bring our vibrant design to life. 3. lib/components/app.svelte: This file is where you would typically define the main application layout, including styling and embedding other components. Heading to the Fun Stuff With the boilerplate components explained, we're now ready to dive into the exciting part of building our interactive 3D web experience. In the next section, we'll begin crafting our auto rotating sphere, and explore how Threlte's robust features will help us bring it to life. Creating a Rotating Sphere Scene In this chapter, we'll walk you through creating an interactive 3D sphere scene using Threlte. We'll cover setting up the scene, the sphere, the camera and lights, and finally the interactivity that includes a scaling effect and color changes. 1. Setting Up the Scene First, we need to import the required components and utilities from Threlte. 2. Setting Up the Sphere We'll create the 3D sphere using Threlte's and components. 1. : This is a component from Threlte that represents a 3D object, which in this case is a sphere. It's the container that holds the geometry and material of the sphere. 2. : This is the geometry of the sphere. It defines the shape and characteristics of the sphere. The args attribute specifies the parameters for the sphere's creation: The first argument (1) is the radius of the sphere. The second argument (32) represents the number of width segments. The third argument (32) represents the number of height segments. 3. : This is the material applied to the sphere. It determines how the surface of the sphere interacts with light. The color attribute specifies the color of the material. In this case, the color is dynamic and defined by the sphereColor variable, which updates based on user interaction. The roughness attribute controls the surface roughness of the sphere, affecting how it reflects light. 3. Setting Up the Camera and Lights Next, we'll position the camera and add lights to create a visually appealing scene. 1. : This component represents the camera in the scene. It provides the viewpoint through which the user sees the 3D objects. The position attribute defines the camera's position in 3D space. In this case, the camera is positioned at ( 10, 20, 10). The fov attribute specifies the field of view, which affects how wide the camera's view is. makeDefault: This attribute makes this camera the default camera for rendering the scene. 2. : This component provides controls for easy navigation and interaction with the scene. It allows the user to pan, zoom, and orbit around the objects in the scene. The attributes within the component configure its behavior: enableZoom: Disables zooming using the mouse scroll wheel. enablePan: Disables panning the scene. enableDamping: Enables a damping effect that smoothens the camera's movement. autoRotate: Enables automatic rotation of the camera around the scene. autoRotateSpeed: Defines the speed of the auto rotation. 3. : This component represents a directional light source in the scene. It simulates light coming from a specific direction. The attributes within the component configure the light's behavior: intensity: Specifies the intensity of the light. position.x and position.y: Define the position of the light source in the scene. 4. : This component represents an ambient light source in the scene. It provides even lighting across all objects in the scene. The intensity attribute controls the strength of the ambient light. 4. Interactivity: Scaling and Color Changes Now we'll add interactivity to the sphere, allowing it to scale and change color in response to user input. First, we'll import the required utilities for animation and set up a spring object to manage the scale. We'll update the sphere definition to include scaling: Lastly, we'll add code to update the color of the sphere based on the mouse's position within the window. We have successfully created a rotating sphere scene with scaling and color changing interactivity. By leveraging Threlte's capabilities, we have built a visually engaging 3D experience that responds to user input, providing a dynamic and immersive interface. Adding Navigation and Scroll Prompt in app.svelte In this chapter, we'll add a navigation bar and a scroll prompt to our scene. The navigation bar provides links for user navigation, while the scroll prompt encourages the user to interact with the content. Here's a step by step breakdown of the code: 1. Importing the Canvas and Scene The Canvas component from Threlte serves as the container for our 3D scene. We import our custom Scene component to render within the canvas. 2. Embedding the 3D Scene The Canvas component wraps the Scene component to render the 3D content. It is positioned absolutely to cover the full viewport, and the z index property ensures that it's layered behind the navigation elements. 3. Adding the Navigation Bar We use a element to create a horizontal navigation bar at the top of the page. It contains a home link and two navigation list items. The styling properties ensure that the navigation bar is visually appealing and positioned correctly. 4. Adding the Scroll Prompt We include a "Give a scroll" prompt with an element to encourage user interaction. It's positioned near the bottom of the viewport and styled for readability against the background. 5. Styling the Components Finally, the provided CSS styles control the positioning and appearance of the canvas, navigation bar, and scroll prompt. The CSS classes apply appropriate color, font, and layout properties to create a cohesive and attractive design. Head to the github repo to view the full code. Check out the result: https://threlte6 spinning ball.vercel.app/ Conclusion We've successfully added navigation and a scroll prompt to our Threlte project in the app.svelte file. By layering 2D HTML content with a 3D scene, we've created an interactive user interface that combines traditional web design elements with immersive 3D visuals....

Ian Sam Mungai6 mins
Svelte

Svelte 4: Unveiled Speed Enhancements and Developer-Centric Features

Svelte 4: Unveiled Speed Enhancements and Developer Centric Features Svelte, a widely favored framework for building user interfaces, unveiled its much anticipated version 4 on June 22. This major release, while paving the way for future advancements, brings a plethora of remarkable enhancements. Focusing on enriching the development experience and boosting performance, Svelte 4 is indeed reshaping the landscape of frontend development. In this post, we'll delve into the specifics of this exciting release, covering the significant performance boosts, enriched developer tools and features, revamped websites, and simplified migration guide. A Deeper Look at Performance Enhancements Svelte 4 delivers remarkable improvements in performance, focusing on shrinking the Svelte package size, and enhancing hydration efficiency. Streamlined Svelte Package Svelte 4 has substantially slimmed down, reducing its overall package size from 10.6 MB to a sleek 2.8 MB a 75% decrease. This reduction in dependencies from 61 to 16 not only lightens Svelte but also optimizes SvelteKit, significantly accelerating the REPL experience and npm install times. For instance, npm install times have been trimmed from over 5 minutes to less than a minute, a leap in quality that any developer will appreciate. NPM I Before: NPM I After: Bundle Size Before: Bundle Size After: Optimized Hydration and Performance Scores Alongside the impressive package size reduction, Svelte 4 offers more efficient code hydration, reducing the generated code size for the SvelteKit website by nearly 13%. This leaner codebase contributes to higher performance on benchmarks like Google Lighthouse. The performance score for the new Svelte 4 starter on starter.dev has soared from 75% to a near perfect 95+%. Overall, the performance enhancements introduced with Svelte 4 mean a faster, more efficient, and smoother developer experience. Before: After: Enhanced Developer Experience in Svelte 4 Localized Transitions Transitions in Svelte 4 are local by default, preventing potential conflicts during page loading. Improved Web Component Authoring Web Components authoring is simplified with the dedicated customElement attribute in svelte:options. Stricter Type Enforcement Svelte 4 introduces stricter types for createEventDispatcher, Action, ActionReturn, and onMount. These changes collectively offer a streamlined, robust, and efficient coding experience. Revamped Svelte Websites With Svelte 4, the team has also revamped its main website, offering an improved and more user friendly experience. The Tutorial Website The Svelte tutorial website has been overhauled for an enhanced learning journey. New improvements include a visible file structure, fewer elements in the navbar, smoother navigation between sections, and a new dark mode. The Svelte Website The primary Svelte website received a makeover too, including better mobile navigation, improved TypeScript documentation, and a handy dark mode. These website updates aim to provide a more engaging, intuitive, and user friendly experience for all Svelte users. A Smooth Migration to Svelte 4 Transitioning from Svelte 3 to Svelte 4 is designed to be as straightforward as possible. The Svelte team has provided an updated migration tool to simplify this process. Here is a step by step guide for the transition: 1. Run the Svelte migration tool. 2. Remove Svelte 3 packages. 3. Update your eslintrc.json configuration file. 4. Upgrade Storybook related packages to the latest v7. Note: as of the publishing of this article, the latest version is 7.0.26. Do note that the minimum version requirements have changed. You will now need: NodeJS 16 or higher SvelteKit 1.20.4 or higher TypeScript 5 or higher For more detailed instructions and information, please refer to the official Svelte 4 migration guide or you can take a look at our Svelte 4 starter kit on starter.dev. The focus is to ensure a hassle free transition, allowing developers to take advantage of the new features and enhancements Svelte 4 offers without significant obstacles. Conclusion Svelte 4, with its performance enhancements and streamlined development process, offers a new pinnacle in the realm of JavaScript frameworks. If you're keen on shifting from Svelte 3 to Svelte 4, a comprehensive migration guide is provided to facilitate a smooth transition. For a quick start with Svelte 4, check out our ready to use Svelte Kit with SCSS Starter Kit. In addition, we've developed two showcases demonstrating Svelte 4's power: 1. Svelte Kit with SCSS & 7GUIs A comprehensive demo showcasing various UI challenges. 2. GitHub Replica Showcase A clone of the popular code hosting platform, GitHub, demonstrating the potential of Svelte 4 in building complex and high performance web applications. In conclusion, Svelte 4 brings numerous performance improvements and enriches the development experience, thereby increasing developer productivity and enabling the creation of more efficient applications. Its thoughtful design, alongside the streamlined migration process, is set to expand its adoption in the web development community....

Ian Sam Mungai5 mins
Svelte