Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,5 @@ $RECYCLE.BIN/
.vite

# End of https://www.toptal.com/developers/gitignore/api/java,linux,macos,maven,eclipse,windows,visualstudiocode,node

celements-admin-frontend/public/config.js

@msladek msladek Jun 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
celements-admin-frontend/public/config.js
**/public/config.js

more frontends will likely follow :)

8 changes: 8 additions & 0 deletions celements-admin-frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules
dist
.git
.gitignore
.env
.env.*
*.log
public/config.js
14 changes: 14 additions & 0 deletions celements-admin-frontend/.env.celdev
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
VITE_ENABLE_LOCAL_DEVELOPMENT=false

# url settings
VITE_APP_BASE_URL=https://bellis.celdev.sneakapeek.ch
VITE_CEL_API_URL=https://bellis.celdev.sneakapeek.ch

# keycloak configuration
VITE_KEYCLOAK_BASE_URL=https://iam.demospace.ch
VITE_KEYCLOAK_REALM=celdev
VITE_KEYCLOAK_CLIENT_ID=celdev

# cel access
VITE_CEL_USER=
VITE_CEL_TOKEN=

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we remove .env.celdev and .env.celint? appConfig should be the preferred configuration mechanism. env- or node-specific values belong on the target nodes, not in this public code repo.

for local configuration:

cp config.sample.js public/config.js && vim public/config.js

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ VITE_ENABLE_LOCAL_DEVELOPMENT=false

# url settings
VITE_APP_BASE_URL=https://bellis.celint.demospace.ch
VITE_CEL_API_URL=https://bellis.celint.sneakapeek.ch
VITE_CEL_API_URL=https://bellis.celint.demospace.ch

# keycloak configuration
VITE_KEYCLOAK_BASE_URL=https://iam.demospace.ch
Expand Down
4 changes: 0 additions & 4 deletions celements-admin-frontend/Caddyfile

This file was deleted.

16 changes: 12 additions & 4 deletions celements-admin-frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,26 @@ RUN npm install --legacy-peer-deps

# Layer: package
COPY . .
ARG PROFILE_ACTIVE=dev
RUN mv .env.${PROFILE_ACTIVE} .env; \
npm run build
RUN npm run build

## Stage: execute
FROM caddy:2 AS execute

ARG VERSION
ARG REVISION

LABEL org.opencontainers.image.source="https://github.com/celements/celements-web" \
org.opencontainers.image.description="Celements admin frontend" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}"

WORKDIR /srv

COPY --from=build /app/dist /srv
COPY Caddyfile /etc/caddy/Caddyfile
COPY docker/Caddyfile /etc/caddy/Caddyfile
COPY --chmod=755 docker/entrypoint.sh /usr/local/bin/start
RUN caddy fmt /etc/caddy/Caddyfile --overwrite

EXPOSE 80
ENTRYPOINT ["start"]
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
63 changes: 63 additions & 0 deletions celements-admin-frontend/Jenkinsfile

@msladek msladek Jun 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
def appImage

pipeline {
agent { label 'docker' }
environment {
REGISTRY = 'ghcr.io'
ORG_NAME = 'celements'
APP_DIR = 'celements-admin-frontend'
IMAGE_NAME = 'celements-admin-frontend'
DOCKER_BUILDKIT = '1'
}
options {
disableConcurrentBuilds()
skipDefaultCheckout(true)
timestamps()
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Prepare Build') {
steps {
dir(APP_DIR) {
script {
env.GIT_REV = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
env.GIT_SHA = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
env.VERSION = sh(
script: 'node -p "require(\'./package.json\').version"',
returnStdout: true
).trim()
env.IMAGE_REF = "${REGISTRY}/${ORG_NAME}/${IMAGE_NAME}:${VERSION}"
}
}
}
}
stage('Build Frontend Docker Image') {
steps {
dir(APP_DIR) {
script {
appImage = docker.build(
IMAGE_REF,
"--build-arg VERSION=${VERSION} " +
"--build-arg REVISION=${GIT_REV} " +
"--load ."
)
}
}
}
}
stage('Push to GHCR') {
steps {
script {
docker.withRegistry("https://${REGISTRY}", 'ghcr-credentials') {
appImage.push()
appImage.push("${VERSION}-${GIT_SHA}")
}
}
}
}
}
}
13 changes: 13 additions & 0 deletions celements-admin-frontend/docker/Caddyfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
:80 {
root * /srv

handle /config.js {
header Cache-Control "no-store, no-cache, must-revalidate"
file_server
}

handle {
try_files {path} /index.html
file_server
}
}
22 changes: 22 additions & 0 deletions celements-admin-frontend/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
set -eu

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
set -eu
set -euo pipefail

POSIX.1-2024 specification added support for pipefail, so it is fine in sh files.


escape_js_string() {
printf '%s' "$1" | sed \
-e 's/\\/\\\\/g' \
-e "s/'/\\\\'/g"
}

cat > /srv/config.js <<EOF
window.__APP_CONFIG__ = {
appBaseUrl: '$(escape_js_string "${APP_BASE_URL:-}")',
keycloakBaseUrl: '$(escape_js_string "${KEYCLOAK_BASE_URL:-}")',
keycloakRealm: '$(escape_js_string "${KEYCLOAK_REALM:-}")',
keycloakClientId: '$(escape_js_string "${KEYCLOAK_CLIENT_ID:-}")',
keycloakClientSecret: '$(escape_js_string "${KEYCLOAK_CLIENT_SECRET:-}")',
Comment on lines +12 to +16

@msladek msladek Jun 23, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
appBaseUrl: '$(escape_js_string "${APP_BASE_URL:-}")',
keycloakBaseUrl: '$(escape_js_string "${KEYCLOAK_BASE_URL:-}")',
keycloakRealm: '$(escape_js_string "${KEYCLOAK_REALM:-}")',
keycloakClientId: '$(escape_js_string "${KEYCLOAK_CLIENT_ID:-}")',
keycloakClientSecret: '$(escape_js_string "${KEYCLOAK_CLIENT_SECRET:-}")',
appBaseUrl: '$(escape_js_string "${APP_BASE_URL}")',
keycloakBaseUrl: '$(escape_js_string "${KEYCLOAK_BASE_URL}")',
keycloakRealm: '$(escape_js_string "${KEYCLOAK_REALM}")',
keycloakClientId: '$(escape_js_string "${KEYCLOAK_CLIENT_ID}")',
keycloakClientSecret: '$(escape_js_string "${KEYCLOAK_CLIENT_SECRET}")',

mandatory fields should fast fail if unset (sh strict mode) to prevent config errors.

defaultLocale: '$(escape_js_string "${DEFAULT_LOCALE:-de}")',
enableLocalDevelopment: ${ENABLE_LOCAL_DEVELOPMENT:-false}
};
EOF

exec "$@"
1 change: 1 addition & 0 deletions celements-admin-frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Celements Admin</title>
<script src="/config.js"></script>
</head>
<body class="bg-grau-20">
<div id="app" class="3xl:mx-auto max-w-screen-3xl"></div>
Expand Down
9 changes: 9 additions & 0 deletions celements-admin-frontend/public/config.sample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
window.__APP_CONFIG__ = {
appBaseUrl: 'http://localhost:5173',
keycloakBaseUrl: 'https://iam.demospace.ch',
keycloakRealm: 'celdev',
keycloakClientId: 'celdev',
keycloakClientSecret: '',
defaultLocale: 'de',
enableLocalDevelopment: false
};
5 changes: 3 additions & 2 deletions celements-admin-frontend/src/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '@/assets/main.css';

import App from '@/App.vue';
import { appConfig } from '@/conf/app';
import { useAuthStore } from '@/core/stores/auth';
import { createI18n } from '@/plugins/i18n';
import { createAuthPlugin } from '@/plugins/plugin.auth';
Expand Down Expand Up @@ -112,7 +113,7 @@ export function createCelementsAdminApp(options: CelementsAdminMountOptions = {}
const authStore = useAuthStore();
const Auth = createAuthPlugin(Router, authStore);

const locale = options.locale ?? import.meta.env.VITE_DEFAULT_LOCALE;
const locale = options.locale ?? appConfig.defaultLocale;

app.use(Router);
app.use(createI18n({ locale }));
Expand All @@ -128,7 +129,7 @@ export function createCelementsAdminApp(options: CelementsAdminMountOptions = {}
});

const localDev =
options.localDev ?? (import.meta.env.VITE_ENABLE_LOCAL_DEVELOPMENT ?? 'true') === 'true';
options.localDev ?? appConfig.enableLocalDevelopment;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldnt it be simpler to use import.meta.env.DEV (true in npm run dev) instead of a local config value?


app.provide('localDev', localDev);

Expand Down
27 changes: 27 additions & 0 deletions celements-admin-frontend/src/conf/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface AppConfig {
appBaseUrl: string;
keycloakBaseUrl: string;
keycloakRealm: string;
keycloakClientId: string;
keycloakClientSecret: string;
defaultLocale: string;
enableLocalDevelopment: boolean;
}

declare global {
interface Window {
__APP_CONFIG__?: Partial<AppConfig>;
}
}

export const appConfig: Readonly<AppConfig> = {
appBaseUrl: window.__APP_CONFIG__?.appBaseUrl || (import.meta.env.VITE_APP_BASE_URL as string) || '',
keycloakBaseUrl: window.__APP_CONFIG__?.keycloakBaseUrl || (import.meta.env.VITE_KEYCLOAK_BASE_URL as string) || '',
keycloakRealm: window.__APP_CONFIG__?.keycloakRealm || (import.meta.env.VITE_KEYCLOAK_REALM as string) || '',
keycloakClientId: window.__APP_CONFIG__?.keycloakClientId || (import.meta.env.VITE_KEYCLOAK_CLIENT_ID as string) || '',
keycloakClientSecret: window.__APP_CONFIG__?.keycloakClientSecret || (import.meta.env.VITE_KEYCLOAK_CLIENT_SECRET as string) || '',
defaultLocale: window.__APP_CONFIG__?.defaultLocale || (import.meta.env.VITE_DEFAULT_LOCALE as string) || 'de',
enableLocalDevelopment: window.__APP_CONFIG__?.enableLocalDevelopment !== undefined
? window.__APP_CONFIG__.enableLocalDevelopment
: (import.meta.env.VITE_ENABLE_LOCAL_DEVELOPMENT ?? 'true') === 'true',
};
3 changes: 2 additions & 1 deletion celements-admin-frontend/src/plugins/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { appConfig } from '@/conf/app';
import { messages } from '@/conf/locale';
import { createI18n as createVueI18n, type I18nOptions } from 'vue-i18n';

Expand All @@ -8,6 +9,6 @@ export const createI18n = (options: I18nOptions) =>
// datetimeFormats: datetime,
// numberFormats: number,
fallbackWarn: false,
fallbackLocale: import.meta.env.VITE_DEFAULT_LOCALE,
fallbackLocale: appConfig.defaultLocale,
...options,
});
13 changes: 7 additions & 6 deletions celements-admin-frontend/src/plugins/plugin.auth.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { appConfig } from '@/conf/app';
import { AuthService, createAuthService } from '@/core/services/auth/auth-service';
import type { AuthOptions } from '@/core/services/auth/types';
import type { AuthState } from '@/core/types/auth';
Expand All @@ -8,12 +9,12 @@ import type { Router } from 'vue-router';

const logger = useLogger('AuthPlugin');

// Get keycloak specific data from env
const appBaseUrl = import.meta.env.VITE_APP_BASE_URL;
const authBaseUrl = import.meta.env.VITE_KEYCLOAK_BASE_URL;
const realm = import.meta.env.VITE_KEYCLOAK_REALM;
const clientId = import.meta.env.VITE_KEYCLOAK_CLIENT_ID;
const clientSecret = import.meta.env.VITE_KEYCLOAK_CLIENT_SECRET;
// Get keycloak specific data from config
const appBaseUrl = appConfig.appBaseUrl;
const authBaseUrl = appConfig.keycloakBaseUrl;
const realm = appConfig.keycloakRealm;
const clientId = appConfig.keycloakClientId;
const clientSecret = appConfig.keycloakClientSecret;
Comment on lines +13 to +17

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const appBaseUrl = appConfig.appBaseUrl;
const authBaseUrl = appConfig.keycloakBaseUrl;
const realm = appConfig.keycloakRealm;
const clientId = appConfig.keycloakClientId;
const clientSecret = appConfig.keycloakClientSecret;
const { appBaseUrl, authBaseUrl, realm, clientId, clientSecret } = appConfig.appBaseUrl;


const createAuthPlugin = (router: Router, authStore: Store<'auth', AuthState>) => {
const options: AuthOptions = {
Expand Down
3 changes: 2 additions & 1 deletion celements-admin-frontend/src/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { appConfig } from '@/conf/app';
import { type ConsolaInstance, createConsola } from 'consola/browser';

// https://github.com/unjs/consola?tab=readme-ov-file#log-level
const level = import.meta.env.VITE_ENABLE_LOCAL_DEVELOPMENT === 'true' ? 4 : 1;
const level = appConfig.enableLocalDevelopment ? 4 : 1;

const loggerFactory: (tagName: string) => ConsolaInstance = (tagName: string) =>
createConsola({
Expand Down