diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte
new file mode 100644
index 000000000..b845b70df
--- /dev/null
+++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte
@@ -0,0 +1,365 @@
+
+
+
+ Deploy {data.repository.name} - Appwrite
+
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.ts b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.ts
new file mode 100644
index 000000000..8b8a33bb3
--- /dev/null
+++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.ts
@@ -0,0 +1,50 @@
+import { sdk } from '$lib/stores/sdk';
+import { redirect } from '@sveltejs/kit';
+import { base } from '$app/paths';
+import type { PageLoad } from './$types';
+import type { Models } from '@appwrite.io/console';
+
+export const load: PageLoad = async ({ url, params }) => {
+ // Get repository URL from query params
+ const repoUrl = url.searchParams.get('repo');
+ if (!repoUrl) {
+ redirect(302, `${base}/project-${params.region}-${params.project}/sites`);
+ }
+
+ // Parse repository information
+ const repoMatch = repoUrl.match(/github\.com[\/:]([^\/]+)\/([^\/\?\s]+)/);
+ if (!repoMatch) {
+ redirect(302, `${base}/project-${params.region}-${params.project}/sites`);
+ }
+
+ const [, owner, repoName] = repoMatch;
+ // Clean repository name (remove .git extension if present)
+ const cleanRepoName = repoName.replace(/\.git$/, '');
+
+ // Get environment variables from query params
+ const envParam = url.searchParams.get('env');
+ const envKeys = envParam ? envParam.split(',').map((key: string) => key.trim()) : [];
+
+ // Try to fetch installations
+ let installations: Models.InstallationList | null = null;
+ try {
+ installations = await sdk.forProject(params.region, params.project).vcs.listInstallations();
+ } catch (error) {
+ // If error, user might not have GitHub connected
+ installations = null;
+ }
+
+ // Fetch frameworks list
+ const frameworks = await sdk.forProject(params.region, params.project).sites.listFrameworks();
+
+ return {
+ repository: {
+ url: repoUrl,
+ owner,
+ name: cleanRepoName
+ },
+ envKeys,
+ installations,
+ frameworks
+ };
+};
diff --git a/src/routes/(public)/deploy/+page.svelte b/src/routes/(public)/deploy/+page.svelte
new file mode 100644
index 000000000..26560c06d
--- /dev/null
+++ b/src/routes/(public)/deploy/+page.svelte
@@ -0,0 +1,263 @@
+
+
+
+ Deploy {data.repository.name} - Appwrite
+
+
+
+
+
+ {#if $app.themeInUse === 'dark'}
+

+ {:else}
+

+ {/if}
+
+
+
+
+
+
+
+
+ Repository
+
+
+
+
+ {data.repository.owner}/{data.repository.name}
+
+
+ {#if data.envKeys.length > 0}
+
+
+
+ Environment Variables Required
+
+
+ {#each data.envKeys as envKey}
+ {envKey}
+ {/each}
+
+
+ {/if}
+
+
+
+
+
+
+
+
+
diff --git a/src/routes/(public)/deploy/+page.ts b/src/routes/(public)/deploy/+page.ts
new file mode 100644
index 000000000..db5148db7
--- /dev/null
+++ b/src/routes/(public)/deploy/+page.ts
@@ -0,0 +1,90 @@
+import { sdk } from '$lib/stores/sdk.js';
+import { redirect } from '@sveltejs/kit';
+import { base } from '$app/paths';
+import { isCloud } from '$lib/system';
+import { BillingPlan } from '$lib/constants';
+import { ID, type Models } from '@appwrite.io/console';
+import type { OrganizationList } from '$lib/stores/organization';
+import { redirectTo } from '$routes/store';
+import type { PageLoad } from './$types';
+
+export const load: PageLoad = async ({ parent, url }) => {
+ const { account } = await parent();
+
+ // Store the full URL for redirect after auth
+ const fullUrl = url.pathname + url.search;
+
+ // Check if user is authenticated
+ if (!account) {
+ redirectTo.set(fullUrl);
+ redirect(302, base + '/login?redirect=' + encodeURIComponent(fullUrl));
+ }
+
+ // Get repository URL from query params
+ const repoUrl = url.searchParams.get('repo');
+ if (!repoUrl) {
+ redirect(302, base + '/');
+ }
+
+ // Parse repository information
+ const repoMatch = repoUrl.match(/github\.com[\/:]([^\/]+)\/([^\/\?\s]+)/);
+ if (!repoMatch) {
+ redirect(302, base + '/');
+ }
+
+ const [, owner, repoName] = repoMatch;
+ // Clean repository name (remove .git extension if present)
+ const cleanRepoName = repoName.replace(/\.git$/, '');
+
+ // Get environment variables from query params
+ const envParam = url.searchParams.get('env');
+ const envKeys = envParam ? envParam.split(',').map((key: string) => key.trim()) : [];
+
+ // Get organizations
+ let organizations: Models.TeamList> | OrganizationList | undefined;
+ if (isCloud) {
+ organizations = await sdk.forConsole.billing.listOrganization();
+ } else {
+ organizations = await sdk.forConsole.teams.list();
+ }
+
+ // Create default organization if none exists - matches console's onboarding behavior
+ if (!organizations?.total) {
+ let org = null;
+ try {
+ if (isCloud) {
+ org = await sdk.forConsole.billing.createOrganization(
+ ID.unique(),
+ 'Personal Projects',
+ BillingPlan.FREE,
+ null,
+ null
+ );
+ } else {
+ org = await sdk.forConsole.teams.create(ID.unique(), 'Personal Projects');
+ }
+
+ // Refetch organizations after creation
+ if (isCloud) {
+ organizations = await sdk.forConsole.billing.listOrganization();
+ } else {
+ organizations = await sdk.forConsole.teams.list();
+ }
+ } catch (e) {
+ // If organization creation fails, still redirect to deploy page
+ // The page will handle showing an error
+ console.error('Failed to create default organization:', e);
+ }
+ }
+
+ return {
+ account,
+ organizations,
+ repository: {
+ url: repoUrl,
+ owner,
+ name: cleanRepoName
+ },
+ envKeys
+ };
+};