Runtime & App Config
A prepare script can set runtimeConfig and appConfig values it had to fetch or compute first.
Runtime Config
Use runtimeConfig to conditionally set environment-based configuration that should be accessible via Nuxt's useRuntimeConfig().
import { defineNuxtPrepareHandler } from 'nuxt-prepare/config'
export default defineNuxtPrepareHandler(async () => {
// Fetch API configuration from a remote source
const apiConfig = await fetch('https://config.example.com/api')
.then(res => res.json())
return {
runtimeConfig: {
// Private config (server-only)
apiSecret: apiConfig.secret,
public: {
// Public config (available everywhere)
apiUrl: apiConfig.url,
apiVersion: apiConfig.version
}
}
}
})Access runtime config values anywhere in your app:
const config = useRuntimeConfig()
console.log(config.public.apiUrl) // Set by prepare scriptPrecedence
A script's result is merged into the runtime config rather than replacing it, so keys you leave out keep the value nuxt.config.ts gave them. Keys you do return win over it, and a later script wins over an earlier one.
App Config
Use appConfig to set application-wide configuration that should be accessible via Nuxt's useAppConfig().
import { defineNuxtPrepareHandler } from 'nuxt-prepare/config'
export default defineNuxtPrepareHandler(async () => {
// Fetch feature flags from a CMS or feature flag service
const features = await fetch('https://api.example.com/features')
.then(res => res.json())
return {
appConfig: {
features: {
darkMode: features.darkMode,
analytics: features.analytics,
betaFeatures: features.beta
}
}
}
})Access app config values anywhere in your app:
<script setup lang="ts">
const appConfig = useAppConfig()
const isDarkModeEnabled = appConfig.features.darkMode
</script>Precedence
App config merges the same way, over what app.config.ts defines.
When to Use Each Option
Use state
- Import data as constants
- Get full TypeScript type inference from generated types
- Share data between multiple modules without prop drilling
import { tenant } from '#nuxt-prepare'
// Direct constant access with full type safety
if (tenant.id) {
// ...
}Use runtimeConfig
- Follow Nuxt's runtime configuration patterns
- Access environment variables and secrets
- Use Nuxt's built-in public/private config separation
const config = useRuntimeConfig()
// Accessed via composable
const apiUrl = config.public.apiUrlUse appConfig
- Define app-wide configuration
- Support runtime updates with HMR
- Follow Nuxt's app config patterns
const appConfig = useAppConfig()
// Accessed via composable, supports HMR
const theme = appConfig.themePractical Example: Multi-Tenant Configuration
A multi-tenant build uses all three:
import { defineNuxtPrepareHandler } from 'nuxt-prepare/config'
import { ofetch } from 'ofetch'
export default defineNuxtPrepareHandler(async () => {
const tenantId = process.env.TENANT_ID
const tenant = await ofetch(`https://api.example.com/tenants/${tenantId}`)
return {
// Public tenant data as importable constants
state: {
tenant: {
id: tenant.id,
name: tenant.name,
logo: tenant.logo
}
},
// API configuration
runtimeConfig: {
tenantApiKey: tenant.apiKey, // Private
public: {
tenantApiUrl: tenant.apiUrl // Public
}
},
// Theme configuration
appConfig: {
theme: {
primaryColor: tenant.primaryColor,
logo: tenant.logo
}
}
}
})Now you can use each piece of data in the most appropriate way:
<script setup lang="ts">
import { tenant } from '#nuxt-prepare'
const config = useRuntimeConfig()
const appConfig = useAppConfig()
// Direct import for static data
const tenantName = tenant.name
// Runtime config for API calls
const apiUrl = config.public.tenantApiUrl
// App config for theme
const primaryColor = appConfig.theme.primaryColor
</script>