Skip to content

Frontend

This guide details the frontend structure and functionality of the Shopify Vue App template.

Directory Structure

client/
├── src/
│   ├── assets/           # Static assets and styles
│   │   ├── base.css     # Base styles and resets
│   │   ├── main.css     # Main application styles
│   │   └── images/      # Image assets
│   ├── components/      # Reusable Vue components
│   │   ├── About/       # About page components
│   │   ├── Home/        # Home page components
│   │   └── NavBar/      # Navigation components
│   ├── locales/         # i18n translation files
│   │   ├── en.json     # English translations
│   │   └── zh.json     # Chinese translations
│   ├── plugins/         # Vue plugins and integrations
│   │   └── appBridge.js # Shopify App Bridge setup
│   ├── router/          # Vue Router configuration
│   │   └── index.js    # Route definitions
│   ├── stores/          # Pinia state management
│   │   └── products.js # Product state store
│   ├── views/           # Page components
│   ├── App.vue         # Root component
│   ├── i18n.js         # i18n configuration
│   └── main.js         # Application entry point
└── vite.config.js      # Vite bundler configuration

Core Components

1. Application Entry

The main entry point (src/main.js) initializes all core functionalities:

js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { i18n } from './i18n'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(i18n) // Enable internationalization
app.use(createPinia()) // Initialize state management
app.use(router) // Set up routing
app.mount('#app')

2. Views and Components

Page Components (/views)

  • HomeView.vue: Landing/dashboard page
  • AboutView.vue: About/info page
  • NotFoundView.vue: 404 error page
vue
// NavBar/WelcomeNavBar.vue
<template>
  <nav>
    <RouterLink :to="{ name: 'home' }">
      {{ $t('NavBar.home') }}
    </RouterLink>
    <LanguageSwitcher />
  </nav>
</template>

3. State Management

The app uses Pinia for state management with modular stores using script setup syntax:

js
// stores/products.js
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useProductStore = defineStore('products', () => {
  // State
  const products = ref([])
  const isLoading = ref(false)

  // Actions
  async function fetchProducts() {
    isLoading.value = true
    try {
      const response = await fetch('/api/products')
      products.value = await response.json()
    } catch (error) {
      console.error('Failed to fetch products:', error)
    } finally {
      isLoading.value = false
    }
  }

  // Return state and actions
  return {
    products,
    isLoading,
    fetchProducts
  }
})

4. Routing System

Vue Router configuration with authentication and locale support:

js
// router/index.js
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/:locale?',
      children: [
        {
          path: '',
          name: 'home',
          component: HomeView
        }
      ]
    }
  ]
})

// i18n navigation guard
router.beforeEach(async (to, from, next) => {
  // Handle locale routing
  const locale = to.params.locale || i18n.global.locale
  await loadLocaleMessages(i18n, locale)
  next()
})

5. Internationalization (i18n)

Multi-language support configuration:

js
// i18n.js
import { createI18n } from 'vue-i18n'

export const SUPPORT_LOCALES = ['en', 'zh']

export const i18n = createI18n({
  locale: localStorage.getItem('app_locale') || 'en',
  fallbackLocale: 'en',
  messages: {}
})

// Usage in components
const { t } = useI18n()
<h1>{{ t('HomePage.title') }}</h1>

Translation structure:

json
// locales/en.json
{
  "NavBar": {
    "home": "Home",
    "about": "About"
  },
  "HomePage": {
    "title": "Welcome",
    "description": "Start building your Shopify app"
  }
}

6. Shopify Integration

App Bridge Setup

js
// plugins/appBridge.js
export const appBridge = window.shopify

App Bridge Usage

js
// Toast notifications
appBridge.toast.show('Operation successful!')

// Navigation
appBridge.navigate.toCard('settings')

// Modal dialogs
appBridge.modal.open({
  title: 'Confirmation',
  message: 'Are you sure?'
})

7. API Communication

Authenticated API requests using App Bridge:

js
// Example API call
async function fetchProducts() {
  try {
    const response = await fetch('/api/products/count')
    if (!response.ok) throw new Error('API Error')
    return await response.json()
  } catch (error) {
    appBridge.toast.show(error.message, { isError: true })
  }
}

Development Tools

1. TypeScript Support

json
// tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "strict": true,
    "jsx": "preserve",
    "types": ["@shopify/app-bridge-types"]
  }
}

Security Best Practices

  1. XSS Prevention
  • Use Vue's template syntax
  • Sanitize user input
  • Enable CSP headers
  1. Authentication
  • Secure session handling
  • Token management
  • HTTPS enforcement
  1. Data Protection
  • Client-side validation
  • Secure storage practices
  • Error handling

Error Handling

  1. API Errors
js
try {
  const response = await fetch('/api/products')
  if (!response.ok) throw new Error('API Error')
} catch (error) {
  appBridge.toast.show(error.message, { isError: true })
}

Performance Optimization

  1. Code Splitting
  • Route-based code splitting
  • Async components
  • Dynamic imports
  1. Asset Optimization
  • Image optimization
  • CSS minification
  • Tree shaking

Best Practices

  1. Component Organization
  • Single responsibility
  • Proper naming
  • Clear props/emits
  • TypeScript types
  1. State Management
  • Clear store modules
  • Computed properties
  • Action composition
  • Type safety
  1. Code Style
  • ESLint configuration
  • Prettier formatting
  • Component conventions
  • Documentation

Deployment

The frontend does not run on it's own, when building the app, the npm run build command will be run and the backend will serve the index.html

Released under the MIT License.