# Ionic Vue Quickstart

URL: https://ionicframework.com/docs/vue/quickstart

Welcome! This guide will walk you through the basics of Ionic Vue development. You'll learn how to set up your development environment, generate a simple project, explore the project structure, and understand how Ionic components work. This is perfect for getting familiar with Ionic Vue before building your first real app.

If you're looking for a high-level overview of what Ionic Vue is and how it fits into the Vue ecosystem, refer to the [Ionic Vue Overview](/docs/vue/overview.md).

## Prerequisites

Before you begin, make sure you have Node.js and npm installed on your machine. You can check by running:

```shell
node -v
npm -v
```

If you don't have Node.js and npm, [download Node.js](https://nodejs.org/en/download) (which includes npm).

## Create a Project with the Ionic CLI

First, install the latest [Ionic CLI](/docs/cli.md):

```shell
npm install -g @ionic/cli
```

Then, run the following commands to create and run a new project:

```shell
ionic start myApp blank --type vue

cd myApp
ionic serve
```

After running `ionic serve`, your project will open in the browser.

![Screenshot of the Ionic Vue Home page](/docs/assets/images/home-page-b1132050b22308a7489fcfe09856e671.png)

## Explore the Project Structure

Your new app's directory will look like this:

```shell
└── src/
    ├── App.vue
    ├── main.ts
    ├── router
    │   └── index.ts
    └── views
       └── HomePage.vue
```

**Info**

All file paths in the examples below are relative to the project root directory.

Let's walk through these files to understand the app's structure.

## View the App Component

The root of your app is defined in `App.vue`:

src/App.vue

```vue
<template>
  <ion-app>
    <ion-router-outlet />
  </ion-app>
</template>

<script setup lang="ts">
import { IonApp, IonRouterOutlet } from '@ionic/vue';
</script>
```

This sets up the root of your application, using Ionic's `ion-app` and `ion-router-outlet` components. The router outlet is where your pages will be displayed.

## View Routes

Routes are defined in `router/index.ts`:

src/router/index.ts

```ts
import { createRouter, createWebHistory } from '@ionic/vue-router';
import type { RouteRecordRaw } from 'vue-router';

import HomePage from '../views/HomePage.vue';

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/home',
    name: 'Home',
    component: HomePage,
  },
];

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes,
});

export default router;
```

When you visit the root URL (`/` ), the `HomePage` component will be loaded.

## View the Home Page

The Home page component, defined in `HomePage.vue`, imports the Ionic components and defines the page template:

src/views/HomePage.vue

```vue
<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Blank</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">Blank</ion-title>
        </ion-toolbar>
      </ion-header>

      <div id="container">
        <strong>Ready to create an app?</strong>
        <p>
          Start with Ionic
          <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components"
            >UI Components</a
          >
        </p>
      </div>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
</script>

<!-- ...styles... -->
```

This creates a page with a header and scrollable content area. The second header shows a [collapsible large title](/docs/api/title.md#collapsible-large-titles) that displays on iOS devices when at the top of the content, then condenses to show the smaller title in the first header when scrolling down.

**Tip: Learn More**

For detailed information about Ionic layout components, refer to the [Header](/docs/api/header.md), [Toolbar](/docs/api/toolbar.md), [Title](/docs/api/title.md), and [Content](/docs/api/content.md) documentation.

## Add an Ionic Component

You can enhance your Home page with more Ionic UI components. For example, add a [Button](/docs/api/button.md) at the end of the `ion-content`:

src/views/HomePage.vue

```vue
<ion-content>
  <!-- existing content -->

  <ion-button>Navigate</ion-button>
</ion-content>
```

Then, import the `IonButton` component in the `<script>` tag:

src/views/HomePage.vue

```vue
<script setup lang="ts">
import { IonButton, IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
</script>
```

## Add a New Page

Create a new page at `NewPage.vue`:

src/views/NewPage.vue

```vue
<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-buttons slot="start">
          <ion-back-button default-href="/"></ion-back-button>
        </ion-buttons>
        <ion-title>New</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">New</ion-title>
        </ion-toolbar>
      </ion-header>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { IonBackButton, IonButtons, IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
</script>
```

This creates a page with a [Back Button](/docs/api/back-button.md) in the [Toolbar](/docs/api/toolbar.md). The back button will automatically handle navigation back to the previous page, or to `/` if there is no history.

**Warning**

When creating your own pages, always use `ion-page` as the root component. This is essential for proper transitions between pages, base CSS styling that Ionic components depend on, and consistent layout behavior across your app.

## Navigate to the New Page

To navigate to the new page, create a route for it by first importing it at the top of `router/index.ts` after the `HomePage` import:

src/router/index.ts

```ts
import NewPage from '../views/NewPage.vue';
```

Then, add its route in the `routes` array:

src/router/index.ts

```ts
const routes: RouteRecordRaw[] = [
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/home',
    name: 'Home',
    component: HomePage,
  },
  {
    path: '/new',
    name: 'New',
    component: NewPage,
  },
];
```

Once that is done, update the button in `HomePage.vue`:

src/views/HomePage.vue

```vue
<ion-button router-link="/new">Navigate</ion-button>
```

**Info**

Navigating can also be performed programmatically using Vue Router, and routes can be lazy loaded for better performance. Refer to the [Vue Navigation documentation](/docs/vue/navigation.md) for more information.

## Add Icons to the New Page

Ionic Vue comes with [Ionicons](https://ionic.io/ionicons/) pre-installed. You can use any icon by setting the `icon` property of the `ion-icon` component.

Update the imports in `NewPage.vue` to import `IonIcon` and the `heart` and `logoIonic` icons:

src/views/NewPage.vue

```vue
<script setup lang="ts">
import { IonBackButton, IonButtons, IonContent, IonHeader, IonIcon, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
import { heart, logoIonic } from 'ionicons/icons';
</script>
```

Then, include them inside of the `ion-content`:

src/views/NewPage.vue

```vue
<ion-icon :icon="heart"></ion-icon>
<ion-icon :icon="logoIonic"></ion-icon>
```

Note that we are passing the imported SVG reference, **not** the icon name as a string.

For more information, refer to the [Icon documentation](/docs/api/icon.md) and the [Ionicons documentation](https://ionic.io/ionicons/).

## Call Component Methods

Let's add a button that can scroll the content area to the bottom.

Update `NewPage.vue` to include a ref on `ion-content` and a button and some items after the existing icons:

src/views/NewPage.vue

```vue
<ion-content ref="content">
  <ion-button @click="scrollToBottom">Scroll to Bottom</ion-button>

  <!-- Add lots of content to make scrolling possible -->
  <ion-item v-for="i in 50" :key="i">
    <ion-label>Item {{ i }}</ion-label>
  </ion-item>
</ion-content>
```

In the script section, add the new component imports and define the `scrollToBottom` function:

src/views/NewPage.vue

```vue
<script setup lang="ts">
import {
  IonBackButton,
  IonButtons,
  IonButton,
  IonContent,
  IonHeader,
  IonIcon,
  IonItem,
  IonLabel,
  IonPage,
  IonTitle,
  IonToolbar,
} from '@ionic/vue';
import { heart, logoIonic } from 'ionicons/icons';
import { ref } from 'vue';

const content = ref();

const scrollToBottom = () => {
  content.value.$el.scrollToBottom(300);
};
</script>
```

To call methods on Ionic components:

1. Create a `ref` for the component
2. Access the underlying Web Component via `$el`
3. Call the method on the Web Component
This pattern is necessary because Ionic components are built as Web Components. The `$el` property gives you access to the actual Web Component instance where the methods are defined.

You can find available methods for each component in the [Methods](/docs/api/content.md#methods) section of their API documentation.

## Run on a Device

Ionic's components work everywhere: on iOS, Android, and PWAs. To deploy to mobile, use [Capacitor](https://capacitorjs.com):

```shell
ionic build
ionic cap add ios
ionic cap add android
```

Open the native projects in their IDEs:

```shell
ionic cap open ios
ionic cap open android
```

Refer to [Capacitor's Getting Started guide](https://capacitorjs.com/docs/getting-started/with-ionic) for more.

## Build with TypeScript or JavaScript

Ionic Vue projects are created with TypeScript by default, but you can easily convert to JavaScript if you prefer. After generating a blank Ionic Vue app, follow these steps:

1. Remove the TypeScript dependencies:

```shell
npm uninstall --save typescript @types/node @ionic/eslint-config @vue/eslint-config-typescript vue-tsc
```

1. Change the extension of all `.ts` files to `.js`, except `src/vite-env.d.ts`, which is deleted in a later step. In a blank Ionic Vue app, this will be the `src/router/index.ts`, `src/main.ts`, `vite.config.ts`, `playwright.config.ts`, and files in the `tests` directory.
2. In `index.html`, change the imported `<script>` file from `/src/main.ts` to `/src/main.js`.
3. Replace the contents of `eslint.config.js` with the following, which removes the TypeScript and `@ionic/eslint-config` configuration:
eslint.config.js

```js
import js from '@eslint/js';
import pluginVue from 'eslint-plugin-vue';
import globals from 'globals';

export default [
  {
    ignores: ['dist/**', 'android/**', 'ios/**', 'playwright-report/**', 'test-results/**', 'blob-report/**'],
  },
  js.configs.recommended,
  ...pluginVue.configs['flat/essential'],
  {
    languageOptions: {
      globals: {
        ...globals.node,
        ...globals.browser,
      },
    },
    rules: {
      'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
      'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
      'vue/no-deprecated-slot-attribute': 'off',
    },
  },
  {
    files: ['tests/unit/**/*.spec.{js,ts}'],
    languageOptions: {
      globals: globals.vitest,
    },
  },
];
```

1. Remove the `RouteRecordRaw[]` type annotation and the import of `RouteRecordRaw` from `src/router/index.js`.
2. Remove `lang="ts"` from the `script` tags in any of your Vue components that have them. In a blank Ionic Vue app, this should only be `src/App.vue` and `src/views/HomePage.vue`.
3. Delete `tsconfig.json`, `tsconfig.node.json`, `tsconfig.e2e.json`, and `src/vite-env.d.ts`.
4. In `package.json`, change the build script from `"build": "vue-tsc && vite build"` to `"build": "vite build"`.
5. In `package.json`, change the prettier script from `"prettier": "prettier \"**/*.{ts,vue}\""` to `"prettier": "prettier \"**/*.{js,vue}\""` so that `npm run lint` checks the formatting of the `.js` files.
6. In `package.json`, remove the `typecheck:e2e` script and change the lint script to `"lint": "npm run eslint && npm run prettier -- --check"`, since there are no TypeScript files left to type-check.

## Explore More

This guide covered the basics of creating an Ionic Vue app, adding navigation, and introducing Capacitor for native builds. To dive deeper, check out:

[![](/docs/icons/component-content-icon.png) ![](/docs/icons/component-content-icon.png)
Build Your First App Build a real Photo Gallery app with Ionic Vue and native device features.](/docs/vue/your-first-app.md) [![](/docs/icons/logo-vue-icon.png) ![](/docs/icons/logo-vue-icon.png)
Vue Documentation Learn more about Vue's core concepts, tools, and best practices from the official Vue documentation.](https://vuejs.org/guide/introduction.html) [![](/docs/icons/component-navigation-icon.png) ![](/docs/icons/component-navigation-icon.png)
Navigation Discover how to handle routing and navigation in Ionic Vue apps using the Vue Router.](/docs/vue/navigation.md) [![](/docs/icons/guide-components-icon.png) ![](/docs/icons/guide-components-icon.png)
Components Explore Ionic's rich library of UI components for building beautiful apps.](/docs/components.md) [![](/docs/icons/guide-theming-icon.png) ![](/docs/icons/guide-theming-icon.png)
Theming Learn how to customize the look and feel of your app with Ionic's powerful theming system.](/docs/theming/basics.md) [![](/docs/icons/guide-capacitor-icon.png) ![](/docs/icons/guide-capacitor-icon.png)
Capacitor Documentation Explore how to access native device features and deploy your app to iOS, Android, and the web with Capacitor.](https://capacitorjs.com/docs/)
