Skip to content
Merged
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
35 changes: 34 additions & 1 deletion src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -451,9 +451,10 @@
/* pink polyfills */
--transition: 0.2s;

/* color hues */
/* color hues (pink by default) */
--color-pink-hue: 343;
--color-secondary-hue: 351;
--brand-accent-rgb: 253 54 110;
--color-red-hue: 3;
--color-orange-hue: 18;
--color-mint-hue: 177;
Expand All @@ -478,6 +479,38 @@
--color-subtle: var(--color-greyscale-850);
}

body.brand-green {
--color-pink-hue: 151;
--color-secondary-hue: 165;
--color-pink-500: hsl(151 72% 38%);
--color-pink-600: hsl(151 66% 32%);
--color-accent: var(--color-pink-500);
--color-accent-darker: var(--color-pink-600);
--brand-accent-rgb: 15 166 95;
}

body.brand-green .light {
--color-pink-hue: 151;
--color-secondary-hue: 165;
--color-pink-500: hsl(151 72% 38%);
--color-pink-600: hsl(151 66% 32%);
--color-accent: var(--color-pink-500);
--color-accent-darker: var(--color-pink-600);
--brand-accent-rgb: 15 166 95;
}

body.brand-pink {
--color-pink-hue: 343;
--color-secondary-hue: 351;
--brand-accent-rgb: 253 54 110;
}

body.brand-pink .light {
--color-pink-hue: 343;
--color-secondary-hue: 351;
--brand-accent-rgb: 253 54 110;
}

.dark {
--color-primary: var(--color-greyscale-100);
--color-secondary: var(--color-greyscale-300);
Expand Down
9 changes: 8 additions & 1 deletion src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
/>
%sveltekit.head%
</head>
<body class="dark group/body antialiased" data-sveltekit-preload-data="hover">
<body class="dark brand-green group/body antialiased" data-sveltekit-preload-data="hover">
<script>
// Theme
const isDocs = window.location.pathname.startsWith('/docs');
Expand All @@ -64,6 +64,13 @@
}
}

// Brand theme
var brandTheme = localStorage.getItem('brand-theme');
if (brandTheme === 'pink' || brandTheme === 'green') {
document.body.classList.remove('brand-pink', 'brand-green');
document.body.classList.add('brand-' + brandTheme);
}

// Progressive enhancement
document.body.dataset.jsEnabled = '';

Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/BlogCta.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
z-index: -1;
background-image: radial-gradient(
ellipse at center,
rgba(253, 54, 110, 0.09),
hsl(var(--web-color-pink-500) / 0.09),
transparent 85%
);
}
Expand Down
21 changes: 20 additions & 1 deletion src/lib/components/FooterNav.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<script lang="ts">
import { slide } from 'svelte/transition';
import { onMount } from 'svelte';
import { trackEvent } from '$lib/actions/analytics';
import { createAccordion, melt } from '@melt-ui/svelte';
export let noBorder = false;
let logoSrc = '/images/logos/appwrite.svg';
const {
elements: { content, heading, item, root, trigger },
Expand Down Expand Up @@ -107,14 +109,31 @@
{ label: 'Security', href: '/docs/advanced/security' }
]
};
const syncBrandLogo = () => {
logoSrc = document.body.classList.contains('brand-pink')
? '/images/logos/appwrite.svg'
: '/images/logos/appwrite-green.svg';
};
onMount(() => {
syncBrandLogo();
const brandObserver = new MutationObserver(syncBrandLogo);
brandObserver.observe(document.body, { attributes: true, attributeFilter: ['class'] });
return () => {
brandObserver.disconnect();
};
});
Comment on lines +113 to +128
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Initial logo may flash before theme class is applied.

The syncBrandLogo() function defaults to the green logo when brand-pink is absent. However, per src/routes/+layout.svelte (lines 109-117), the root layout applies brand-pink/brand-green to document.body in its own onMount, which runs after child components mount. This means on initial render, neither class exists, causing the logo to briefly show green before the MutationObserver corrects it.

Consider checking for both classes explicitly and only switching when the theme is definitively determined:

Proposed fix
 const syncBrandLogo = () => {
-    logoSrc = document.body.classList.contains('brand-pink')
-        ? '/images/logos/appwrite.svg'
-        : '/images/logos/appwrite-green.svg';
+    if (document.body.classList.contains('brand-green')) {
+        logoSrc = '/images/logos/appwrite-green.svg';
+    } else {
+        logoSrc = '/images/logos/appwrite.svg';
+    }
 };

This ensures pink is the default until brand-green is explicitly set.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const syncBrandLogo = () => {
logoSrc = document.body.classList.contains('brand-pink')
? '/images/logos/appwrite.svg'
: '/images/logos/appwrite-green.svg';
};
onMount(() => {
syncBrandLogo();
const brandObserver = new MutationObserver(syncBrandLogo);
brandObserver.observe(document.body, { attributes: true, attributeFilter: ['class'] });
return () => {
brandObserver.disconnect();
};
});
const syncBrandLogo = () => {
if (document.body.classList.contains('brand-green')) {
logoSrc = '/images/logos/appwrite-green.svg';
} else {
logoSrc = '/images/logos/appwrite.svg';
}
};
onMount(() => {
syncBrandLogo();
const brandObserver = new MutationObserver(syncBrandLogo);
brandObserver.observe(document.body, { attributes: true, attributeFilter: ['class'] });
return () => {
brandObserver.disconnect();
};
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/components/FooterNav.svelte` around lines 113 - 128, The
syncBrandLogo logic can flash the wrong logo because the layout sets body
classes after child mounts; update syncBrandLogo to explicitly check for both
'brand-pink' and 'brand-green' (rather than defaulting to green when
'brand-pink' is absent) and set logoSrc only when the theme is determined —
e.g., prefer '/images/logos/appwrite.svg' if
document.body.classList.contains('brand-pink'), else if contains('brand-green')
use '/images/logos/appwrite-green.svg', otherwise leave the current logo or
default to the pink asset; keep the MutationObserver and onMount cleanup
(brandObserver.disconnect) as-is and only change the branch logic in
syncBrandLogo and where logoSrc is initially set.

</script>

<nav
aria-label="Footer"
class="web-footer-nav relative mt-24"
class:web-u-sep-block-start={!noBorder}
>
<img class="web-logo" src="/images/logos/appwrite.svg" alt="appwrite" height="24" width="130" />
<img class="web-logo" src={logoSrc} alt="appwrite" height="24" width="130" />
<ul class="web-footer-nav-main-list" use:melt={$root}>
{#each Object.entries(links) as [title, items]}
<li class="web-footer-nav-main-item web-is-not-mobile">
Expand Down
4 changes: 4 additions & 0 deletions src/lib/components/PreFooter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,8 @@
max-block-size: unset;
filter: blur(100px);
}

:global(body.brand-green .web-pre-footer-bg) {
filter: blur(100px) var(--web-color-image-background-filter);
}
</style>
6 changes: 5 additions & 1 deletion src/lib/components/PromptBanner.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
<div class="ai-banner">
<div class="ai-banner_content">
<div class="ai-banner_title">
<AiPromptIcon class="text-primary" aria-hidden="true" />
<AiPromptIcon class="ai-banner-prompt-icon text-primary" aria-hidden="true" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Rename this styling hook so it doesn't match the generic icon override.

ai-banner-prompt-icon matches .ai-banner [class*='icon'] on Line 272, so the prompt icon gets pulled into the existing color: white rule. That makes text-primary and the new brand-green tinting unreliable.

🔧 Minimal fix
-                <AiPromptIcon class="ai-banner-prompt-icon text-primary" aria-hidden="true" />
+                <AiPromptIcon class="ai-banner-prompt-mark text-primary" aria-hidden="true" />
-    :global(body.brand-green .ai-banner .ai-banner-prompt-icon) {
+    :global(body.brand-green .ai-banner .ai-banner-prompt-mark) {
         filter: var(--web-color-image-accent-filter);
     }

Also applies to: 317-319

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/components/PromptBanner.svelte` at line 86, The prompt icon's class
ai-banner-prompt-icon is matching the generic selector .ai-banner
[class*='icon'] and getting forced white; rename the class on the AiPromptIcon
usage (and the other occurrences around lines 317-319) to a more specific name
(e.g., ai-banner-prompt-icon--unique or ai-banner__prompt-icon) and update any
corresponding CSS if present so it no longer matches [class*='icon']; keep the
utility class text-primary (or brand-green) on the element so color rules apply
correctly after renaming.

<span class="text-primary text-sub-body"
>Use this pre-built prompt to get started faster</span
>
Expand Down Expand Up @@ -313,4 +313,8 @@
padding-right: 10px;
gap: 4px;
}

:global(body.brand-green .ai-banner .ai-banner-prompt-icon) {
filter: var(--web-color-image-accent-filter);
}
</style>
6 changes: 2 additions & 4 deletions src/lib/components/fancy/gradient-text.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
</script>

<span
class={cn(
'-mb-1 block bg-linear-145 from-[#f8a1ba] to-white to-50% bg-clip-text pb-1 text-transparent',
className
)}
class={cn('-mb-1 block bg-clip-text pb-1 text-transparent', className)}
style="background-image: linear-gradient(145deg, color-mix(in srgb, var(--color-accent) 62%, transparent) 0%, #fff 50%);"
{...rest}
>
{@render children()}
Expand Down
27 changes: 20 additions & 7 deletions src/lib/components/layout/site-footer.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script lang="ts">
import { createAccordion, melt } from '@melt-ui/svelte';
import { onMount } from 'svelte';
import { slide } from 'svelte/transition';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Wrong initial logo causes SSR/hydration flash

Same issue as FooterNav.svelte: logoSrc initialises to the pink logo while the default brand theme is now brand-green. The server-rendered HTML will contain the pink logo and it will only switch to green once onMount fires in the browser, creating a visible flash of the wrong logo on every initial page load.

Suggested change
let logoSrc = '/images/logos/appwrite-green.svg';

export let noBorder = false;
let logoSrc = '/images/logos/appwrite.svg';

const {
elements: { content, heading, item, root, trigger },
Expand Down Expand Up @@ -91,6 +93,23 @@
{ label: 'Assets', href: '/assets' }
]
};

const syncBrandLogo = () => {
logoSrc = document.body.classList.contains('brand-pink')
? '/images/logos/appwrite.svg'
: '/images/logos/appwrite-green.svg';
};

onMount(() => {
syncBrandLogo();

const brandObserver = new MutationObserver(syncBrandLogo);
brandObserver.observe(document.body, { attributes: true, attributeFilter: ['class'] });

return () => {
brandObserver.disconnect();
};
});
</script>

<nav
Expand All @@ -99,13 +118,7 @@
class:web-u-sep-block-start={!noBorder}
>
<div class="web-footer-nav container">
<img
class="web-logo"
src="/images/logos/appwrite.svg"
alt="appwrite"
height="24"
width="130"
/>
<img class="web-logo" src={logoSrc} alt="appwrite" height="24" width="130" />
<ul class="web-footer-nav-main-list" use:melt={$root}>
{#each Object.entries(links) as [title, items], i (i)}
<li class="web-footer-nav-main-item web-is-not-mobile">
Expand Down
12 changes: 11 additions & 1 deletion src/lib/components/marketing/open-source-alternative.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,21 @@
<div
class="border-smooth py-10 text-center font-medium last-of-type:border-0 md:border-r md:px-10 md:py-0"
>
<img src={item.icon} alt={item.title} class="mx-auto" />
<img
src={item.icon}
alt={item.title}
class="open-source-alternative-icon mx-auto"
/>
<h3 class="text-sub-body text-primary mt-4 font-medium">{item.title}</h3>
<p class="text-sub-body text-secondary mt-2 font-normal">{item.copy}</p>
</div>
{/each}
</div>
</div>
</div>

<style>
:global(body.brand-green .open-source-alternative-icon) {
filter: var(--web-color-image-accent-filter);
}
</style>
2 changes: 1 addition & 1 deletion src/lib/components/marketing/platforms.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
<img
src={platform.icon}
alt={platform.name}
class="h-8 w-auto grayscale transition-all duration-500 group-hover:grayscale-0"
class="no-brand-filter h-8 w-auto grayscale transition-all duration-500 group-hover:grayscale-0"
/>

<div
Expand Down
44 changes: 41 additions & 3 deletions src/lib/components/product-pages/hero.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
</script>

<div
class="border-smooth box-content flex items-center border-b bg-[url(/images/bgs/mobile-hero.png)] bg-cover bg-bottom px-5 py-12 md:bg-[url(/images/bgs/hero.png)] md:bg-center md:pt-32 md:pb-40 lg:px-8 xl:px-16"
class="product-page-hero-bg border-smooth box-content flex items-center border-b px-5 py-12 md:pt-32 md:pb-40 lg:px-8 xl:px-16"
>
<div class="mx-auto grid max-w-[75rem] items-center gap-16 md:grid-cols-2">
<div class="space-y-8">
Expand Down Expand Up @@ -76,9 +76,47 @@
{/if}
</div>
</div>
<img class={cn({ 'hidden md:block': mobileImage })} src={image.url} alt={image.alt ?? ''} />
<img
class={cn('no-brand-filter', { 'hidden md:block': mobileImage })}
src={image.url}
alt={image.alt ?? ''}
/>
{#if mobileImage}
<img class="block md:hidden" src={mobileImage.url} alt={mobileImage.alt ?? ''} />
<img
class="no-brand-filter block md:hidden"
src={mobileImage.url}
alt={mobileImage.alt ?? ''}
/>
{/if}
</div>
</div>

<style>
.product-page-hero-bg {
position: relative;
isolation: isolate;
}

.product-page-hero-bg::before {
content: '';
position: absolute;
inset: 0;
z-index: -1;
pointer-events: none;
background-image: url('/images/bgs/mobile-hero.png');
background-size: cover;
background-position: bottom;
background-repeat: no-repeat;
}

@media (min-width: 48rem) {
.product-page-hero-bg::before {
background-image: url('/images/bgs/hero.png');
background-position: center;
}
}

:global(body.brand-green .product-page-hero-bg::before) {
filter: var(--web-color-image-background-filter);
}
</style>
14 changes: 13 additions & 1 deletion src/lib/components/product-pages/product-cards.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@
class="web-u-padding-inline-8 web-u-padding-block-end-8 flex flex-col gap-2"
>
<div class="flex items-center gap-2">
<img src={product.icon} alt="auth" width="32" height="32" />
<img
src={product.icon}
alt="auth"
width="32"
height="32"
class="products-explore-card-icon"
/>
<h4 class="text-main-body text-primary">{product.title}</h4>
<span class="web-icon-arrow-right ml-auto" aria-hidden="true"></span>
</div>
Expand All @@ -78,3 +84,9 @@
</div>
</div>
</section>

<style>
:global(body.brand-green .products-brandable .products-explore-card-icon) {
filter: var(--web-color-image-accent-filter) !important;
}
</style>
8 changes: 8 additions & 0 deletions src/lib/components/ui/icon/sprite/sprite.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@
fill-rule="evenodd"
></path>
</symbol>
<symbol id="mongo" stroke="currentColor" viewBox="0 0 120 258">
<path
d="M83.009 28.756 C 72.133 15.909,62.767 2.861,60.854 0.151 C 60.653 -0.050,60.350 -0.050,60.149 0.151 C 58.236 2.861,48.870 15.909,37.994 28.756 C -55.359 147.292,52.697 227.287,52.697 227.287 L 53.603 227.889 C 54.409 240.235,56.423 258.000,56.423 258.000 L 60.451 258.000 L 64.479 258.000 C 64.479 258.000,66.493 240.335,67.299 227.889 L 68.205 227.187 C 68.306 227.187,176.362 147.292,83.009 28.756 M60.451 225.480 C 60.451 225.480,55.617 221.365,54.308 219.257 L 54.308 219.057 L 60.149 89.981 C 60.149 89.580,60.753 89.580,60.753 89.981 L 66.594 219.057 L 66.594 219.257 C 65.285 221.365,60.451 225.480,60.451 225.480 Z"
fill="currentColor"
stroke="none"
fill-rule="evenodd"
></path>
</symbol>
<symbol id="divider-vertical" stroke="currentColor" viewBox="0 0 20 20">
<path
d="M9.750 3.463 C 9.591 3.536,9.520 3.610,9.451 3.775 C 9.406 3.884,9.400 4.585,9.400 10.009 L 9.400 16.119 9.475 16.268 C 9.696 16.705,10.304 16.705,10.525 16.268 L 10.600 16.119 10.599 10.001 C 10.599 4.136,10.596 3.878,10.537 3.750 C 10.464 3.591,10.390 3.520,10.225 3.451 C 10.064 3.384,9.914 3.388,9.750 3.463 "
Expand Down
1 change: 1 addition & 0 deletions src/lib/components/ui/icon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type IconType =
| 'github'
| 'ticket'
| 'sparkle'
| 'mongo'
| 'divider-vertical'
| 'nuxt'
| 'chevron-up'
Expand Down
Loading
Loading