Reference

Assets

OtherEvergreenPublic

Vector

Bitmap

Font

  • Backgrounds
  • Logos
  • Tokens
  • Templates
  • Layouts
  • Themes
  • Components

Nuxt 3 Environment Configuration Setup

1. Configure Runtime Config in nuxt.config.ts

export default defineNuxtConfig({
  runtimeConfig: {
    // Private keys (server-side only)
    apiSecret: '',

    // Public keys (exposed to client and server)
    public: {
      baseUrl: process.env.NUXT_PUBLIC_BASE_URL || 'http://localhost:3000',
      assetsPath: process.env.NUXT_PUBLIC_ASSETS_PATH || '/resources',
      apiPath: process.env.NUXT_PUBLIC_API_PATH || '/api',
    }
  },

  // Optional: Configure asset handling
  app: {
    baseURL: process.env.NUXT_APP_BASE_URL || '/',
    buildAssetsDir: '/_nuxt/',
    cdnURL: process.env.NUXT_APP_CDN_URL || ''
  }
})

2. Environment Variables Setup

Development (.env)

# Base configuration
NUXT_PUBLIC_BASE_URL=http://localhost:3000
NUXT_PUBLIC_ASSETS_PATH=/resources
NUXT_PUBLIC_API_PATH=/api

# Optional: App-level configuration
NUXT_APP_BASE_URL=/
NUXT_APP_CDN_URL=

Production (.env.production)

# Production configuration
NUXT_PUBLIC_BASE_URL=https://yourdomain.com
NUXT_PUBLIC_ASSETS_PATH=/assets
NUXT_PUBLIC_API_PATH=/api/v1

# Optional: Production CDN
NUXT_APP_CDN_URL=https://cdn.yourdomain.com

Staging (.env.staging)

# Staging configuration
NUXT_PUBLIC_BASE_URL=https://staging.yourdomain.com
NUXT_PUBLIC_ASSETS_PATH=/resources
NUXT_PUBLIC_API_PATH=/api

# Optional: Staging CDN
NUXT_APP_CDN_URL=https://staging-cdn.yourdomain.com

3. Asset URL Builder Composable

Create composables/useAssetUrl.ts:

export const useAssetUrl = () => {
  const config = useRuntimeConfig()

  const buildAssetUrl = (path: string): string => {
    // Remove leading slash if present to avoid double slashes
    const cleanPath = path.startsWith('/') ? path.slice(1) : path

    // Combine base URL, assets path, and the specific asset path
    return `${config.public.baseUrl}${config.public.assetsPath}/${cleanPath}`
  }

  const buildApiUrl = (endpoint: string): string => {
    // Remove leading slash if present to avoid double slashes
    const cleanEndpoint = endpoint.startsWith('/') ? endpoint.slice(1) : endpoint

    // Combine base URL, API path, and the specific endpoint
    return `${config.public.baseUrl}${config.public.apiPath}/${cleanEndpoint}`
  }

  // Helper for building full URLs with query parameters
  const buildAssetUrlWithQuery = (path: string, params?: Record<string, string>): string => {
    const baseUrl = buildAssetUrl(path)
    if (!params) return baseUrl

    const searchParams = new URLSearchParams(params)
    return `${baseUrl}?${searchParams.toString()}`
  }

  return {
    buildAssetUrl,
    buildApiUrl,
    buildAssetUrlWithQuery,
    config: config.public
  }
}

Auto-Import Setup (Optional)

To make the composable available globally without imports, add to nuxt.config.ts:

export default defineNuxtConfig({
  // ... your existing config

  // Auto-import the composable globally
  imports: {
    dirs: ['composables/**']
  }
})

4. Usage Examples

In Vue Components

<template>
  <div>
    <!-- Method 1: Pre-computed reactive variables (Recommended) -->
    <img :src="backgroundImageUrl" alt="Background" />

    <!-- Method 2: Direct function calls in template -->
    <img :src="buildAssetUrl('images/hero/hero-banner.jpeg')" alt="Hero" />

    <!-- Method 3: Using computed properties for complex logic -->
    <img :src="dynamicImageUrl" alt="Dynamic" />

    <!-- Method 4: Template string interpolation -->
    <div>Background URL: {{ backgroundImageUrl }}</div>

    <!-- Direct access to config -->
    <div>Base URL: {{ config.baseUrl }}</div>
    <div>Assets Path: {{ config.assetsPath }}</div>
    <div>API Path: {{ config.apiPath }}</div>
  </div>
</template>

<script setup lang="ts">
// Using the composable
const { buildAssetUrl, buildApiUrl, config } = useAssetUrl()

// Method 1: Pre-computed reactive variables (Best for performance)
const backgroundImageUrl = buildAssetUrl('images/backgrounds/background-slide.jpeg')

// Method 2: Functions are automatically available in template when destructured

// Method 3: Computed properties for dynamic URLs
const imageName = ref('background-slide.jpeg')
const dynamicImageUrl = computed(() =>
  buildAssetUrl(`images/backgrounds/${imageName.value}`)
)

// Example API URL building
const usersApiUrl = buildApiUrl('users')

console.log('Background Image URL:', backgroundImageUrl)
// Output: http://localhost:3000/resources/images/backgrounds/background-slide.jpeg

console.log('Users API URL:', usersApiUrl)
// Output: http://localhost:3000/api/users

// Direct access to runtime config
const runtimeConfig = useRuntimeConfig()
console.log('All public config:', runtimeConfig.public)
</script>

Template Usage Patterns

<template>
  <div>
    <!-- ✅ CORRECT: Direct function call -->
    <img :src="buildAssetUrl('images/backgrounds/background-slide.jpeg')" alt="Background" />

    <!-- ✅ CORRECT: Pre-computed variable -->
    <img :src="heroImage" alt="Hero" />

    <!-- ✅ CORRECT: Computed property -->
    <img :src="dynamicImage" alt="Dynamic" />

    <!-- ✅ CORRECT: String interpolation -->
    <div>{{ buildAssetUrl('images/logo.png') }}</div>

    <!-- ❌ INCORRECT: Double curly braces in attributes -->
    <!-- <img src="{{buildAssetUrl('image.jpg')}}" alt="Wrong" /> -->

    <!-- ❌ INCORRECT: Missing v-bind or : -->
    <!-- <img src="buildAssetUrl('image.jpg')" alt="Wrong" /> -->
  </div>
</template>

<script setup lang="ts">
const { buildAssetUrl } = useAssetUrl()

// Pre-computed for better performance
const heroImage = buildAssetUrl('images/hero/main-banner.jpeg')

// Dynamic computed property
const imageType = ref('jpeg')
const dynamicImage = computed(() =>
  buildAssetUrl(`images/gallery/photo.${imageType.value}`)
)
</script>

In Server API Routes

// server/api/example.ts
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig(event)

  // Access public config on server
  const baseUrl = config.public.baseUrl
  const apiPath = config.public.apiPath

  // Build URLs on server-side
  const externalApiUrl = `${baseUrl}${apiPath}/external-service`

  return {
    message: 'Server response',
    apiUrl: externalApiUrl
  }
})

In Plugins

// plugins/api.client.ts
export default defineNuxtPlugin(() => {
  const config = useRuntimeConfig()

  // Configure API client with runtime config
  const apiClient = $fetch.create({
    baseURL: `${config.public.baseUrl}${config.public.apiPath}`
  })

  return {
    provide: {
      apiClient
    }
  }
})

5. Alternative: Using App Config for Static Values

If you have static configuration that doesn't need environment overrides, use app.config.ts:

// app.config.ts
export default defineAppConfig({
  assets: {
    imageSizes: ['sm', 'md', 'lg', 'xl'],
    formats: ['webp', 'jpeg', 'png']
  },
  ui: {
    theme: 'dark',
    primary: '#ff0000'
  }
})

Access in components:

<script setup lang="ts">
const appConfig = useAppConfig()
console.log(appConfig.assets.imageSizes)
</script>

6. Production Deployment

When deploying to production, set environment variables:

# For Node.js deployment
NUXT_PUBLIC_BASE_URL=https://yourdomain.com \
NUXT_PUBLIC_ASSETS_PATH=/assets \
NUXT_PUBLIC_API_PATH=/api/v1 \
node .output/server/index.mjs

# Or via Docker environment
docker run -e NUXT_PUBLIC_BASE_URL=https://yourdomain.com \
           -e NUXT_PUBLIC_ASSETS_PATH=/assets \
           -e NUXT_PUBLIC_API_PATH=/api/v1 \
           your-nuxt-app

7. TypeScript Support

Add type safety by augmenting the runtime config types:

// types/runtime-config.d.ts
declare module 'nuxt/schema' {
  interface PublicRuntimeConfig {
    baseUrl: string
    assetsPath: string
    apiPath: string
  }
}

// Ensure this file is treated as a module
export {}

Key Benefits

  1. Environment Flexibility: Different configs for dev, staging, production
  2. Security: Sensitive values can be server-only (not in public)
  3. Type Safety: Full TypeScript support with proper typing
  4. Reusability: Composables make URL building consistent across your app
  5. Hot Reload: Environment changes are picked up automatically in development

Migration from Hardcoded URLs

Replace your current hardcoded URLs:

// Before
const imageUrl = 'http://localhost:3000/resources/images/backgrounds/background-slide.jpeg'

// After
const { buildAssetUrl } = useAssetUrl()
const imageUrl = buildAssetUrl('images/backgrounds/background-slide.jpeg')

This setup provides a robust, scalable solution for managing environment-specific configurations in your Nuxt 3 application.