diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml
index 4ab7a210..e8a400f4 100644
--- a/.github/workflows/dockerhub.yml
+++ b/.github/workflows/dockerhub.yml
@@ -60,6 +60,7 @@ jobs:
build-args: |
APP_ENV=${{ env.VERSION == 'dev' && 'local' || 'production' }}
COMPOSER_FLAGS=${{ env.VERSION == 'dev' && '--optimize-autoloader --no-interaction' || '--no-dev --optimize-autoloader --no-interaction' }}
+ APP_VERSION=${{ env.VERSION }}
tags: ${{ env.API_TAGS }}
cache-from: type=registry,ref=${{secrets.DOCKER_API_REPO}}:dev
cache-to: type=inline
@@ -71,6 +72,8 @@ jobs:
file: docker/Dockerfile.client
platforms: linux/amd64,linux/arm64
push: true
+ build-args: |
+ APP_VERSION=${{ env.VERSION }}
tags: ${{ env.UI_TAGS }}
cache-from: type=registry,ref=${{secrets.DOCKER_UI_REPO}}:dev
cache-to: type=inline
diff --git a/api/app/Http/Controllers/Content/FeatureFlagsController.php b/api/app/Http/Controllers/Content/FeatureFlagsController.php
index 43ff0b57..dd7cae53 100644
--- a/api/app/Http/Controllers/Content/FeatureFlagsController.php
+++ b/api/app/Http/Controllers/Content/FeatureFlagsController.php
@@ -14,6 +14,7 @@ class FeatureFlagsController extends Controller
'self_hosted' => config('app.self_hosted', true),
'custom_domains' => config('custom-domains.enabled', false),
'ai_features' => !empty(config('services.openai.api_key')),
+ 'version' => $this->getAppVersion(),
'billing' => [
'enabled' => !empty(config('cashier.key')) && !empty(config('cashier.secret')),
@@ -44,4 +45,17 @@ class FeatureFlagsController extends Controller
return response()->json($featureFlags);
}
+
+ /**
+ * Get the application version from Docker environment or fallback
+ */
+ private function getAppVersion(): ?string
+ {
+ // Only return version for self-hosted installations
+ if (!config('app.self_hosted', true)) {
+ return null;
+ }
+
+ return config('app.docker_version');
+ }
}
diff --git a/api/config/app.php b/api/config/app.php
index e409eb8b..dddc163f 100644
--- a/api/config/app.php
+++ b/api/config/app.php
@@ -15,6 +15,17 @@ return [
'name' => env('APP_NAME', 'OpnForm'),
+ /*
+ |--------------------------------------------------------------------------
+ | Application Version
+ |--------------------------------------------------------------------------
+ |
+ | This value is the version of your application. Used for display purposes
+ | and fallback when Docker build version is not available.
+ |
+ */
+ 'docker_version' => env('APP_VERSION_DOCKER'),
+
/*
|--------------------------------------------------------------------------
| Application Environment
diff --git a/client/components/pages/OpenFormFooter.vue b/client/components/pages/OpenFormFooter.vue
index fa61bf8f..0a7e881a 100644
--- a/client/components/pages/OpenFormFooter.vue
+++ b/client/components/pages/OpenFormFooter.vue
@@ -4,6 +4,9 @@
© Copyright {{ currYear }}. All Rights Reserved
+
+
Version {{ version }}
+
@@ -82,22 +85,14 @@
-
diff --git a/client/middleware/self-hosted-credentials.js b/client/middleware/self-hosted-credentials.js
index be46fbbc..d7d6265b 100644
--- a/client/middleware/self-hosted-credentials.js
+++ b/client/middleware/self-hosted-credentials.js
@@ -1,11 +1,5 @@
export default defineNuxtRouteMiddleware(async () => {
const authStore = useAuthStore()
- const featureFlagsStore = useFeatureFlagsStore()
-
- // Ensure feature flags are loaded
- if (!featureFlagsStore.isLoaded) {
- await featureFlagsStore.fetchFlags()
- }
if (useFeatureFlag('self_hosted')) {
if (authStore.check && authStore.user?.email === 'admin@opnform.com') {
diff --git a/client/plugins/feature-flags.js b/client/plugins/feature-flags.js
deleted file mode 100644
index 2c067660..00000000
--- a/client/plugins/feature-flags.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { useFeatureFlagsStore } from '~/stores/featureFlags'
-
-export default defineNuxtPlugin(async () => {
- const featureFlagsStore = useFeatureFlagsStore()
-
- // Load flags if they haven't been loaded yet
- if (!featureFlagsStore.isLoaded) {
- await featureFlagsStore.fetchFlags()
- }
-})
\ No newline at end of file
diff --git a/client/plugins/featureFlags.js b/client/plugins/featureFlags.js
index 35cbca2f..1bcc8b0c 100644
--- a/client/plugins/featureFlags.js
+++ b/client/plugins/featureFlags.js
@@ -1,9 +1,18 @@
import { useFeatureFlagsStore } from '~/stores/featureFlags'
-export default defineNuxtPlugin((nuxtApp) => {
- const featureFlagsStore = useFeatureFlagsStore()
+export default defineNuxtPlugin(async (nuxtApp) => {
+ // Get the pinia instance for SSR compatibility
+ const { $pinia } = nuxtApp
- nuxtApp.provide('featureFlag', (key, defaultValue = false) => {
- return featureFlagsStore.getFlag(key, defaultValue)
- })
+ try {
+ // Pass pinia instance for SSR compatibility
+ const featureFlagsStore = useFeatureFlagsStore($pinia)
+
+ // Fetch flags during SSR to prevent hydration mismatches
+ if (!featureFlagsStore.isLoaded) {
+ await featureFlagsStore.fetchFlags()
+ }
+ } catch (error) {
+ console.error('Feature flags plugin failed:', error)
+ }
})
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index c1ca2438..39194bdf 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,7 +1,11 @@
---
services:
api: &api-environment
- image: jhumanj/opnform-api:latest
+ build:
+ context: .
+ dockerfile: docker/Dockerfile.api
+ args:
+ APP_VERSION: "local-test-1.0.0"
container_name: opnform-api
volumes: &api-environment-volumes
- opnform_storage:/usr/share/nginx/html/storage:rw
@@ -62,7 +66,11 @@ services:
start_period: 70s # Allow time for first scheduled run and cache write
ui:
- image: jhumanj/opnform-client:latest
+ build:
+ context: .
+ dockerfile: docker/Dockerfile.client
+ args:
+ APP_VERSION: "local-test-1.0.0"
container_name: opnform-client
env_file:
- ./client/.env
diff --git a/docker/Dockerfile.api b/docker/Dockerfile.api
index a2055666..a3e5b9ec 100644
--- a/docker/Dockerfile.api
+++ b/docker/Dockerfile.api
@@ -27,6 +27,9 @@ RUN composer install --optimize-autoloader --no-interaction \
# Final stage - smaller runtime image
FROM php:8.3-fpm-alpine
+# Accept version build argument
+ARG APP_VERSION=unknown
+
# Install runtime dependencies
RUN apk add --no-cache \
libzip \
@@ -75,6 +78,9 @@ RUN mkdir -p storage/framework/sessions \
# Copy the entire application from the builder stage
COPY --from=builder /app/ ./
+# Set version as environment variable (more reliable than file approach)
+ENV APP_VERSION_DOCKER=$APP_VERSION
+
# Setup entrypoint
COPY docker/php-fpm-entrypoint /usr/local/bin/opnform-entrypoint
RUN chmod a+x /usr/local/bin/*