From 2cee22f9bda40dfa6fab366f5fc2e991b16c6213 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 13 Nov 2025 15:01:37 +0530 Subject: [PATCH 01/13] hide: new dev promo alert. --- src/lib/stores/billing.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 46134dde3..d93af3842 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -41,6 +41,7 @@ import BudgetLimitAlert from '$routes/(console)/organization-[organization]/budg import TeamReadonlyAlert from '$routes/(console)/organization-[organization]/teamReadonlyAlert.svelte'; import ProjectsLimit from '$lib/components/billing/alerts/projectsLimit.svelte'; import EnterpriseTrial from '$routes/(console)/organization-[organization]/enterpriseTrial.svelte'; +import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte'; export type Tier = 'tier-0' | 'tier-1' | 'tier-2' | 'auto-1' | 'cont-1' | 'ent-1'; @@ -572,6 +573,8 @@ export async function checkForMissingPaymentMethod() { // Display upgrade banner for new users after 1 week for 30 days export async function checkForNewDevUpgradePro(org: Organization) { + if (resolvedProfile.id !== ProfileMode.CONSOLE) return; + // browser or plan check. if (!browser || org?.billingPlan !== BillingPlan.FREE) return; From 9b5f6ffe3ab19fcff9c6d29bc5c753f35f6c0f42 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 13 Nov 2025 16:42:48 +0530 Subject: [PATCH 02/13] hide: promo alerts and notifications. --- src/lib/stores/database.ts | 6 +++++- src/routes/(console)/bottomAlerts.ts | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib/stores/database.ts b/src/lib/stores/database.ts index 4c93859ce..636345bcb 100644 --- a/src/lib/stores/database.ts +++ b/src/lib/stores/database.ts @@ -7,6 +7,7 @@ import BackupDatabase from '$lib/components/backupDatabaseAlert.svelte'; import { shouldShowNotification } from '$lib/helpers/notifications'; import { isCloud } from '$lib/system'; import { currentPlan } from '$lib/stores/organization'; +import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte'; export const database = derived(page, ($page) => $page.data?.database as Models.Database); @@ -19,7 +20,10 @@ export async function checkForDatabaseBackupPolicies( projectId: string, database: Models.Database ) { - // fast path: return if user dismissed the banner + // fast path: not the valid profile to show this! + if (resolvedProfile.id !== ProfileMode.CONSOLE) return; + + // fast path: return if user dismissed the banner. if (!shouldShowNotification(backupsBannerId)) return; let total = 0; diff --git a/src/routes/(console)/bottomAlerts.ts b/src/routes/(console)/bottomAlerts.ts index b0316aeac..6e732786d 100644 --- a/src/routes/(console)/bottomAlerts.ts +++ b/src/routes/(console)/bottomAlerts.ts @@ -3,6 +3,7 @@ import { isSameDay } from '$lib/helpers/date'; import { type BottomModalAlertItem, showBottomModalAlert } from '$lib/stores/bottom-alerts'; import DbOperatorsDark from '$lib/images/promos/db-operators-dark.png'; import DbOperatorsLight from '$lib/images/promos/db-operators-light.png'; +import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte'; const listOfPromotions: BottomModalAlertItem[] = []; @@ -30,6 +31,9 @@ if (isCloud) { } export function addBottomModalAlerts() { + // fast path: not the valid profile to show this! + if (resolvedProfile.id !== ProfileMode.CONSOLE) return; + listOfPromotions.forEach((promotion) => showBottomModalAlert(promotion)); } From e863ba4696bbcabc366138c40d98a2c4fca27a92 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 14 Nov 2025 18:43:51 +0400 Subject: [PATCH 03/13] Add Platform support and organizationPlatform --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- src/lib/profiles/index.svelte.ts | 4 ++++ src/lib/sdk/billing.ts | 4 +++- src/lib/stores/organization.ts | 3 ++- src/lib/stores/sdk.ts | 6 ++++-- src/routes/(console)/apply-credit/+page.svelte | 1 + src/routes/(console)/create-organization/+page.svelte | 4 +++- .../onboarding/create-organization/+page.svelte | 1 + .../(console)/onboarding/create-project/+page.ts | 1 + src/routes/(public)/functions/deploy/+page.ts | 2 ++ src/routes/(public)/sites/deploy/+page.ts | 4 +++- 12 files changed, 30 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 6ac79cd4e..80aeca8ff 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@ai-sdk/svelte": "^1.1.24", - "@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2752", + "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7", "@appwrite.io/pink-icons": "0.25.0", "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@4472521", "@appwrite.io/pink-legacy": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b680bc162..ec49e3767 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^1.1.24 version: 1.1.24(svelte@5.43.6)(zod@3.24.3) '@appwrite.io/console': - specifier: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2752 - version: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2752 + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7 + version: https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7 '@appwrite.io/pink-icons': specifier: 0.25.0 version: 0.25.0 @@ -272,8 +272,8 @@ packages: '@analytics/type-utils@0.6.4': resolution: {integrity: sha512-Ou1gQxFakOWLcPnbFVsrPb8g1wLLUZYYJXDPjHkG07+5mustGs5yqACx42UAu4A6NszNN6Z5gGxhyH45zPWRxw==} - '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2752': - resolution: {tarball: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2752} + '@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7} version: 1.10.0 '@appwrite.io/pink-icons-svelte@2.0.0-RC.1': @@ -3648,7 +3648,7 @@ snapshots: '@analytics/type-utils@0.6.4': {} - '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@2752': {} + '@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7': {} '@appwrite.io/pink-icons-svelte@2.0.0-RC.1(svelte@5.43.6)': dependencies: diff --git a/src/lib/profiles/index.svelte.ts b/src/lib/profiles/index.svelte.ts index a8d94562d..b1f357fda 100644 --- a/src/lib/profiles/index.svelte.ts +++ b/src/lib/profiles/index.svelte.ts @@ -1,6 +1,7 @@ import { asset, resolve } from '$app/paths'; import type { ResolvedPathname } from '$app/types'; import { PUBLIC_CONSOLE_PROFILE } from '$env/static/public'; +import { Platform } from '@appwrite.io/console'; export const enum ProfileMode { STUDIO = 'studio', @@ -10,6 +11,7 @@ export const enum ProfileMode { export type Profile = { id: ProfileMode; platform: string; + organizationPlatform: Platform; logo: { src: { dark: string; @@ -42,6 +44,7 @@ export type Profile = { export const base: Profile = { id: ProfileMode.CONSOLE, platform: 'Appwrite', + organizationPlatform: Platform.Appwrite, logo: { src: { dark: asset('/images/appwrite-logo-dark.svg'), @@ -79,6 +82,7 @@ export const base: Profile = { export const studio: Profile = { id: ProfileMode.STUDIO, platform: 'Imagine', + organizationPlatform: Platform.Imagine, logo: { src: { dark: asset('/images/imagine-logo-dark.svg'), diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 0361f5910..6e0c69802 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -1,6 +1,6 @@ import type { Tier } from '$lib/stores/billing'; import type { Campaign } from '$lib/stores/campaigns'; -import type { Client, Models } from '@appwrite.io/console'; +import type { Client, Models, Platform } from '@appwrite.io/console'; import type { PaymentMethod } from '@stripe/stripe-js'; import type { Organization, OrganizationError, OrganizationList } from '../stores/organization'; @@ -490,6 +490,7 @@ export class Billing { name: string, billingPlan: string, paymentMethodId: string, + platform: Platform, billingAddressId: string = null, couponId: string = null, invites: Array = [], @@ -500,6 +501,7 @@ export class Billing { const params = { organizationId, name, + platform, billingPlan, paymentMethodId, billingAddressId, diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts index 79f218d8f..d0b49e50f 100644 --- a/src/lib/stores/organization.ts +++ b/src/lib/stores/organization.ts @@ -1,6 +1,6 @@ import { page } from '$app/stores'; import { derived, writable } from 'svelte/store'; -import type { Models } from '@appwrite.io/console'; +import type { Models, Platform } from '@appwrite.io/console'; import type { Tier } from './billing'; import type { Plan } from '$lib/sdk/billing'; @@ -35,6 +35,7 @@ export type Organization = Models.Team> & { status: string; remarks: string; projects: string[]; + platform: Platform; }; export type OrganizationList = { diff --git a/src/lib/stores/sdk.ts b/src/lib/stores/sdk.ts index daeb7ffba..05f9f54db 100644 --- a/src/lib/stores/sdk.ts +++ b/src/lib/stores/sdk.ts @@ -22,7 +22,8 @@ import { Tokens, TablesDB, Domains, - Realtime + Realtime, + Organizations } from '@appwrite.io/console'; import { Billing } from '../sdk/billing'; import { Backups } from '../sdk/backups'; @@ -95,7 +96,8 @@ function createConsoleSdk(client: Client) { sites: new Sites(client), domains: new Domains(client), storage: new Storage(client), - realtime: new Realtime(client) + realtime: new Realtime(client), + organizations: new Organizations(client) }; } diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte index b5bb3926d..b8bc37a60 100644 --- a/src/routes/(console)/apply-credit/+page.svelte +++ b/src/routes/(console)/apply-credit/+page.svelte @@ -135,6 +135,7 @@ name, billingPlan, paymentMethodId, + resolvedProfile.organizationPlatform, null, couponData.code ? couponData.code : null, collaborators, diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 54f6bbb48..15ccaa6f8 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -114,7 +114,8 @@ name, BillingPlan.FREE, null, - null + null, + resolvedProfile.organizationPlatform ); } else { org = await sdk.forConsole.billing.createOrganization( @@ -122,6 +123,7 @@ name, selectedPlan, paymentMethodId, + resolvedProfile.organizationPlatform, null, selectedCoupon?.code, collaborators, diff --git a/src/routes/(console)/onboarding/create-organization/+page.svelte b/src/routes/(console)/onboarding/create-organization/+page.svelte index 9fb1bc26b..11fd6d21e 100644 --- a/src/routes/(console)/onboarding/create-organization/+page.svelte +++ b/src/routes/(console)/onboarding/create-organization/+page.svelte @@ -27,6 +27,7 @@ organizationName, BillingPlan.FREE, null, + resolvedProfile.organizationPlatform, null ); diff --git a/src/routes/(console)/onboarding/create-project/+page.ts b/src/routes/(console)/onboarding/create-project/+page.ts index a12f3f5e0..a39592844 100644 --- a/src/routes/(console)/onboarding/create-project/+page.ts +++ b/src/routes/(console)/onboarding/create-project/+page.ts @@ -46,6 +46,7 @@ export const load: PageLoad = async ({ parent }) => { 'Personal projects', BillingPlan.FREE, null, + resolvedProfile.organizationPlatform, null ); trackEvent(Submit.OrganizationCreate, { diff --git a/src/routes/(public)/functions/deploy/+page.ts b/src/routes/(public)/functions/deploy/+page.ts index 978894e78..a5a61d420 100644 --- a/src/routes/(public)/functions/deploy/+page.ts +++ b/src/routes/(public)/functions/deploy/+page.ts @@ -8,6 +8,7 @@ import type { OrganizationList } from '$lib/stores/organization'; import { redirectTo } from '$routes/store'; import type { PageLoad } from './$types'; import { getRepositoryInfo } from '$lib/helpers/github'; +import { resolvedProfile } from '$lib/profiles/index.svelte'; export const load: PageLoad = async ({ parent, url }) => { const { account } = await parent(); @@ -79,6 +80,7 @@ export const load: PageLoad = async ({ parent, url }) => { 'Personal Projects', BillingPlan.FREE, null, + resolvedProfile.organizationPlatform, null ); } else { diff --git a/src/routes/(public)/sites/deploy/+page.ts b/src/routes/(public)/sites/deploy/+page.ts index 991de1bf5..341eda265 100644 --- a/src/routes/(public)/sites/deploy/+page.ts +++ b/src/routes/(public)/sites/deploy/+page.ts @@ -8,6 +8,7 @@ import type { OrganizationList } from '$lib/stores/organization'; import { redirectTo } from '$routes/store'; import type { PageLoad } from './$types'; import { getRepositoryInfo } from '$lib/helpers/github'; +import { resolvedProfile } from '$lib/profiles/index.svelte'; export const load: PageLoad = async ({ parent, url }) => { const { account } = await parent(); @@ -95,7 +96,8 @@ export const load: PageLoad = async ({ parent, url }) => { ID.unique(), 'Personal Projects', BillingPlan.FREE, - null + null, + resolvedProfile.organizationPlatform ); } else { await sdk.forConsole.teams.create({ From b2a27d42896b835ee3aa21a2f93db2c65166aacd Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 14 Nov 2025 18:45:48 +0400 Subject: [PATCH 04/13] Rename createCsvMigration to createCSVImport --- .../databases/database-[database]/table-[table]/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte index bc556e3ed..5483e87a3 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+page.svelte @@ -107,7 +107,7 @@ try { await sdk .forProject(page.params.region, page.params.project) - .migrations.createCsvMigration({ + .migrations.createCSVImport({ bucketId: file.bucketId, fileId: file.$id, resourceId: `${page.params.database}:${page.params.table}`, From 5d14bfc8c2f88eaea54ad44c4ee8806b53ddc828 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 14 Nov 2025 18:58:01 +0400 Subject: [PATCH 05/13] Add trailing null argument to createOrganization --- src/routes/(console)/create-organization/+page.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 15ccaa6f8..18c9fa66c 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -114,8 +114,8 @@ name, BillingPlan.FREE, null, - null, - resolvedProfile.organizationPlatform + resolvedProfile.organizationPlatform, + null ); } else { org = await sdk.forConsole.billing.createOrganization( From 56f2f6aa07d96a641347e43ddfcd646e55be5d3e Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sun, 16 Nov 2025 21:28:35 -0600 Subject: [PATCH 06/13] chore: add generate-env.sh script --- Dockerfile | 1 + docker/generate-env.sh | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100755 docker/generate-env.sh diff --git a/Dockerfile b/Dockerfile index b7a4c303d..76ef0afd8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,3 +57,4 @@ EXPOSE 80 COPY docker/nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/build /usr/share/nginx/html/console +COPY docker/generate-env.sh /app/generate-env.sh diff --git a/docker/generate-env.sh b/docker/generate-env.sh new file mode 100755 index 000000000..b5de7e335 --- /dev/null +++ b/docker/generate-env.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# Regenerate env.js from runtime PUBLIC_ environment variables + +echo "Regenerating env.js from environment variables..." + +# Build JSON object from PUBLIC_ env vars +env_json="{" +first=true + +for var in $(printenv | grep '^PUBLIC_' | awk -F= '{print $1}' | sort); do + value=$(printenv "$var") + + # Escape special characters for JSON + escaped_value=$(echo "$value" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g') + + if [ "$first" = true ]; then + first=false + else + env_json="$env_json," + fi + + env_json="$env_json\"$var\":\"$escaped_value\"" + echo " $var=$value" +done + +env_json="$env_json}" + +# Write to env.js +# Determine correct path based on script location +if [ -d "./_app" ]; then + # Script is in build/ directory + env_file="./_app/env.js" +elif [ -d "./build/_app" ]; then + # Script is in root or docker/ directory + env_file="./build/_app/env.js" +else + echo "⚠ Error: Cannot find _app directory" + exit 1 +fi + +echo "export const env=$env_json" > "$env_file" + +echo "✓ Generated $env_file" + +# Remove compressed versions (they'll be regenerated by nginx if needed) +rm -f "${env_file}.br" "${env_file}.gz" + +exec "$@" \ No newline at end of file From 7a81f46cda9a871a22fc804998013948e7918424 Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sun, 16 Nov 2025 21:43:38 -0600 Subject: [PATCH 07/13] fix: chmod generate-env.sh --- Dockerfile | 4 ++++ docker/generate-env.sh | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 76ef0afd8..44a6fcae7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,4 +57,8 @@ EXPOSE 80 COPY docker/nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/build /usr/share/nginx/html/console + +# feat-profiles +RUN mkdir -p /app COPY docker/generate-env.sh /app/generate-env.sh +RUN chmod +x /app/generate-env.sh diff --git a/docker/generate-env.sh b/docker/generate-env.sh index b5de7e335..d5ab236da 100755 --- a/docker/generate-env.sh +++ b/docker/generate-env.sh @@ -27,15 +27,17 @@ done env_json="$env_json}" # Write to env.js -# Determine correct path based on script location -if [ -d "./_app" ]; then - # Script is in build/ directory - env_file="./_app/env.js" -elif [ -d "./build/_app" ]; then - # Script is in root or docker/ directory +# Use CONSOLE_BUILD_PATH env var if set, otherwise try common locations +if [ -n "$CONSOLE_BUILD_PATH" ]; then + env_file="$CONSOLE_BUILD_PATH/_app/env.js" +elif [ -f "/usr/share/nginx/html/console/_app/env.js" ]; then + env_file="/usr/share/nginx/html/console/_app/env.js" +elif [ -f "./build/_app/env.js" ]; then env_file="./build/_app/env.js" +elif [ -f "./_app/env.js" ]; then + env_file="./_app/env.js" else - echo "⚠ Error: Cannot find _app directory" + echo "⚠ Error: Cannot find env.js file. Set CONSOLE_BUILD_PATH env var to the build directory." exit 1 fi From 3799b12a2dd74422e29c863bbe597e18739fa28f Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sun, 16 Nov 2025 22:56:24 -0600 Subject: [PATCH 08/13] test: fix generate-env.sh --- docker/generate-env.sh | 45 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/docker/generate-env.sh b/docker/generate-env.sh index d5ab236da..ac83a5781 100755 --- a/docker/generate-env.sh +++ b/docker/generate-env.sh @@ -1,14 +1,30 @@ #!/bin/sh +set -e # Regenerate env.js from runtime PUBLIC_ environment variables +echo "=========================================" echo "Regenerating env.js from environment variables..." +echo "=========================================" + +# Check if any PUBLIC_ env vars exist +public_vars=$(printenv | grep '^PUBLIC_' | awk -F= '{print $1}' | sort) + +if [ -z "$public_vars" ]; then + echo "⚠ WARNING: No PUBLIC_ environment variables found!" + echo "The application may not work correctly." + echo "Expected variables like:" + echo " - PUBLIC_APPWRITE_ENDPOINT" + echo " - PUBLIC_CONSOLE_MODE" + echo " - PUBLIC_CONSOLE_PROFILE" + echo "=========================================" +fi # Build JSON object from PUBLIC_ env vars env_json="{" first=true -for var in $(printenv | grep '^PUBLIC_' | awk -F= '{print $1}' | sort); do +for var in $public_vars; do value=$(printenv "$var") # Escape special characters for JSON @@ -21,7 +37,7 @@ for var in $(printenv | grep '^PUBLIC_' | awk -F= '{print $1}' | sort); do fi env_json="$env_json\"$var\":\"$escaped_value\"" - echo " $var=$value" + echo " ✓ $var=$value" done env_json="$env_json}" @@ -38,14 +54,33 @@ elif [ -f "./_app/env.js" ]; then env_file="./_app/env.js" else echo "⚠ Error: Cannot find env.js file. Set CONSOLE_BUILD_PATH env var to the build directory." + echo "Searched in:" + echo " - /usr/share/nginx/html/console/_app/env.js" + echo " - ./build/_app/env.js" + echo " - ./_app/env.js" exit 1 fi +echo "Writing to: $env_file" + +# Remove old compressed versions FIRST (nginx might serve these instead) +rm -f "${env_file}.br" "${env_file}.gz" +echo " Removed old compressed files" + echo "export const env=$env_json" > "$env_file" -echo "✓ Generated $env_file" +# Verify the file was written +if [ ! -f "$env_file" ]; then + echo "⚠ Error: Failed to write $env_file" + exit 1 +fi -# Remove compressed versions (they'll be regenerated by nginx if needed) -rm -f "${env_file}.br" "${env_file}.gz" +echo "✓ Successfully generated $env_file" +echo "File contents:" +cat "$env_file" + +echo "=========================================" +echo "Starting nginx..." +echo "=========================================" exec "$@" \ No newline at end of file From 88bc820dfb15a558677e8fa4663c6c4f720f3aee Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sun, 16 Nov 2025 23:12:36 -0600 Subject: [PATCH 09/13] dybnamic env --- docker/generate-env.sh | 23 ++++++++++++++++++----- src/lib/profiles/index.svelte.ts | 4 ++-- src/lib/studio/studio-widget.ts | 5 ++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/docker/generate-env.sh b/docker/generate-env.sh index ac83a5781..e39881fb6 100755 --- a/docker/generate-env.sh +++ b/docker/generate-env.sh @@ -62,11 +62,6 @@ else fi echo "Writing to: $env_file" - -# Remove old compressed versions FIRST (nginx might serve these instead) -rm -f "${env_file}.br" "${env_file}.gz" -echo " Removed old compressed files" - echo "export const env=$env_json" > "$env_file" # Verify the file was written @@ -79,6 +74,24 @@ echo "✓ Successfully generated $env_file" echo "File contents:" cat "$env_file" +# NUKE all pre-compressed files so nginx serves fresh content +echo "Nuking all .br and .gz files..." +find /usr/share/nginx/html/console -type f \( -name "*.br" -o -name "*.gz" \) -delete +echo "✓ Nuked all compressed files" + +# Replace hardcoded PUBLIC_ values in JavaScript files +# Vite inlines env vars at build time, so we need to replace them in the built JS +echo "Replacing hardcoded env values in JavaScript files..." +for var in $public_vars; do + value=$(printenv "$var") + echo " Replacing $var in JS files..." + + # Find all .js files and replace the value + # Match pattern: "PUBLIC_VAR":"old_value" or 'PUBLIC_VAR':'old_value' + find /usr/share/nginx/html/console -type f -name "*.js" -exec sed -i "s|\"$var\":\"[^\"]*\"|\"$var\":\"$value\"|g" {} \; +done +echo "✓ Replaced env values in JS files" + echo "=========================================" echo "Starting nginx..." echo "=========================================" diff --git a/src/lib/profiles/index.svelte.ts b/src/lib/profiles/index.svelte.ts index a8d94562d..bcdb8284b 100644 --- a/src/lib/profiles/index.svelte.ts +++ b/src/lib/profiles/index.svelte.ts @@ -1,6 +1,6 @@ import { asset, resolve } from '$app/paths'; import type { ResolvedPathname } from '$app/types'; -import { PUBLIC_CONSOLE_PROFILE } from '$env/static/public'; +import { env } from '$env/dynamic/public'; export const enum ProfileMode { STUDIO = 'studio', @@ -114,7 +114,7 @@ export const studio: Profile = { }; const resolver = $derived(() => { - switch (PUBLIC_CONSOLE_PROFILE) { + switch (env.PUBLIC_CONSOLE_PROFILE) { case 'studio': return studio; default: diff --git a/src/lib/studio/studio-widget.ts b/src/lib/studio/studio-widget.ts index 6ea27537e..055014ddc 100644 --- a/src/lib/studio/studio-widget.ts +++ b/src/lib/studio/studio-widget.ts @@ -1,4 +1,3 @@ -import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_AI_SERVICE_BASE_URL } from '$env/static/public'; import { env } from '$env/dynamic/public'; import { app } from '$lib/stores/app'; import { get } from 'svelte/store'; @@ -283,8 +282,8 @@ export async function initImagine( if (!configInitialized) { initImagineConfig( { - AI_SERVICE_ENDPOINT: PUBLIC_AI_SERVICE_BASE_URL, - APPWRITE_ENDPOINT: PUBLIC_APPWRITE_ENDPOINT, + AI_SERVICE_ENDPOINT: env.PUBLIC_AI_SERVICE_BASE_URL, + APPWRITE_ENDPOINT: env.PUBLIC_APPWRITE_ENDPOINT, APPWRITE_SITES_BASE_URL: '' }, { From 39e37f04c55690f168b3b4c8e87fb547c6f1cbcc Mon Sep 17 00:00:00 2001 From: Ariel Weinberger Date: Sun, 16 Nov 2025 23:14:22 -0600 Subject: [PATCH 10/13] update generate-env.sh --- docker/generate-env.sh | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docker/generate-env.sh b/docker/generate-env.sh index e39881fb6..82cf94071 100755 --- a/docker/generate-env.sh +++ b/docker/generate-env.sh @@ -79,19 +79,6 @@ echo "Nuking all .br and .gz files..." find /usr/share/nginx/html/console -type f \( -name "*.br" -o -name "*.gz" \) -delete echo "✓ Nuked all compressed files" -# Replace hardcoded PUBLIC_ values in JavaScript files -# Vite inlines env vars at build time, so we need to replace them in the built JS -echo "Replacing hardcoded env values in JavaScript files..." -for var in $public_vars; do - value=$(printenv "$var") - echo " Replacing $var in JS files..." - - # Find all .js files and replace the value - # Match pattern: "PUBLIC_VAR":"old_value" or 'PUBLIC_VAR':'old_value' - find /usr/share/nginx/html/console -type f -name "*.js" -exec sed -i "s|\"$var\":\"[^\"]*\"|\"$var\":\"$value\"|g" {} \; -done -echo "✓ Replaced env values in JS files" - echo "=========================================" echo "Starting nginx..." echo "=========================================" From b3d447a47e34384b3c15979f39776733206b2384 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Mon, 17 Nov 2025 14:59:51 +0400 Subject: [PATCH 11/13] Switch to isFreePlan for free plan checks Replace direct BillingPlan.FREE checks with isFreePlan throughout UI and routes to determine the Free tier. --- src/lib/components/archiveProject.svelte | 4 ++-- src/lib/components/backupDatabaseAlert.svelte | 11 ++++++----- src/lib/components/backupRestoreBox.svelte | 3 ++- .../components/billing/alerts/limitReached.svelte | 3 ++- .../billing/alerts/newDevUpgradePro.svelte | 3 ++- src/lib/components/billing/usageRates.svelte | 3 ++- src/lib/components/roles/upgrade.svelte | 3 ++- src/lib/helpers/billing.ts | 11 +++++++++++ src/lib/layout/containerButton.svelte | 12 ++++++------ src/lib/layout/containerHeader.svelte | 9 +++++---- src/lib/layout/shell.svelte | 3 ++- src/lib/profiles/index.svelte.ts | 4 ++++ src/lib/stores/billing.ts | 11 ++++++----- src/routes/(console)/+layout.svelte | 3 ++- .../(console)/account/organizations/+page.svelte | 5 +++-- .../(console)/create-organization/+page.svelte | 9 +++++---- .../onboarding/create-organization/+page.svelte | 2 +- .../(console)/onboarding/create-project/+page.ts | 2 +- .../organization-[organization]/billing/+page.ts | 3 ++- .../billing/availableCredit.svelte | 5 +++-- .../billing/budgetAlert.svelte | 3 ++- .../billing/budgetCap.svelte | 3 ++- .../billing/deleteOrgPayment.svelte | 5 +++-- .../billing/paymentMethods.svelte | 3 ++- .../billing/planSummary.svelte | 3 ++- .../billing/planSummaryOld.svelte | 5 +++-- .../budgetLimitAlert.svelte | 3 ++- .../change-plan/+page.svelte | 11 ++++++----- .../organization-[organization]/change-plan/+page.ts | 5 +++-- .../organization-[organization]/header.svelte | 5 +++-- .../organization-[organization]/members/+page.svelte | 5 +++-- .../usage/[[invoice]]/+page.svelte | 5 +++-- .../usage/[[invoice]]/totalMembers.svelte | 3 ++- .../organization-[organization]/view.svelte | 3 ++- .../databases/create.svelte | 3 ++- .../create-function/(components)/details.svelte | 3 ++- .../settings/updateResourceLimits.svelte | 3 ++- .../settings/smtp/+page.svelte | 5 +++-- .../settings/usage/[[invoice]]/+page.svelte | 5 +++-- .../site-[site]/settings/updateResourceLimits.svelte | 3 ++- .../settings/updateMaxFileSize.svelte | 5 +++-- src/routes/(public)/functions/deploy/+page.ts | 2 +- src/routes/(public)/sites/deploy/+page.ts | 2 +- 43 files changed, 126 insertions(+), 76 deletions(-) create mode 100644 src/lib/helpers/billing.ts diff --git a/src/lib/components/archiveProject.svelte b/src/lib/components/archiveProject.svelte index c7896c991..512b35380 100644 --- a/src/lib/components/archiveProject.svelte +++ b/src/lib/components/archiveProject.svelte @@ -29,7 +29,6 @@ import { getPlatformInfo } from '$lib/helpers/platform'; import { Status, type Models } from '@appwrite.io/console'; import type { ComponentType } from 'svelte'; - import { BillingPlan } from '$lib/constants'; import { goto } from '$app/navigation'; import { base } from '$app/paths'; import { sdk } from '$lib/stores/sdk'; @@ -97,7 +96,7 @@ function isUnarchiveDisabled(): boolean { if (!organization || !currentPlan) return true; - if (organization.billingPlan === BillingPlan.FREE) { + if (isFreePlan(organization.billingPlan)) { const currentProjectCount = organization.projects?.length || 0; const projectLimit = currentPlan.projects || 0; @@ -189,6 +188,7 @@ } import { formatName as formatNameHelper } from '$lib/helpers/string'; + import { isFreePlan } from '$lib/helpers/billing'; function formatName(name: string, limit: number = 19) { return formatNameHelper(name, limit, $isSmallViewport); } diff --git a/src/lib/components/backupDatabaseAlert.svelte b/src/lib/components/backupDatabaseAlert.svelte index 1c2ceed16..78d3ac20a 100644 --- a/src/lib/components/backupDatabaseAlert.svelte +++ b/src/lib/components/backupDatabaseAlert.svelte @@ -10,6 +10,7 @@ import { backupsBannerId, showPolicyAlert } from '$lib/stores/database'; import { IconX } from '@appwrite.io/pink-icons-svelte'; import { Icon } from '@appwrite.io/pink-svelte'; + import { isFreePlan } from '$lib/helpers/billing'; function handleClose() { showPolicyAlert.set(false); @@ -18,14 +19,14 @@ {#if $showPolicyAlert && isCloud && $organization?.$id && page.url.pathname.match(/\/databases\/database-[^/]+$/)} - {@const isFreePlan = $organization?.billingPlan === BillingPlan.FREE} + {@const isFree = isFreePlan($organization?.billingPlan)} - {@const subtitle = isFreePlan + {@const subtitle = isFree ? 'Upgrade your plan to ensure your data stays safe and backed up' : 'Protect your data by quickly adding a backup policy'} - {@const ctaText = isFreePlan ? 'Upgrade plan' : 'Create policy'} - {@const ctaURL = isFreePlan ? $upgradeURL : `${page.url.pathname}/backups`} + {@const ctaText = isFree ? 'Upgrade plan' : 'Create policy'} + {@const ctaURL = isFree ? $upgradeURL : `${page.url.pathname}/backups`} {subtitle} @@ -35,7 +36,7 @@ href={ctaURL} secondary fullWidthMobile - event={isFreePlan ? 'backup_banner_upgrade' : 'backup_banner_add'}> + event={isFree ? 'backup_banner_upgrade' : 'backup_banner_add'}> {ctaText} diff --git a/src/lib/components/backupRestoreBox.svelte b/src/lib/components/backupRestoreBox.svelte index f1de9d3ba..b6b431f0c 100644 --- a/src/lib/components/backupRestoreBox.svelte +++ b/src/lib/components/backupRestoreBox.svelte @@ -13,6 +13,7 @@ import { getProjectId } from '$lib/helpers/project'; import { toLocaleDate } from '$lib/helpers/date'; import { Typography } from '@appwrite.io/pink-svelte'; + import { isFreePlan } from '$lib/helpers/billing'; const backupRestoreItems: { archives: Map; @@ -125,7 +126,7 @@ onMount(() => { // fast path: don't subscribe if org is on a free plan or is self-hosted. - if (isSelfHosted || (isCloud && $organization?.billingPlan === BillingPlan.FREE)) return; + if (isSelfHosted || (isCloud && isFreePlan($organization?.billingPlan))) return; return realtime.forProject(page.params.region, 'console', (response) => { if (!response.channels.includes(`projects.${getProjectId()}`)) return; diff --git a/src/lib/components/billing/alerts/limitReached.svelte b/src/lib/components/billing/alerts/limitReached.svelte index 4885db75e..45258e0ca 100644 --- a/src/lib/components/billing/alerts/limitReached.svelte +++ b/src/lib/components/billing/alerts/limitReached.svelte @@ -4,12 +4,13 @@ import { Click, trackEvent } from '$lib/actions/analytics'; import { BillingPlan } from '$lib/constants'; import { Button } from '$lib/elements/forms'; + import { isFreePlan } from '$lib/helpers/billing'; import { HeaderAlert } from '$lib/layout'; import { hideBillingHeaderRoutes, readOnly, tierToPlan, upgradeURL } from '$lib/stores/billing'; import { organization } from '$lib/stores/organization'; -{#if $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && $readOnly && !hideBillingHeaderRoutes.includes(page.url.pathname)} +{#if $organization?.$id && isFreePlan($organization?.billingPlan) && $readOnly && !hideBillingHeaderRoutes.includes(page.url.pathname)} diff --git a/src/lib/components/billing/alerts/newDevUpgradePro.svelte b/src/lib/components/billing/alerts/newDevUpgradePro.svelte index dfb9caefe..e0e108134 100644 --- a/src/lib/components/billing/alerts/newDevUpgradePro.svelte +++ b/src/lib/components/billing/alerts/newDevUpgradePro.svelte @@ -10,6 +10,7 @@ import { isSmallViewport } from '$lib/stores/viewport'; import { Layout, Typography } from '@appwrite.io/pink-svelte'; import { resolvedProfile } from '$lib/profiles/index.svelte'; + import { isFreePlan } from '$lib/helpers/billing'; let show = true; @@ -24,7 +25,7 @@ } -{#if show && $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && !page.url.pathname.includes(base + '/account')} +{#if show && $organization?.$id && isFreePlan($organization?.billingPlan) && !page.url.pathname.includes(base + '/account')} { diff --git a/src/lib/components/roles/upgrade.svelte b/src/lib/components/roles/upgrade.svelte index b3f15e85b..24a995b57 100644 --- a/src/lib/components/roles/upgrade.svelte +++ b/src/lib/components/roles/upgrade.svelte @@ -6,12 +6,13 @@ import { BillingPlan } from '$lib/constants'; import Button from '$lib/elements/forms/button.svelte'; import { Badge, Layout, Link, Typography } from '@appwrite.io/pink-svelte'; + import { isFreePlan } from '$lib/helpers/billing'; {#if isCloud} - {#if $organization?.billingPlan !== BillingPlan.FREE} + {#if !isFreePlan($organization?.billingPlan)} Roles Owner, Developer, Editor, Analyst and Billing. diff --git a/src/lib/helpers/billing.ts b/src/lib/helpers/billing.ts new file mode 100644 index 000000000..0ade94986 --- /dev/null +++ b/src/lib/helpers/billing.ts @@ -0,0 +1,11 @@ +import { BillingPlan } from '@appwrite.io/console'; + +export function isFreePlan(plan: BillingPlan | string): boolean { + switch (plan) { + case BillingPlan.Imaginebasic: + case BillingPlan.Tier0: + return true; + default: + return false; + } +} diff --git a/src/lib/layout/containerButton.svelte b/src/lib/layout/containerButton.svelte index 53cfc35bf..5b4038f32 100644 --- a/src/lib/layout/containerButton.svelte +++ b/src/lib/layout/containerButton.svelte @@ -1,17 +1,17 @@ - + {!areCreditsSupported ? 'Credits' : 'Available credit'} @@ -172,7 +173,7 @@ {/if} - {#if $organization?.billingPlan === BillingPlan.FREE} + {#if isFreePlan($organization?.billingPlan)}
- {organization?.billingPlan === BillingPlan.FREE + {isFreePlan(organization?.billingPlan) ? 'Upgrade to add more members' : `You've reached the members limit for the ${ tierToPlan(organization?.billingPlan)?.name diff --git a/src/routes/(console)/organization-[organization]/members/+page.svelte b/src/routes/(console)/organization-[organization]/members/+page.svelte index 05c350080..e50434c9d 100644 --- a/src/routes/(console)/organization-[organization]/members/+page.svelte +++ b/src/routes/(console)/organization-[organization]/members/+page.svelte @@ -36,6 +36,7 @@ } from '@appwrite.io/pink-svelte'; import { BillingPlan } from '$lib/constants'; import { tierToPlan } from '$lib/stores/billing'; + import { isFreePlan } from '$lib/helpers/billing'; export let data; @@ -46,7 +47,7 @@ // Calculate if button should be disabled and tooltip should show $: memberCount = data.organizationMembers?.total ?? 0; - $: isFreeWithMembers = $organization?.billingPlan === BillingPlan.FREE && memberCount >= 1; + $: isFreeWithMembers = isFreePlan($organization?.billingPlan) && memberCount >= 1; $: isButtonDisabled = isCloud ? isFreeWithMembers : false; const resend = async (member: Models.Membership) => { @@ -89,7 +90,7 @@
- {$organization?.billingPlan === BillingPlan.FREE + {isFreePlan($organization?.billingPlan) ? 'Upgrade to add more members' : `You've reached the members limit for the ${ tierToPlan($organization?.billingPlan)?.name diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte index a9422df60..706a51102 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -24,6 +24,7 @@ import { IconChartSquareBar, IconInfo } from '@appwrite.io/pink-icons-svelte'; import { onMount } from 'svelte'; import type { UsageProjectInfo } from '../../store'; + import { isFreePlan } from '$lib/helpers/billing'; export let data; @@ -61,7 +62,7 @@
Usage - {#if $organization?.billingPlan === BillingPlan.FREE} + {#if isFreePlan($organization?.billingPlan)} diff --git a/src/routes/(console)/project-[region]-[project]/settings/usage/[[invoice]]/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/usage/[[invoice]]/+page.svelte index 76d4d5e1e..f239a448d 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/usage/[[invoice]]/+page.svelte @@ -15,6 +15,7 @@ import { Accordion, Icon, Layout, Link, Table, Typography } from '@appwrite.io/pink-svelte'; import { IconChartSquareBar } from '@appwrite.io/pink-icons-svelte'; import { page } from '$app/state'; + import { isFreePlan } from '$lib/helpers/billing.js'; export let data; @@ -52,7 +53,7 @@
Usage - {#if $organization?.billingPlan === BillingPlan.FREE} + {#if isFreePlan($organization?.billingPlan)} @@ -73,7 +74,7 @@ on:click={() => ($showUsageRatesModal = true)} >Learn more about plan usage limits.

- {:else if $organization.billingPlan === BillingPlan.FREE} + {:else if isFreePlan($organization?.billingPlan)}

If you exceed the limits of the {plan} plan, services for your projects may be disrupted. - {#if isCloud && $organization.billingPlan === BillingPlan.FREE} + {#if isCloud && isFreePlan($organization?.billingPlan)} Upgrade to Pro or Scale to adjust your CPU and RAM beyond the default. diff --git a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte index 6e8b681dc..ddf543946 100644 --- a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte +++ b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/updateMaxFileSize.svelte @@ -12,6 +12,7 @@ import { updateBucket } from './+page.svelte'; import type { Plan } from '$lib/sdk/billing'; import type { Models } from '@appwrite.io/console'; + import { isFreePlan } from '$lib/helpers/billing'; export let bucket: Models.Bucket; export let currentPlan: Plan | null; @@ -50,11 +51,11 @@ The {currentPlan.name} plan has a maximum upload file size limit of {Math.floor( parseInt(size.value) )}{size.unit}. - {#if $organization?.billingPlan === BillingPlan.FREE} + {#if isFreePlan($organization?.billingPlan)} Upgrade to allow files of a larger size. {/if} - {#if $organization?.billingPlan === BillingPlan.FREE} + {#if isFreePlan($organization?.billingPlan)}