Merge branch 'main' into add-mid-content-cta
@@ -35,12 +35,12 @@
|
||||
Products: [
|
||||
{ label: 'Auth', href: '/products/auth' },
|
||||
{ label: 'Databases', href: '/docs/products/databases' },
|
||||
{ label: 'Storage', href: '/products/storage' },
|
||||
{ label: 'Functions', href: '/products/functions' },
|
||||
{ label: 'Messaging', href: '/products/messaging' },
|
||||
{ label: 'Storage', href: '/products/storage' },
|
||||
{ label: 'Realtime', href: '/docs/apis/realtime' },
|
||||
{ label: 'Network', href: '/docs/products/network' },
|
||||
{ label: 'Hosting', href: '/docs/products/sites' }
|
||||
{ label: 'Hosting', href: '/docs/products/sites' },
|
||||
{ label: 'Network', href: '/docs/products/network' }
|
||||
],
|
||||
Learn: [
|
||||
{ label: 'Blog', href: '/blog' },
|
||||
|
||||
@@ -43,17 +43,17 @@
|
||||
description: 'Set up a full-functioning messaging service.',
|
||||
icon: '/images/icons/illustrated/dark/messaging.png'
|
||||
},
|
||||
{
|
||||
name: 'Sites',
|
||||
href: '/products/sites',
|
||||
description: 'The open-source Vercel alternative.',
|
||||
icon: '/images/icons/illustrated/dark/sites.png'
|
||||
},
|
||||
{
|
||||
name: 'Realtime',
|
||||
href: '/docs/apis/realtime',
|
||||
description: 'Subscribe and react to any event.',
|
||||
icon: '/images/icons/illustrated/dark/realtime.png'
|
||||
},
|
||||
{
|
||||
name: 'Sites',
|
||||
href: '/products/sites',
|
||||
description: 'The open-source Vercel alternative.',
|
||||
icon: '/images/icons/illustrated/dark/sites.png'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -33,6 +33,11 @@
|
||||
name: 'Realtime',
|
||||
href: '/docs/apis/realtime',
|
||||
description: 'Subscribe and react to any event.'
|
||||
},
|
||||
{
|
||||
name: 'Sites',
|
||||
href: '/products/sites',
|
||||
description: 'The open-source Vercel alternative.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
@@ -33,6 +33,11 @@
|
||||
name: 'Realtime',
|
||||
href: '/docs/apis/realtime',
|
||||
description: 'Subscribe and react to any event.'
|
||||
},
|
||||
{
|
||||
name: 'Sites',
|
||||
href: '/products',
|
||||
description: 'The open-source Vercel alternative.'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -34,10 +34,11 @@
|
||||
Products: [
|
||||
{ label: 'Auth', href: '/products/auth' },
|
||||
{ label: 'Databases', href: '/docs/products/databases' },
|
||||
{ label: 'Storage', href: '/products/storage' },
|
||||
{ label: 'Functions', href: '/products/functions' },
|
||||
{ label: 'Messaging', href: '/products/messaging' },
|
||||
{ label: 'Storage', href: '/products/storage' },
|
||||
{ label: 'Realtime', href: '/docs/apis/realtime' }
|
||||
{ label: 'Realtime', href: '/docs/apis/realtime' },
|
||||
{ label: 'Sites', href: '/products/sites' }
|
||||
],
|
||||
Learn: [
|
||||
{ label: 'Docs', href: '/docs' },
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/state';
|
||||
|
||||
const allProducts = {
|
||||
messaging: {
|
||||
title: 'Messaging',
|
||||
description: 'Use Appwrite messaging to send email, SMS, and push notifications.',
|
||||
icon: '/images/icons/illustrated/dark/messaging.png',
|
||||
url: '/products/messaging'
|
||||
},
|
||||
auth: {
|
||||
title: 'Auth',
|
||||
description: 'Build secure authentication and manage your users.',
|
||||
icon: '/images/icons/illustrated/dark/auth.png',
|
||||
url: '/products/auth'
|
||||
},
|
||||
functions: {
|
||||
title: 'Functions',
|
||||
description: ' Scale big and unlock limitless potential with Appwrite functions.',
|
||||
icon: '/images/icons/illustrated/dark/functions.png',
|
||||
url: '/products/functions'
|
||||
},
|
||||
databases: {
|
||||
title: 'Databases',
|
||||
description: 'Store and query structured data, ensuring scalable storage.',
|
||||
@@ -32,17 +19,30 @@
|
||||
icon: '/images/icons/illustrated/dark/storage.png',
|
||||
url: '/products/storage'
|
||||
},
|
||||
sites: {
|
||||
title: 'Sites',
|
||||
description: 'The open-source Vercel alternative.',
|
||||
icon: '/images/icons/illustrated/dark/sites.png',
|
||||
url: '/products/sites'
|
||||
functions: {
|
||||
title: 'Functions',
|
||||
description: ' Scale big and unlock limitless potential with Appwrite functions.',
|
||||
icon: '/images/icons/illustrated/dark/functions.png',
|
||||
url: '/products/functions'
|
||||
},
|
||||
|
||||
messaging: {
|
||||
title: 'Messaging',
|
||||
description: 'Use Appwrite messaging to send email, SMS, and push notifications.',
|
||||
icon: '/images/icons/illustrated/dark/messaging.png',
|
||||
url: '/products/messaging'
|
||||
},
|
||||
realtime: {
|
||||
title: 'Realtime',
|
||||
description: 'Subscribe and react to any event using the Realtime API.',
|
||||
icon: '/images/icons/illustrated/dark/realtime.png',
|
||||
url: '/docs/realtime'
|
||||
},
|
||||
sites: {
|
||||
title: 'Sites',
|
||||
description: 'The open-source Vercel alternative.',
|
||||
icon: '/images/icons/illustrated/dark/sites.png',
|
||||
url: '/products/sites'
|
||||
}
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -59,13 +59,13 @@ export type SocialShareOption = {
|
||||
type: 'link' | 'copy';
|
||||
};
|
||||
|
||||
export type IntegrationCategory = {
|
||||
export type SearchableCategory = {
|
||||
slug: string;
|
||||
heading: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export const integrationCategoryDescriptions: IntegrationCategory[] = [
|
||||
export const integrationCategoryDescriptions: SearchableCategory[] = [
|
||||
{
|
||||
slug: 'ai',
|
||||
heading: 'AI',
|
||||
@@ -118,6 +118,14 @@ export const integrationCategoryDescriptions: IntegrationCategory[] = [
|
||||
}
|
||||
];
|
||||
|
||||
export const partnerCategoryDescriptions: SearchableCategory[] = [
|
||||
{
|
||||
slug: 'agency',
|
||||
heading: 'Agency',
|
||||
description: 'Agencies that build software for their clients using Appwrite'
|
||||
}
|
||||
];
|
||||
|
||||
export const socialSharingOptions: Array<SocialShareOption> = [
|
||||
{
|
||||
icon: 'web-icon-x',
|
||||
|
||||
@@ -17,6 +17,33 @@ const BillingPlan = {
|
||||
SCALE: 'tier-2'
|
||||
} as const;
|
||||
|
||||
const ASCII_ART = `
|
||||
_ _ _
|
||||
/_\\ _ __ _ ____ ___ __(_) |_ ___
|
||||
//_\\\\| '_ \\| '_ \\ \\ /\\ / / '__| | __/ _ \\
|
||||
/ _ \\ |_) | |_) \\ V V /| | | | || __/
|
||||
\\_/ \\_/ .__/| .__/ \\_/\\_/ |_| |_|\\__\\___|
|
||||
|_| |_|
|
||||
`;
|
||||
|
||||
export function displayHiringMessage() {
|
||||
if (browser) {
|
||||
console.log('%c' + ASCII_ART, 'font-family: monospace; white-space: pre; color: #fd366e;');
|
||||
console.log(
|
||||
'%cWe are hiring!',
|
||||
'font-family: Aeonik Pro, -apple-system, BlinkMacSystemFont, sans-serif; font-size: 20px; font-weight: bold;'
|
||||
);
|
||||
console.log(
|
||||
'%cJoin us in building the open-source, all-in-one development platform',
|
||||
'font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif; font-size: 14px;'
|
||||
);
|
||||
console.log(
|
||||
'%cCheck out our open positions at https://appwrite.io/careers',
|
||||
'font-family: monospace; color: #666;'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function createSource(
|
||||
ref: string | null,
|
||||
referrer: string | null,
|
||||
|
||||
172
src/markdoc/layouts/Partner.svelte
Normal file
@@ -0,0 +1,172 @@
|
||||
<script lang="ts">
|
||||
import FooterNav from '$lib/components/FooterNav.svelte';
|
||||
import MainFooter from '$lib/components/MainFooter.svelte';
|
||||
import { Main } from '$lib/layouts';
|
||||
import { DEFAULT_HOST } from '$lib/utils/metadata';
|
||||
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import type { Partner } from '$routes/partners/catalog/+page';
|
||||
import ContactPartner from '$routes/partners/catalog/(components)/contact-partner.svelte';
|
||||
|
||||
export let title: Partner['title'];
|
||||
export let partnerLevel: Partner['partnerLevel'];
|
||||
export let category: Partner['category'];
|
||||
export let description: Partner['description'];
|
||||
export let cover: Partner['cover'];
|
||||
export let capabilities: Partner['capabilities'];
|
||||
export let frameworks: Partner['frameworks'];
|
||||
export let regions: Partner['regions'];
|
||||
export let languages: Partner['languages'];
|
||||
export let website: Partner['website'];
|
||||
|
||||
const ogImage = DEFAULT_HOST + cover;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<!-- Titles -->
|
||||
<title>{title}</title>
|
||||
<meta property="og:title" content={title} />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<!-- Description -->
|
||||
<meta name="description" content={description} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<!-- Image -->
|
||||
<meta property="og:image" content={ogImage} />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta name="twitter:image" content={ogImage} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</svelte:head>
|
||||
|
||||
<Main>
|
||||
<div
|
||||
class={classNames(
|
||||
'grid-bg border-smooth relative flex items-center border-b px-5 py-28 lg:px-8 xl:px-16',
|
||||
'before:from-accent/20 before:absolute before:inset-0 before:-z-1 before:bg-linear-to-tr before:via-transparent before:via-40% before:to-transparent'
|
||||
)}
|
||||
>
|
||||
<div class="relative container w-full pb-0">
|
||||
<div class="flex flex-col gap-7">
|
||||
<a href="/partners" class="text-caption text-primary group flex gap-2">
|
||||
<span class="web-icon-arrow-left transition group-hover:-translate-x-1" />
|
||||
Back to Partners Catalog
|
||||
</a>
|
||||
<h1 class="text-headline font-aeonik-pro text-primary">{title}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="py-10">
|
||||
<div class="container">
|
||||
<article class="flex flex-col gap-10 md:gap-14">
|
||||
<div class="grid grid-cols-1 gap-10 md:grid-cols-12 md:gap-x-14">
|
||||
<div class="md:col-span-7">
|
||||
<div class="web-article">
|
||||
<div class="web-article-content">
|
||||
<slot />
|
||||
</div>
|
||||
<ContactPartner />
|
||||
</div>
|
||||
</div>
|
||||
<div class="md:col-span-5">
|
||||
<h2 class="text-label text-primary font-aeonik-pro">About {title}</h2>
|
||||
<dl class="divide-smooth sticky top-32 mt-10 flex flex-col gap-7 divide-y">
|
||||
<div class="flex flex-col justify-between gap-7 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Frameworks
|
||||
</dt>
|
||||
<dd class="flex flex-wrap gap-2">
|
||||
{#each frameworks as framework}
|
||||
<div
|
||||
class="text-primary text-caption bg-smooth rounded-full px-3 py-1"
|
||||
>
|
||||
{framework}
|
||||
</div>
|
||||
{/each}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-between gap-7 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Capabilities
|
||||
</dt>
|
||||
<dd class="flex flex-wrap gap-2">
|
||||
{#each capabilities as capability}
|
||||
<div
|
||||
class="text-primary text-caption bg-smooth rounded-full px-3 py-1"
|
||||
>
|
||||
{capability}
|
||||
</div>
|
||||
{/each}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-7 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Category
|
||||
</dt>
|
||||
<dd class="text-primary text-caption">{category}</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-7 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Website
|
||||
</dt>
|
||||
<dd
|
||||
class="text-primary text-caption font-medium underline underline-offset-4"
|
||||
>
|
||||
{website}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-7 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Partner Level
|
||||
</dt>
|
||||
<dd>
|
||||
<div
|
||||
class="text-primary text-caption rounded bg-white/24 px-2 py-0.5"
|
||||
>
|
||||
{partnerLevel}
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between gap-8 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Regions
|
||||
</dt>
|
||||
<dd class="text-primary text-caption">
|
||||
{regions.join(', ')}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-between gap-7 pb-7">
|
||||
<dt class="text-micro font-aeonik-fono tracking-loose uppercase">
|
||||
Languages
|
||||
</dt>
|
||||
<dd class="flex flex-wrap gap-2">
|
||||
{#each languages as language}
|
||||
<div
|
||||
class="text-primary text-caption bg-smooth rounded-full px-3 py-1"
|
||||
>
|
||||
{language}
|
||||
</div>
|
||||
{/each}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-12 overflow-hidden py-10">
|
||||
<div class="container">
|
||||
<FooterNav />
|
||||
<MainFooter />
|
||||
</div>
|
||||
</div>
|
||||
</Main>
|
||||
@@ -1,4 +1,4 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
import Auth from './(animations)/auth.svelte';
|
||||
import Databases from './(animations)/databases.svelte';
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
import { saveReferrerAndUtmSource } from '$lib/utils/utm';
|
||||
import { Sprite } from '$lib/components/ui/icon/sprite';
|
||||
import { setTheme, ThemeProvider } from '$lib/providers/theme';
|
||||
import { displayHiringMessage } from '$lib/utils/console';
|
||||
|
||||
function applyTheme(theme: Theme) {
|
||||
const resolvedTheme = theme === 'system' ? getSystemTheme() : theme;
|
||||
@@ -71,6 +72,7 @@
|
||||
const tracked = new Set();
|
||||
|
||||
onMount(() => {
|
||||
displayHiringMessage();
|
||||
saveReferrerAndUtmSource(page.url);
|
||||
|
||||
const initialTheme = page.route.id?.startsWith('/docs') ? getPreferredTheme() : 'dark';
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
layout: post
|
||||
title: "Rethinking SaaS Authentication: Build secure, scalable experiences with Appwrite"
|
||||
description: Learn the essentials of secure, scalable SaaS authentication with modern best practices.
|
||||
date: 2025-06-19
|
||||
cover: /images/blog/rethinking-saas-authentication/cover.png
|
||||
timeToRead: 6
|
||||
author: laura-du-ry
|
||||
callToAction: true
|
||||
unlisted: true
|
||||
category: product
|
||||
---
|
||||
|
||||
In SaaS, authentication isn’t just a technical requirement—it's a key pillar of product quality, security, and growth. Whether you're guiding new users through onboarding, handling multi-tenant environments, or protecting APIs, how you manage identity can make or break customer trust and loyalty.
|
||||
|
||||
In this guide, we’ll walk through the fundamentals of effective SaaS authentication, the core challenges every SaaS team faces, modern techniques that optimize both security and user experience, and how Appwrite helps you deliver it all—faster.
|
||||
|
||||
# What SaaS authentication really means
|
||||
|
||||
[Authentication](/products/auth) verifies a user’s identity and grants access to data, services, or functionality. In SaaS, it must make user access effortless while ensuring security across distributed, cloud-native environments.
|
||||
|
||||
A streamlined login flow keeps users engaged, but as identity attacks rise, strong security practices are now critical for protecting trust and ensuring your platform’s resilience.
|
||||
|
||||
# Key SaaS authentication challenges
|
||||
|
||||
## Finding the Balance: Security vs. User Friction
|
||||
|
||||
Security measures like MFA, device verification, and session management often add steps to login flows. If not handled thoughtfully, they frustrate users.
|
||||
|
||||
Technologies like **Single Sign-On (SSO)** help bridge this gap—offering both enhanced [security](/docs/products/auth/security) and smoother user experiences.
|
||||
|
||||
Take a look at our [developer’s guide to user authentication](/blog/post/guide-to-user-authentication) for more in-depth insights.
|
||||
|
||||
{% call_to_action title="Customer identity without the hassle" description="Add secure authentication for your users in just a couple of minutes." point1="Built-in security and compliance" point2="Multi-factor authentication" point3="Custom roles and permissions" point4="Session control and management" cta="Request a demo" url="https://appwrite.io/contact-us/enterprise" /%}
|
||||
|
||||
## Managing multi-tenant complexity
|
||||
|
||||
Multi-tenancy is the backbone of SaaS, but it complicates identity management. Different tenants may need custom sign-in flows, roles, or [Identity Provider (IdP)](/blog/post/understanding-idp-vs-sp-initiated-sso) setups.
|
||||
|
||||
Appwrite’s **Teams API** provides per-tenant identity management—supporting isolation, security, and flexibility at scale.
|
||||
|
||||
## Strengthening MFA without disrupting UX
|
||||
|
||||
Multi-factor authentication is essential for SaaS security, but weak MFA implementations (like SMS OTPs) are vulnerable. Phishing-resistant methods like **TOTP apps** and **passkeys** are the new standard.
|
||||
|
||||
With Appwrite, it's easy to enable TOTP 2FA and customize how and when users are challenged—balancing safety with usability.
|
||||
|
||||
## Scaling authentication seamlessly
|
||||
|
||||
As your SaaS user base grows, authentication performance becomes mission-critical. Slow logins, session errors, or outages will frustrate users and damage your reputation.
|
||||
|
||||
Appwrite’s architecture is designed for high scalability, keeping authentication fast and reliable, even under heavy load.
|
||||
|
||||
## Meeting compliance and privacy expectations
|
||||
|
||||
Regulations like [GDPR](/docs/advanced/security/gdpr), [HIPAA](/docs/advanced/security/hipaa), and [SOC 2](/docs/advanced/security/soc2) demand strict user data protection and auditability.
|
||||
|
||||
Appwrite’s built-in encryption, access controls, and regional hosting options make compliance simpler, helping you earn and maintain client trust.
|
||||
|
||||
# Proven SaaS authentication strategies
|
||||
|
||||
## Go passwordless
|
||||
|
||||
Traditional passwords are painful and risky. Passwordless options like Magic URLs dramatically improve both security and user experience.
|
||||
|
||||
Appwrite’s Magic URL feature lets users log in securely with a single click—no passwords, no friction. Learn more about [Magic URL](/docs/products/auth/magic-url).
|
||||
|
||||
## Offer Single Sign-On (SSO)
|
||||
|
||||
Enterprise SaaS customers expect SSO integration with providers like Google Workspace, Okta, and Azure AD.
|
||||
|
||||
Appwrite supports OAuth out of the box, and flexible extensions let you connect to custom or third-party IdPs easily.
|
||||
|
||||
## Embrace adaptive MFA
|
||||
|
||||
Static MFA prompts can annoy users. Adaptive MFA adjusts authentication requirements based on risk signals—like device reputation or location.
|
||||
|
||||
Appwrite enables dynamic security flows with Cloud Functions and custom verification logic. Want to add MFA to your app? We've got you covered in the [docs](/docs/products/auth/mfa).
|
||||
|
||||
## Prioritize secure API access
|
||||
|
||||
APIs are core to SaaS platforms, but they're also prime targets for attacks. Secure your APIs with short-lived tokens, proper JWT signing, and strict audience validation.
|
||||
|
||||
Appwrite’s secure session and token handling features make it easier to protect your backend services.
|
||||
|
||||
## Empower tenants with delegated management
|
||||
|
||||
Your customers want control. Appwrite’s Teams API lets tenant admins manage users, permissions, and access policies themselves, reducing your operational load and improving client satisfaction.
|
||||
|
||||
# Choosing the right approach to SaaS authentication
|
||||
|
||||
When building your auth stack, ask:
|
||||
|
||||
- **Is it flexible enough?** Support for OAuth, SSO, magic links, MFA, and multi-tenant variations.
|
||||
- **Is it secure enough?** Encryption, secure tokens, ACLs, and strong MFA are non-negotiables.
|
||||
- **How fast can we ship?** Good SDKs, clear APIs, and customization options matter.
|
||||
- **Will it scale?** Performance under load and future-proofing are essential.
|
||||
- **Can we stay compliant?** Built-in privacy controls save time and headaches.
|
||||
|
||||
Appwrite checks every box, giving you a robust, developer-friendly [authentication platform](/products/auth) without the heavyweight complexity.
|
||||
|
||||
# Ship SaaS authentication smarter with Appwrite
|
||||
|
||||
Authentication isn’t just about login screens, it’s a foundation for SaaS product success. Strong auth builds trust, supports scale, and enables faster growth.
|
||||
|
||||
With Appwrite, you can launch secure, scalable, and flexible authentication flows—and customize them to fit your users' exact needs.
|
||||
|
||||
Ready to simplify your SaaS authentication journey? [Deploy Appwrite](https://cloud.appwrite.io/) and start building your future, today.
|
||||
|
||||
# Further reading
|
||||
- [Appwrite Authentication docs](/docs/products/auth)
|
||||
- [Setup magic link authentication](https://youtu.be/mqgNmx9YE5w?si=FsCD88afY4Cu_Bdl)
|
||||
- [Appwrite Authentication quick-start doc](/docs/products/auth/quick-start)
|
||||
|
||||
232
src/routes/blog/post/startup-incubator-guide/+page.markdoc
Normal file
@@ -0,0 +1,232 @@
|
||||
---
|
||||
layout: post
|
||||
title: "What is an Incubator? A guide for tech startups"
|
||||
description: Explore what startup incubators really offer, their pros and cons, and a list of top programs to consider.
|
||||
cover: /images/blog/startup-incubator-guide/cover.png
|
||||
timeToRead: 10
|
||||
date: 2025-06-18
|
||||
author: veeresh-mulge
|
||||
callToAction: true
|
||||
unlisted: true
|
||||
category: product
|
||||
---
|
||||
|
||||
Building a tech startup is hard, especially for first-time founders. You're expected to move fast, ship a great product, find early users, and raise money. All at once, with limited resources and almost no room for error.
|
||||
|
||||
That's where startup incubators come in. Designed to make those first 6–12 months less chaotic and more productive. Whether you're a solo technical founder or a team still figuring things out, a good incubator can be your multiplier.
|
||||
|
||||
In this guide, we will learn about incubators, their benefits, and what to look for in an Incubator.
|
||||
|
||||
# What is a Startup Incubator?
|
||||
|
||||
Startup Incubators are specialized organizations designed to support early-stage startups by providing them with the tools, guidance, and environment they need to get off the ground. Think of them as a launchpad that can help your startup go from initial idea or prototype to a functional business.
|
||||
|
||||
They typically offer a mix of:
|
||||
|
||||
- **Mentorship** → Guidance from experienced entrepreneurs, investors, and domain experts who've built and scaled startups.
|
||||
- **Resources →** Access to office space, developer credits, product tools, and legal or accounting support to reduce operational overhead.
|
||||
- **Networking →** Connections with investors, fellow founders, alumni, and other key players in the startup ecosystem.
|
||||
- **Workshops and sessions →** Sessions on building an MVP, fundraising, GTM strategy, hiring, pitching, and more.
|
||||
- **Time-bound programs →** Time-bound formats (typically 3 to 12 months) with regular check-ins, progress tracking, and demo days to showcase your startup.
|
||||
|
||||
# How do they work?
|
||||
|
||||
Startup incubators support companies in the earliest stages, often before there's a product, revenue, or even a finalized business model. Their goal is to help founders go from a concept to a structured, validated business. Here’s how Startup Incubators work:
|
||||
|
||||
## 1. Selection
|
||||
|
||||
Incubators typically run application cycles where founders pitch their [startup ideas](/blog/post/startups-ideas-for-developers-2024). The selection process looks for founder-market fit, technical potential, clarity of vision, and the problem being solved. Some programs are open to solo founders, while others prefer early teams.
|
||||
|
||||
## 2. Pre-Incubation
|
||||
|
||||
In this phase, the incubator helps founders sharpen their core assumptions, define the product vision, understand the market, and build a business plan. For tech startups, this often includes guidance on choosing the right stack, validating technical feasibility, mapping user personas, and leveraging cloud credits or dev tool support to set up the foundation efficiently.
|
||||
|
||||
## 3. Incubation
|
||||
|
||||
Now it's time to build. You start developing your [MVP](/blog/post/how-can-you-rapidly-build-an-mvp-for-your-startup), setting up early marketing, talking to users, and preparing for growth. You may attend workshops, peer feedback sessions, and 1:1s with mentors. Incubators also help with early hiring plans, GTM strategy, and investor readiness.
|
||||
|
||||
## 4. Post-Incubation
|
||||
|
||||
Once the program ends, many incubators offer ongoing support through alumni networks, investor connections, or optional follow-on programs. Some provide co-investment opportunities or introductions to accelerators and VCs.
|
||||
|
||||
{% call_to_action title="Build your startup with Appwrite" description="Join the Startups program and benefit from Appwrite’s all-in-one development platform to build, deploy, and scale your products." point1="Ship faster" point2="Cloud credits and discounts" point3="Priority support" point4="Managed cloud solution" cta="Apply now" url="/startups" /%}
|
||||
|
||||
# Benefits of a Startup Incubator
|
||||
|
||||
Startup Incubators can add value to an early-stage startup in many shapes and forms. Here are some top benefits of being part of an Incubator:
|
||||
|
||||
- **Office space:** Many incubators provide access to shared office spaces, which can help small companies save on rent and offer unique networking opportunities to other startups.
|
||||
- **Mentorship:** The biggest value in an incubator is in the people, mentors, and partners. You get direct access to founders and mentors who've built successful companies in the past to help you make smart product, hiring, and business decisions.
|
||||
- **Seed funding:** Incubators can assist you by connecting with potential VCs for seed funding that can help you grow and take your startup to the next level.
|
||||
|
||||
# Drawbacks of a Startup Incubator
|
||||
|
||||
While there are plenty of benefits, there are some drawbacks to consider. Here are a couple of them:
|
||||
|
||||
- **Equity trade:** Many incubators trade for equity in exchange for access to resources and expertise they offer, which may not make sense if you're already well-resourced or further along in your startup journey.
|
||||
- **Time commitment:** Founders are required to commit to the program, which can run over several months with multiple sessions, check-ins, or deliverables. Yes, you will learn a lot, but you'll also spend a fair amount of time doing it.
|
||||
- **Fit and alignment:** There's no one-size-fits-all incubator. Many are built for specific industries, markets, or stages. You can waste your time, equity, or money by joining the wrong incubator.
|
||||
|
||||
# Top 10 Startup Incubators in the world
|
||||
|
||||
## 1. [Station F](https://stationf.co/)
|
||||
|
||||
Widely regarded as the world's largest startup incubator campus, hosting over 1,000 startups and 30 different programs under one roof. Station F offers everything from coworking space and on-site housing to 600+ annual events and workshops, providing a comprehensive ecosystem for international early-stage ventures.
|
||||
|
||||
**Location**: Paris, France
|
||||
|
||||
**Industries:** Broad tech focus (from general digital tech to climate tech)
|
||||
|
||||
**Top startups incubated:** Hugging Face, Alan
|
||||
|
||||

|
||||
|
||||
|
||||
## 2. [Plug and Play Tech Center](https://www.plugandplaytechcenter.com/)
|
||||
|
||||
An early Silicon Valley incubator that famously made seed investments in Google and PayPal, Plug & Play now runs a no-equity "open innovation" platform connecting startups to hundreds of corporate partners worldwide. It offers continuous mentorship, coworking space, and business development programs without the typical demo-day accelerator format.
|
||||
|
||||
**Location**: Sunnyvale, USA – with 35+ global offices
|
||||
|
||||
**Industries:** Runs vertical programs in AI, IT, SaaS, retail, energy, fintech, insurtech, health, mobility, and more
|
||||
|
||||
**Top startups incubated:** PayPal, Dropbox
|
||||
|
||||

|
||||
|
||||
|
||||
## 3. [DMZ](https://dmz.torontomu.ca/)
|
||||
|
||||
DMZ is a tech incubator that was ranked the [#1 university-based incubator](https://www.notion.so/What-is-an-incubator-A-guide-for-tech-startups-210fb53fe82d804b8227dc53f88ccca3?pvs=21) in the world (tied with SETsquared) in 2018. It focuses on helping pre-seed and early-stage startups through 18-month programs with mentorship and resources, and its companies have raised over $400 M and created 3,000+ jobs since inception
|
||||
|
||||
**Location**: Toronto, Ontario, Canada
|
||||
|
||||
**Industries:** AI, fintech, edtech, prop tech, health tech, and other digital domains
|
||||
|
||||
**Top startups incubated:** Mejuri, Borrowell, Ada
|
||||
|
||||

|
||||
|
||||
|
||||
## 4. [Idealab](https://www.idealab.com/)
|
||||
|
||||
Idealab is the longest-running tech incubator and is often credited as one of the first of its kind. It follows a studio model of generating and testing ideas in-house and has launched 150+ companies with over 45 successful IPOs/acquisitions to date. Idealab's enduring track record and its focus on big problem-solving ideas make it uniquely influential in the startup world.
|
||||
|
||||
**Location**: Pasadena, California, USA
|
||||
|
||||
**Industries:** Focus on technology and innovation. Historically web & software, but also clean energy and other science-driven ventures
|
||||
|
||||
**Top startups incubated:** Pica, [GoTo.com](http://goto.com/)
|
||||
|
||||

|
||||
|
||||
|
||||
## 5. [1871](https://1871.com/)
|
||||
|
||||
A nonprofit incubator named after Chicago's rebirth after the 1871 fire, it has been ranked the [world's #1 business incubator](https://1871.com/about/#:~:text=These%20values%20make%20up%20the,Most%20Promising%20Women%20Founders%20Incubator) by UBI Global. Located in a 150,000 sq ft coworking space, 1871 supports early-stage companies with mentorship, workshops, investor connections, and specialized programs (e.g., for women founders), serving as the tech startup nexus of the US Midwest.
|
||||
|
||||
**Location**: Chicago, Illinois, USA
|
||||
|
||||
**Industries:** Broadly tech (sector-agnostic digital startups), with an emphasis on supporting Chicago's tech ecosystem (e.g., B2B software, fintech, health, etc.)
|
||||
|
||||
**Top startups incubated:** Cameo, SpotHero
|
||||
|
||||

|
||||
|
||||
{% call_to_action title="Build your startup with Appwrite" description="Join the Startups program and benefit from Appwrite’s all-in-one development platform to build, deploy, and scale your products." point1="Ship faster" point2="Cloud credits and discounts" point3="Priority support" point4="Managed cloud solution" cta="Apply now" url="/startups" /%}
|
||||
|
||||
## 6. [MaRS Discovery District](https://www.marsdd.com/)
|
||||
|
||||
MaRS is North America's largest urban innovation hub, supporting 1,200+ science and technology startups under one roof. Housed in a 1.5 million sq ft downtown campus, this incubator provides long-term venture support (in cleantech, health, fintech, etc.) with lab facilities, mentorship, and corporate partnerships. Its portfolio has raised over $19 B in capital and employs 33,000 people.
|
||||
|
||||
**Location**: Toronto, Ontario, Canada
|
||||
|
||||
**Industries:** Mix of health tech, cleantech, fintech, and enterprise software
|
||||
|
||||
**Top startups incubated:** Wattpad, Kobo, Wealthsimple
|
||||
|
||||

|
||||
|
||||
## 7. [Captial Factory](https://capitalfactory.com/)
|
||||
|
||||
Often called the "center of gravity for entrepreneurs in Texas," Capital Factory runs a rolling incubator where startups get 6+ months of coworking space and mentorship in exchange for just 1% equity. It hosts hackathons, investor meetings, an accelerator (optional), and a vast mentor network. As the hub of Texas's startup scene, it's also the region's most active early-stage investor and a magnet for international founders looking to enter the US market.
|
||||
|
||||
**Location**: Austin, Texas, USA
|
||||
|
||||
**Industries:** Generally tech startups with an emphasis on SaaS, enterprise software, AI, and consumer apps
|
||||
|
||||
**Top startups incubated:** SpareFoot, Favor
|
||||
|
||||

|
||||
|
||||
## 8. [Antler Residency](https://www.antler.co/residency)
|
||||
|
||||
Antler is a global early-stage startup incubator and venture capital firm, renowned for its intensive Residency program that helps founders build companies from scratch. Founded in 2017 (in Singapore) by experienced entrepreneurs, Antler’s mission is to “enable and invest in the world’s most exceptional people to build the businesses of tomorrow”. Antler brings together talented individuals (often pre-team or even pre-idea) into cohort programs typically lasting about 3–6 months. During this period, founders are matched with co-founders, develop a viable business idea, and rapidly validate it through market feedback.
|
||||
|
||||
**Location**: Singapore and Ho Chi Minh City, Vietnam
|
||||
|
||||
**Industries:** Fintech, Healthtech, and Proptech
|
||||
|
||||
**Top startups incubated:** Sampingan, Xailient
|
||||
|
||||

|
||||
|
||||
## 9. [SETsquared Partnership](https://www.setsquared.co.uk/)
|
||||
|
||||
A collaboration of five universities (Bath, Bristol, Exeter, Southampton, Surrey), SETsquared has been ranked the [world's #1 university business incubator](https://www.setsquared.co.uk/programme/global-no-1-homepage/#:~:text=In%20November%202019%2C%20we%20were,third%20time%20in%20a%20row) three times (most recently in 2019). Since 2002, it has incubated over 5,000 companies that collectively raised more than £2.7 B. Its incubators offer multi-year support, industry mentoring, and investor access without a fixed program timeline, welcoming international founders across all tech sectors.
|
||||
|
||||
**Location**: UK
|
||||
|
||||
**Industries:** Technology, healthcare, clean energy, AI, and advanced engineering.
|
||||
|
||||
**Top startups incubated:** Brightpearl, Zynstra
|
||||
|
||||

|
||||
|
||||
## 10. [CodeBase](https://thisiscodebase.com/)
|
||||
|
||||
CodeBase is the largest technology incubator in the UK and one of the fastest-growing in Europe. It has supported some of Scotland's most successful tech startups and is central to the country's national Techscaler program, aimed at scaling Scottish startups globally. It's a non-equity, founder-first incubator focused on supporting early to growth-stage tech startups through mentorship, education, infrastructure, and access to Scotland's national tech ecosystem.
|
||||
|
||||
**Location**: Edinburgh, UK
|
||||
|
||||
**Industries:** Primarily technology startups (software, digital, and IT)
|
||||
|
||||
**Top startups incubated:** FanDuel, Skyscanner
|
||||
|
||||

|
||||
|
||||
# What should you look for in an Incubator?
|
||||
|
||||
When evaluating startup incubators, it's important to ask the right questions to ensure the program aligns with your business needs. Here are key questions to guide your decision:
|
||||
|
||||
## 1. What perks and resources does the incubator offer?
|
||||
|
||||
- Do they provide legal, marketing, or funding support?
|
||||
- Do mentors have relevant industry experience?
|
||||
|
||||
## 2. Does the curriculum match your needs?
|
||||
|
||||
- Is the training aligned with your business goals?
|
||||
- Can you manage it alongside daily operations?
|
||||
|
||||
## 3. How strong is the incubator's track record?
|
||||
|
||||
- Have past startups succeeded?
|
||||
- Can you speak to alumni for honest feedback?
|
||||
|
||||
## 4. What does it cost to join?
|
||||
|
||||
- Are there fees for space or services?
|
||||
- How much equity do they take, if any?
|
||||
- Is the value worth the trade-off?
|
||||
|
||||
## 5. Is the location convenient?
|
||||
|
||||
- Is frequent in-person attendance required?
|
||||
- Would relocation be necessary?
|
||||
|
||||
# Conclusion
|
||||
|
||||
Joining a startup incubator can be a great decision, but only if it aligns with your startup's unique needs, goals, and stage of growth. The right incubator can accelerate and take your startup to the next level. But the wrong one can cost you time, equity, and focus.
|
||||
|
||||
Did you know Appwrite has a special program for startups? You can leverage Appwrite's all-in-one cloud platform to build your products. Plus, you will receive Cloud credits and a discount for Appwrite's paid plans. [Apply now](/startups)
|
||||
@@ -48,6 +48,12 @@
|
||||
icon: 'icon-database',
|
||||
isParent: true
|
||||
},
|
||||
{
|
||||
label: 'Storage',
|
||||
href: '/docs/products/storage',
|
||||
icon: 'icon-folder',
|
||||
isParent: true
|
||||
},
|
||||
{
|
||||
label: 'Functions',
|
||||
href: '/docs/products/functions',
|
||||
@@ -67,12 +73,6 @@
|
||||
isParent: true,
|
||||
new: isNewUntil('19 Jul 2025')
|
||||
},
|
||||
{
|
||||
label: 'Storage',
|
||||
href: '/docs/products/storage',
|
||||
icon: 'icon-folder',
|
||||
isParent: true
|
||||
},
|
||||
{
|
||||
label: 'Network',
|
||||
href: '/docs/products/network',
|
||||
|
||||
@@ -157,6 +157,11 @@
|
||||
new: isNewUntil('31 July 2025'),
|
||||
label: 'Support SLA',
|
||||
href: '/docs/advanced/platform/support-sla'
|
||||
},
|
||||
{
|
||||
new: isNewUntil('31 July 2025'),
|
||||
label: 'Uptime SLA',
|
||||
href: '/docs/advanced/platform/uptime-sla'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
63
src/routes/docs/advanced/platform/uptime-sla/+page.markdoc
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
layout: article
|
||||
title: Uptime SLA
|
||||
description: Learn about Appwrite's uptime service level agreement and commitments for different subscription plans.
|
||||
---
|
||||
|
||||
This Uptime Service Level Agreement ("SLA") describes the uptime commitments and related service credit terms provided by APPWRITE ("we," "us," or "our") to users of our products and services ("you" or "user"). By using our services, you agree to the terms of this SLA.
|
||||
|
||||
# Uptime commitments {% #uptime-commitments %}
|
||||
|
||||
We commit to maintaining the following monthly uptime percentages based on your subscription plan:
|
||||
|
||||
| Plan | Monthly Uptime Commitment |
|
||||
| --- | --- |
|
||||
| **Free** | N/A |
|
||||
| **Pro** | 99.5% |
|
||||
| **Scale** | 99.9% |
|
||||
| **Enterprise** | 99.95% |
|
||||
|
||||
# Allowed downtime {% #allowed-downtime %}
|
||||
|
||||
Based on the above uptime commitments, permissible downtime durations are:
|
||||
|
||||
| Plan | Annual Downtime | Monthly Downtime |
|
||||
| --- | --- | --- |
|
||||
| **Free** | N/A | N/A |
|
||||
| **Pro** | ~1.83 days | ~3.6 hours |
|
||||
| **Scale** | ~8.76 hours | ~43.2 minutes |
|
||||
| **Enterprise** | ~4.38 hours | ~21.6 minutes |
|
||||
|
||||
# Service credit terms {% #service-credit-terms %}
|
||||
|
||||
If we fail to meet our uptime commitment, affected users may be eligible for service credits according to the following schedule:
|
||||
|
||||
| Plan | Uptime < Commitment but ≥ 99% | Uptime < 99% but ≥ 95% | Uptime < 95% |
|
||||
| --- | --- | --- | --- |
|
||||
| **Pro** | 10% of monthly fee | 25% of monthly fee | 50% of monthly fee |
|
||||
| **Scale** | 10% of monthly fee | 25% of monthly fee | 50% of monthly fee |
|
||||
| **Enterprise** | 10% of monthly fee | 25% of monthly fee | 50% of monthly fee |
|
||||
|
||||
# Credit request procedure {% #credit-request-procedure %}
|
||||
|
||||
To receive service credits, you must submit a support ticket within **30 days** of the incident via the Appwrite Console, providing relevant data, logs, or screenshots.
|
||||
|
||||
# SLA exclusions {% #sla-exclusions %}
|
||||
|
||||
Downtime specifically excludes periods caused by:
|
||||
|
||||
- Scheduled maintenance activities communicated in advance.
|
||||
- Events beyond our reasonable control (e.g., natural disasters, third-party outages, governmental actions).
|
||||
- Customer or third-party actions, including incorrect configurations or misuse of our services.
|
||||
- Minor performance degradations that do not materially impact core functionality.
|
||||
- External network issues beyond our infrastructure.
|
||||
|
||||
# Commitment to continuous improvement {% #commitment-to-continuous-improvement %}
|
||||
|
||||
We continuously strive to exceed the commitments outlined in this SLA by improving infrastructure resilience and service quality. While the maximum attainable uptime commitment is influenced by our upstream service providers, we aim for excellence and transparency in all operational matters.
|
||||
|
||||
# Modifications {% #modifications %}
|
||||
|
||||
We reserve the right to modify this SLA periodically. Changes will become effective upon publication on our website. Your continued use of our services indicates acceptance of these changes.
|
||||
|
||||
For questions or concerns regarding this SLA, please contact us at our [contact page](/contact-us).
|
||||
@@ -1,7 +1,7 @@
|
||||
import { base } from '$app/paths';
|
||||
import { groupBy } from 'remeda';
|
||||
import type { IntegrationCategory } from '$lib/constants';
|
||||
import { integrationCategoryDescriptions as categoryDescriptions } from '$lib/constants';
|
||||
import type { SearchableCategory } from '$lib/constants';
|
||||
import { partnerCategoryDescriptions as categoryDescriptions } from '$lib/constants';
|
||||
|
||||
export type Integration = {
|
||||
title: string;
|
||||
@@ -26,7 +26,7 @@ export const load = () => {
|
||||
eager: true
|
||||
});
|
||||
|
||||
const categories: IntegrationCategory[] = [];
|
||||
const categories: SearchableCategory[] = [];
|
||||
const platforms: string[] = [];
|
||||
|
||||
const integrations = Object.entries(integrationsGlob).map(([filepath, integrationList]) => {
|
||||
@@ -40,7 +40,7 @@ export const load = () => {
|
||||
frontmatter.platform.map((platform) => platforms.push(platform));
|
||||
categories.push(
|
||||
categoryDescriptions.find((i) => i.slug === frontmatter.category) ??
|
||||
({} as IntegrationCategory)
|
||||
({} as SearchableCategory)
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
{
|
||||
title: 'Training',
|
||||
description:
|
||||
'We provide in depth training and workshops to help you master Appwrite for your clients.',
|
||||
'We provide in-depth training and workshops to help you master Appwrite for your clients.',
|
||||
icon: Training
|
||||
},
|
||||
{
|
||||
@@ -36,9 +36,9 @@
|
||||
icon: EarlyAccess
|
||||
},
|
||||
{
|
||||
title: 'Revenue share',
|
||||
title: 'Innovation',
|
||||
description:
|
||||
'For each client you sell Appwrite to, you will receive a part of the revenue for a whole year.',
|
||||
"Empower your team and elevate your customers' experiences with the newest technology.",
|
||||
icon: Revenue
|
||||
},
|
||||
{
|
||||
@@ -64,7 +64,7 @@
|
||||
},
|
||||
{
|
||||
title: 'All in one platform',
|
||||
description: 'All the APIs a developer needs in one place. And more to come.',
|
||||
description: 'Everything you need to develop, deploy, and scale your applications.',
|
||||
icon: Expert
|
||||
}
|
||||
];
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={classNames(
|
||||
'border-smooth relative -mb-24 border-t py-32',
|
||||
'bg-[url("/images/bgs/building-blocks.webp")] [background-size:50%] bg-right-bottom bg-no-repeat',
|
||||
'before:absolute before:top-0 before:left-0 before:z-0 before:block before:h-80 before:w-full before:bg-[radial-gradient(at_25%_0%,_hsla(343,_98%,_60%,_0.05)_0px,_transparent_73%,_transparent_100%)] md:before:w-1/2',
|
||||
'after:absolute after:top-0 after:right-0 after:z-0 after:hidden after:h-80 after:w-1/2 after:bg-[radial-gradient(at_100%_0%,_hsla(177,_53%,_69%,_0.1)_0px,_transparent_73%,_transparent_100%)] after:md:block md:after:block'
|
||||
)}
|
||||
>
|
||||
<div class="relative container grid grid-cols-1 place-items-center md:grid-cols-2">
|
||||
<section class="flex flex-col gap-4">
|
||||
<h2 class="text-display font-aeonik-pro text-primary max-w-[600px]">
|
||||
Become a Technology Partner
|
||||
</h2>
|
||||
<p class="text-body font-medium">
|
||||
Join our Technology Partners program to integrate your solutions with Appwrite’s
|
||||
API, enhancing functionality and expanding your reach.
|
||||
</p>
|
||||
<a href="/integrations/technology-partner" class="web-button mt-4">
|
||||
<span class="text">Get Started</span>
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
174
src/routes/partners/catalog/(components)/contact-partner.svelte
Normal file
@@ -0,0 +1,174 @@
|
||||
<script context="module" lang="ts">
|
||||
import { PUBLIC_GROWTH_ENDPOINT } from '$env/static/public';
|
||||
|
||||
export const subscribeToNewsletter = async (email: string) => {
|
||||
const response = await fetch(`${PUBLIC_GROWTH_ENDPOINT}/partners/contact`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email
|
||||
})
|
||||
});
|
||||
return response;
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
let name = '';
|
||||
let email = '';
|
||||
let companyName = '';
|
||||
let companyUrl = '';
|
||||
let message = '';
|
||||
|
||||
let submitted = false;
|
||||
let error: string | undefined;
|
||||
let submitting = false;
|
||||
|
||||
const handleSubmit = async () => {
|
||||
submitting = true;
|
||||
error = undefined;
|
||||
const response = await subscribeToNewsletter(email);
|
||||
submitting = false;
|
||||
if (response.status >= 400) {
|
||||
error = response.status >= 500 ? 'Server Error.' : 'Error submitting form.';
|
||||
return;
|
||||
}
|
||||
submitted = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="relative max-h-[35vh]">
|
||||
<div class="relative z-10 py-10">
|
||||
<div class="mx-auto flex w-full max-w-4xl flex-col items-center gap-8 text-center">
|
||||
{#if submitted}
|
||||
<div class="flex items-center gap-2">
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="9"
|
||||
cy="9"
|
||||
r="8"
|
||||
fill="#FD366E"
|
||||
fill-opacity="0.08"
|
||||
stroke="#FD366E"
|
||||
stroke-opacity="0.32"
|
||||
stroke-width="1.2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5.25 10.5L7.75 12.5L12.75 6"
|
||||
stroke="#E4E4E7"
|
||||
stroke-width="1.2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span class="text">
|
||||
Thank you for subscribing! An email has been sent to your inbox.
|
||||
</span>
|
||||
</div>
|
||||
{:else}
|
||||
<form
|
||||
method="post"
|
||||
on:submit|preventDefault={handleSubmit}
|
||||
class="mt-4 flex w-full flex-col gap-4 lg:mt-0"
|
||||
>
|
||||
<div class="flex w-full text-left">
|
||||
<ul class="web-form-list grid w-full gap-4 md:grid-cols-2">
|
||||
<li class="web-form-item">
|
||||
<label class="text-caption block" for="name">Full name</label>
|
||||
<input
|
||||
required
|
||||
class="web-input-text w-full"
|
||||
type="text"
|
||||
placeholder="Walter"
|
||||
id="name"
|
||||
bind:value={name}
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="web-form-item">
|
||||
<label class="text-caption block" for="workEmail">Email</label>
|
||||
<input
|
||||
required
|
||||
class="web-input-text w-full"
|
||||
type="email"
|
||||
placeholder="walter@appwrite.io"
|
||||
id="workEmail"
|
||||
bind:value={email}
|
||||
/>
|
||||
</li>
|
||||
<li class="web-form-item">
|
||||
<label class="text-caption block" for="companyName"
|
||||
>Company name</label
|
||||
>
|
||||
<input
|
||||
required
|
||||
class="web-input-text w-full"
|
||||
type="text"
|
||||
placeholder="Acme Corp"
|
||||
id="companyName"
|
||||
bind:value={companyName}
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="web-form-item flex-col gap-1">
|
||||
<label class="text-caption block" for="companyUrl"
|
||||
>Company url</label
|
||||
>
|
||||
<input
|
||||
required
|
||||
class="web-input-text w-full"
|
||||
type="url"
|
||||
placeholder="https://appwrite.io"
|
||||
id="companyUrl"
|
||||
bind:value={companyUrl}
|
||||
/>
|
||||
</li>
|
||||
<li class="web-form-item flex-col gap-1 sm:col-span-1 md:col-span-2">
|
||||
<label class="text-caption block" for="message"
|
||||
>Any other details you’d like to share?</label
|
||||
>
|
||||
<textarea
|
||||
required
|
||||
class="web-input-text w-full"
|
||||
id="message"
|
||||
placeholder="Your message"
|
||||
bind:value={message}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col items-center justify-between gap-4 sm:flex-col md:flex-col lg:flex-row"
|
||||
>
|
||||
<p class="text-caption max-w-sm self-start text-left lg:self-center">
|
||||
{#if error}
|
||||
{error}
|
||||
{:else}
|
||||
This form is protected by reCAPTCHA, and the Google Privacy Policy
|
||||
and Terms of Service apply.
|
||||
{/if}
|
||||
</p>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
class="web-button is-secondary cursor-pointer px-16!"
|
||||
>
|
||||
<span>Send</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
64
src/routes/partners/catalog/(components)/hero.svelte
Normal file
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={classNames(
|
||||
'grid-bg border-smooth relative flex items-center border-b px-5 py-28 lg:px-8 xl:px-16',
|
||||
'before:from-accent/20 before:absolute before:inset-0 before:-z-1 before:bg-linear-to-tr before:via-transparent before:via-40% before:to-transparent'
|
||||
)}
|
||||
>
|
||||
<div class="relative container pb-0">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="flex flex-col items-center justify-center gap-5 text-center">
|
||||
<div class="text-micro text-white uppercase">
|
||||
Appwrite Partner Catalog<span class="web-u-color-text-accent">_</span>
|
||||
</div>
|
||||
<h1 class="text-headline font-aeonik-pro text-primary">Find a Partner</h1>
|
||||
<p class="text-description max-w-xl">
|
||||
Unlock the full potential of Appwrite by seamlessly integrating your favorite
|
||||
apps with your projects.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.grid-bg {
|
||||
--line-color: rgba(255, 255, 255, 0.02);
|
||||
--size: calc(100vw / 16);
|
||||
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
background-image:
|
||||
repeating-linear-gradient(
|
||||
0deg,
|
||||
var(--line-color),
|
||||
var(--line-color) 1px,
|
||||
transparent 1px,
|
||||
transparent var(--size)
|
||||
),
|
||||
repeating-linear-gradient(
|
||||
90deg,
|
||||
var(--line-color),
|
||||
var(--line-color) 1px,
|
||||
transparent 1px,
|
||||
transparent var(--size)
|
||||
);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: radial-gradient(
|
||||
circle at bottom right,
|
||||
rgba(25, 25, 28, 0.5) 19%,
|
||||
transparent 100%
|
||||
);
|
||||
z-index: -2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
541
src/routes/partners/catalog/+page.svelte
Normal file
@@ -0,0 +1,541 @@
|
||||
<script lang="ts">
|
||||
import { Main } from '$lib/layouts';
|
||||
import { DEFAULT_HOST } from '$lib/utils/metadata';
|
||||
import { TITLE_SUFFIX } from '$routes/titles';
|
||||
import FooterNav from '$lib/components/FooterNav.svelte';
|
||||
import MainFooter from '$lib/components/MainFooter.svelte';
|
||||
import { type ResultType, Fuse } from '$lib/integrations';
|
||||
import { writable } from 'svelte/store';
|
||||
import { autoHash } from '$lib/actions/autoHash';
|
||||
import type { Partner } from './+page';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { classNames } from '$lib/utils/classnames';
|
||||
|
||||
import { page } from '$app/state';
|
||||
import Hero from './(components)/hero.svelte';
|
||||
import CallToAction from './(components)/call-to-action.svelte';
|
||||
import Input from '$lib/components/ui/input.svelte';
|
||||
import Icon from '$lib/components/ui/icon';
|
||||
|
||||
export let data;
|
||||
|
||||
const title = 'Partners' + TITLE_SUFFIX;
|
||||
const description =
|
||||
'Connect your favorite apps to Appwrite for one unified tech stack. Explore our catalog of integrations now.';
|
||||
const ogImage = DEFAULT_HOST + '/images/open-graph/website.png';
|
||||
|
||||
// search functionality
|
||||
let fuseOptions = {
|
||||
keys: ['title'],
|
||||
threshold: 0.2,
|
||||
distance: 500
|
||||
};
|
||||
|
||||
let result: ResultType<Partner> = [];
|
||||
|
||||
let hasQuery: boolean;
|
||||
let query = writable(decodeURIComponent(page.url.searchParams.get('search') ?? ''));
|
||||
|
||||
$: query.subscribe((value) => {
|
||||
hasQuery = value.length > 0;
|
||||
});
|
||||
|
||||
// platform filters
|
||||
const platforms = ['All', ...data.platforms];
|
||||
|
||||
let activePlatform = 'All';
|
||||
|
||||
// categories
|
||||
let activeCategory: string | null = null;
|
||||
|
||||
const handleQuery = (e: Event) => {
|
||||
const value = (e.currentTarget as HTMLInputElement).value;
|
||||
query.set(value);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
if (browser) document.documentElement.setAttribute('data-scroll-smooth', '');
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (browser) document.documentElement.removeAttribute('data-scroll-smooth');
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<!-- Titles -->
|
||||
<title>{title}</title>
|
||||
<meta property="og:title" content={title} />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<!-- Desscription -->
|
||||
<meta name="description" content={description} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<!-- Image -->
|
||||
<meta property="og:image" content={ogImage} />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
<meta name="twitter:image" content={ogImage} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</svelte:head>
|
||||
|
||||
<!-- binding for fuse -->
|
||||
<Fuse list={data.list} options={fuseOptions} bind:query={$query} bind:result />
|
||||
<Main>
|
||||
<Hero />
|
||||
|
||||
<div class="py-10">
|
||||
<div>
|
||||
<div class="container">
|
||||
<div class="l-integrations-grid">
|
||||
<aside class="sidebar flex flex-col gap-8" id="integrations-side">
|
||||
<section>
|
||||
<Input
|
||||
label="Search"
|
||||
name="search"
|
||||
placeholder="Search"
|
||||
bind:value={$query}
|
||||
autocomplete="off"
|
||||
oninput={handleQuery}
|
||||
>
|
||||
{#snippet icon()}
|
||||
<Icon name="search" aria-hidden="true" />
|
||||
{/snippet}
|
||||
</Input>
|
||||
</section>
|
||||
<section class="flex flex-col">
|
||||
<section class="flex flex-col gap-4">
|
||||
<h2
|
||||
class="web-side-nav-header text-micro whitespace-nowrap uppercase"
|
||||
>
|
||||
Platform
|
||||
</h2>
|
||||
<ul class="flex flex-wrap gap-2" class:disabled={hasQuery}>
|
||||
{#each platforms as platform}
|
||||
<li>
|
||||
<button
|
||||
class={classNames(
|
||||
'tag bg-greyscale-800 border-greyscale-700 h-8 cursor-pointer rounded-full border px-3 text-sm font-light',
|
||||
{
|
||||
'bg-white text-black':
|
||||
activePlatform === platform
|
||||
}
|
||||
)}
|
||||
class:active-tag={activePlatform === platform}
|
||||
on:click={() => (activePlatform = platform)}
|
||||
>{platform}</button
|
||||
>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
<div class="web-u-sep-block-start my-6"></div>
|
||||
<section class="flex flex-col gap-4">
|
||||
<h2
|
||||
class="web-side-nav-header text-micro whitespace-nowrap uppercase"
|
||||
>
|
||||
Categories
|
||||
</h2>
|
||||
|
||||
<div class="relative block sm:hidden">
|
||||
<select
|
||||
class="web-input-text w-full appearance-none"
|
||||
disabled={hasQuery}
|
||||
on:change={(e) =>
|
||||
goto(`#${e.currentTarget.value.toLowerCase()}`)}
|
||||
>
|
||||
{#each data.categories as category}
|
||||
{@const integrations = data.partners.find(
|
||||
(i) => i.category === category.slug
|
||||
)}
|
||||
{#if integrations && (activePlatform === 'All' || integrations.integrations.some( (i) => i.partnerLevel.includes(activePlatform) ))}
|
||||
<option value={category.slug}>
|
||||
{category.heading}
|
||||
</option>
|
||||
{/if}
|
||||
{/each}
|
||||
<option value={null}> Select category </option>
|
||||
</select>
|
||||
<Icon
|
||||
name="chevron-down"
|
||||
class="web-u-pointer-events-none absolute top-[11px] right-2"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ul class="hidden flex-col gap-4 sm:flex" class:disabled={hasQuery}>
|
||||
{#each data.categories as category}
|
||||
{@const integrations = data.partners.find(
|
||||
(i) => i.category === category.slug
|
||||
)}
|
||||
{#if integrations && (activePlatform === 'All' || integrations.integrations.some( (i) => i.partnerLevel.includes(activePlatform) ))}
|
||||
<li>
|
||||
<a
|
||||
href={`#${category.slug}`}
|
||||
class="web-link"
|
||||
class:is-pink={category.slug === activeCategory}
|
||||
on:click={() =>
|
||||
activeCategory === category.slug}
|
||||
>{category.heading}</a
|
||||
>
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
</aside>
|
||||
|
||||
<section>
|
||||
<div class="flex flex-col gap-16">
|
||||
{#if hasQuery}
|
||||
<section class="l-max-size-list-cards-section flex flex-col gap-8">
|
||||
<header class="flex flex-col gap-1">
|
||||
<h2 class="text-label text-primary">Search results</h2>
|
||||
<p class="text-description">
|
||||
{result.length > 0 ? result.length : 'No'} results found
|
||||
for "{$query}"
|
||||
</p>
|
||||
</header>
|
||||
<div class="l-max-size-list-cards flex flex-col gap-8">
|
||||
<ul class="l-grid-1">
|
||||
{#each result.map((d) => d.item) as item}
|
||||
<li>
|
||||
<a
|
||||
href={item.href}
|
||||
class="web-card is-normal h-full"
|
||||
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem;"
|
||||
>
|
||||
<div
|
||||
class="mb-3 flex items-center justify-between"
|
||||
>
|
||||
<img
|
||||
class="web-user-box-image is-32px"
|
||||
src={item.product.avatar}
|
||||
alt={item.product.vendor}
|
||||
width="32"
|
||||
height="32"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
class="ml-auto"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h4 class="text-primary">
|
||||
{item.title}
|
||||
</h4>
|
||||
<p class="text-sub-body mt-1">
|
||||
{item.description}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
{:else}
|
||||
<section class="flex flex-col gap-8">
|
||||
<header class="flex flex-col gap-1">
|
||||
<h2 class="text-label text-primary">Featured</h2>
|
||||
<p class="text-description">Top recommended integrations</p>
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<ul class="web-feature-grid grid gap-4 sm:grid-cols-2">
|
||||
{#each data.featured as item}
|
||||
<li
|
||||
class="web-feature-grid-item is-two-columns-desktop-only relative"
|
||||
>
|
||||
<a
|
||||
class="block overflow-hidden rounded-2xl before:absolute before:inset-x-0 before:bottom-0 before:block before:h-80 before:rounded-[inherit] before:bg-gradient-to-b before:from-transparent before:via-transparent before:to-black"
|
||||
href={item.integration.href}
|
||||
>
|
||||
<img
|
||||
src={item.integration.cover}
|
||||
alt={item.integration.title}
|
||||
class="web-u-media-cover block aspect-video"
|
||||
/>
|
||||
<div
|
||||
class="web-user-box absolute bottom-4 left-4 z-10 gap-x-2"
|
||||
>
|
||||
<img
|
||||
class="row-span-2 block size-12 rounded-full"
|
||||
src={item.integration.product
|
||||
.avatar}
|
||||
alt={`Avatar for ${item.integration.product.vendor}`}
|
||||
width="40"
|
||||
height="40"
|
||||
/>
|
||||
<div
|
||||
class="text-body gap-2 font-medium"
|
||||
>
|
||||
<span class="text-primary mt-3">
|
||||
{item.integration.title}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="text-caption web-u-color-text-secondary"
|
||||
>
|
||||
{item.heading}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{#each data.partners as { category, heading, description, integrations }}
|
||||
{#if integrations?.length > 0 && (activePlatform === 'All' || integrations.some( (i) => i.partnerLevel.includes(activePlatform) ))}
|
||||
<section
|
||||
class="l-max-size-list-cards-section flex flex-col gap-8"
|
||||
id={category.toLowerCase()}
|
||||
use:autoHash={(entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (
|
||||
entry.isIntersecting &&
|
||||
activeCategory !== category.toLowerCase()
|
||||
) {
|
||||
activeCategory = category.toLowerCase();
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<header class="flex flex-col gap-1">
|
||||
<h2 class="text-label text-primary">
|
||||
{heading}
|
||||
</h2>
|
||||
<p class="text-description">
|
||||
{description}
|
||||
</p>
|
||||
</header>
|
||||
<div class="l-max-size-list-cards flex flex-col gap-8">
|
||||
<ul class="l-grid-1">
|
||||
{#each integrations as integration, index (`${integration.title}-${index}`)}
|
||||
{#if activePlatform === 'All' || integration.partnerLevel.includes(activePlatform)}
|
||||
<li>
|
||||
<a
|
||||
href={integration.href}
|
||||
class="web-card is-normal h-full"
|
||||
style="--card-padding:1.5rem; --card-padding-mobile:1.5rem; --card-border-radius: 1.5rem"
|
||||
>
|
||||
<div
|
||||
class="mb-3 flex items-center justify-between"
|
||||
>
|
||||
<img
|
||||
class="web-user-box-image is-32px"
|
||||
src={integration.product
|
||||
.avatar}
|
||||
alt={integration.product
|
||||
.vendor}
|
||||
width="32"
|
||||
height="32"
|
||||
/>
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
class="ml-auto"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h4 class="text-primary">
|
||||
{integration.title}
|
||||
</h4>
|
||||
|
||||
<p
|
||||
class="text-sub-body mt-1 line-clamp-2"
|
||||
>
|
||||
{integration.description}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ul>
|
||||
<a
|
||||
href={`#${category.toLowerCase()}`}
|
||||
class="l-float-button web-button is-text"
|
||||
>
|
||||
<span>Show more</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden pt-10">
|
||||
<CallToAction />
|
||||
<div class="container">
|
||||
<FooterNav />
|
||||
<MainFooter />
|
||||
</div>
|
||||
</div>
|
||||
</Main>
|
||||
|
||||
<style lang="scss">
|
||||
@use '$scss/abstract/functions' as f;
|
||||
@use '$scss/abstract/variables/devices';
|
||||
|
||||
:global([data-scroll-smooth]) {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.web-pre-footer-bg {
|
||||
position: absolute;
|
||||
top: clamp(300px, 50vw, 50%);
|
||||
left: clamp(300px, 50vw, 50%);
|
||||
transform: translate(-58%, -72%);
|
||||
width: clamp(1200px, 200vw, 3000px);
|
||||
height: auto;
|
||||
max-inline-size: unset;
|
||||
max-block-size: unset;
|
||||
}
|
||||
.l-float-button {
|
||||
display: none;
|
||||
}
|
||||
/* more tha 9 items */
|
||||
.l-max-size-list-cards-section {
|
||||
scroll-snap-align: start;
|
||||
scroll-margin-top: f.pxToRem(120);
|
||||
}
|
||||
.l-max-size-list-cards {
|
||||
&:where(:has(> ul > li:nth-child(10))) {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-height: f.pxToRem(350);
|
||||
content: '';
|
||||
display: block;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(25, 25, 28, 0) 0%,
|
||||
rgba(25, 25, 28, 0.92) 90%,
|
||||
#19191c 100%
|
||||
);
|
||||
transition: var(--transition);
|
||||
}
|
||||
.l-float-button {
|
||||
position: absolute;
|
||||
inset-inline: 0;
|
||||
inset-block-end: f.pxToRem(20);
|
||||
margin-inline: auto;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:where(:target) {
|
||||
.l-max-size-list-cards {
|
||||
overflow: visible;
|
||||
max-block-size: none;
|
||||
scroll-margin: 100px;
|
||||
&::before {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.l-float-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-grid-1 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
|
||||
gap: 1rem;
|
||||
@media #{devices.$break1} {
|
||||
gap: 1.25rem;
|
||||
}
|
||||
}
|
||||
.l-integrations-grid {
|
||||
position: relative;
|
||||
|
||||
@media #{devices.$break1} {
|
||||
gap: 0;
|
||||
padding-block-start: f.pxToRem(80);
|
||||
}
|
||||
|
||||
.disabled {
|
||||
& > li {
|
||||
pointer-events: none;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
margin-bottom: f.pxToRem(60);
|
||||
@media #{devices.$break2open} {
|
||||
position: sticky;
|
||||
top: 90px;
|
||||
height: 500px;
|
||||
transition: top 0.3s ease;
|
||||
|
||||
&.menu-visible {
|
||||
top: 122px;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
min-width: f.pxToRem(42) !important;
|
||||
|
||||
&.active-tag {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media #{devices.$break2open} {
|
||||
display: grid;
|
||||
gap: f.pxToRem(68);
|
||||
grid-template-columns: f.pxToRem(240) 1fr;
|
||||
padding-block-start: f.pxToRem(40);
|
||||
}
|
||||
}
|
||||
.l-integrations-hero {
|
||||
@media #{devices.$break1} {
|
||||
}
|
||||
@media #{devices.$break2open} {
|
||||
}
|
||||
}
|
||||
.l-bg-1 {
|
||||
max-inline-size: none;
|
||||
max-block-size: none;
|
||||
inset-block-end: -600px;
|
||||
inset-inline-start: -600px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.l-bg-2 {
|
||||
inset-block-start: 0;
|
||||
inset-inline-start: 0;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.web-feature-grid {
|
||||
@media #{devices.$break1} {
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
.web-feature-grid {
|
||||
@media #{devices.$break1} {
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
95
src/routes/partners/catalog/+page.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { base } from '$app/paths';
|
||||
import { groupBy } from 'remeda';
|
||||
import {
|
||||
partnerCategoryDescriptions as categoryDescriptions,
|
||||
type SearchableCategory
|
||||
} from '$lib/constants';
|
||||
|
||||
export type Partner = {
|
||||
title: string;
|
||||
description: string;
|
||||
featured?: boolean;
|
||||
cover: string;
|
||||
partnerLevel: 'Bronze' | 'Silver' | 'Gold' | 'Platinum';
|
||||
category: string;
|
||||
frameworks: Array<string>;
|
||||
website: string;
|
||||
href: string;
|
||||
product: {
|
||||
vendor: string;
|
||||
avatar: string;
|
||||
href: string;
|
||||
};
|
||||
capabilities: Array<string>;
|
||||
regions: Array<string>;
|
||||
languages: Array<string>;
|
||||
};
|
||||
|
||||
export const load = () => {
|
||||
const partnersGlob = import.meta.glob('./**/*.markdoc', {
|
||||
eager: true
|
||||
});
|
||||
|
||||
const categories: Array<SearchableCategory> = [];
|
||||
const platforms: string[] = [];
|
||||
|
||||
const partners = Object.entries(partnersGlob).map(([filepath, integrationList]) => {
|
||||
const { frontmatter } = integrationList as {
|
||||
frontmatter: Partner;
|
||||
};
|
||||
|
||||
const slug = filepath.replace('./', '').replace('/+page.markdoc', '');
|
||||
const integrationName = slug.slice(slug.lastIndexOf('/') + 1);
|
||||
|
||||
categories.push(
|
||||
categoryDescriptions.find((i) => i.slug === frontmatter.category) ??
|
||||
({} as SearchableCategory)
|
||||
);
|
||||
|
||||
return {
|
||||
...frontmatter,
|
||||
href: `${base}/partners/catalog/${integrationName}`
|
||||
};
|
||||
});
|
||||
|
||||
const groupedPartners = groupBy(partners, (i) => i.category);
|
||||
|
||||
const partnersWithDescriptions = Object.entries(groupedPartners).map(
|
||||
([category, integrations]) => {
|
||||
const integrationCategory = categoryDescriptions.find(
|
||||
(key) => key.slug === category.toLowerCase()
|
||||
);
|
||||
return {
|
||||
category,
|
||||
heading: integrationCategory?.heading,
|
||||
description: integrationCategory?.description,
|
||||
integrations
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const featuredIntegrations = partners.filter((i) => i.featured);
|
||||
|
||||
const featuredIntegrationsWithCategoryHeadings = Object.entries(featuredIntegrations).map(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
([_, integration]) => {
|
||||
const integrationCategory = categoryDescriptions.find(
|
||||
(key) => key.slug === integration.category.toLowerCase()
|
||||
);
|
||||
return {
|
||||
heading: integrationCategory?.heading,
|
||||
integration
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
partners: partnersWithDescriptions,
|
||||
list: partners,
|
||||
categories: new Set(categories),
|
||||
platforms: new Set(platforms),
|
||||
featured: featuredIntegrationsWithCategoryHeadings
|
||||
};
|
||||
};
|
||||
|
||||
export const prerender = false;
|
||||
56
src/routes/partners/catalog/fraqtory/+page.markdoc
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
layout: partner
|
||||
title: Fraqtory
|
||||
description: Transform your startup vision into reality with custom software and Fractional CTO services, tailored to accelerate growth and success.
|
||||
date: 2025-03-21
|
||||
featured: false
|
||||
partnerLevel: Silver
|
||||
isNew: true
|
||||
cover: /images/partners/covers/fraqtory.png
|
||||
category: agency
|
||||
website:
|
||||
product:
|
||||
avatar: '/images/partners/avatars/fraqtory.png'
|
||||
vendor: Fraqtory
|
||||
description: Transform your startup vision into reality with custom software and Fractional CTO services, tailored to accelerate growth and success.
|
||||
frameworks:
|
||||
- Javascript
|
||||
- Typescript
|
||||
- React
|
||||
- Next.js
|
||||
- Flutter
|
||||
- React Native
|
||||
- PHP,
|
||||
- Java
|
||||
- Kotlin
|
||||
- Python
|
||||
- C
|
||||
- .NET
|
||||
- Spring Boot
|
||||
- Laravel
|
||||
- MySQL
|
||||
- PostgreSQL
|
||||
capabilities:
|
||||
- Fractional CTO
|
||||
- Software House
|
||||
- Mobile App Development
|
||||
- Web App Development
|
||||
regions:
|
||||
- Africa
|
||||
- Europe
|
||||
- South America
|
||||
- Mid America
|
||||
- North America
|
||||
languages:
|
||||
- English
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
Transform your startup vision into reality with custom software and Fractional CTO services, tailored to accelerate growth and success.
|
||||
|
||||
# Services
|
||||
|
||||
We use Appwrite to accelerate the development of new technology for our clients, primarily tech-based startups. It also enables us to rapidly build MVPs and event platforms, ensuring speed and efficiency in execution.
|
||||
|
||||
Our ideal projects involve collaborating with startups that need to develop innovative solutions from the ground up, mainly focusing on computer vision, full-stack and cloud computing areas.
|
||||
43
src/routes/partners/catalog/makeshyft/+page.markdoc
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
layout: partner
|
||||
title: MakeShyft
|
||||
description: MakeShyft is a software company currently transitioning from client work to B2C & B2B software products. Our goal is to build productivity, communication and collaboration tools. We have big goals and dreams and we're just getting started.
|
||||
date: 2025-03-21
|
||||
featured: true
|
||||
partnerLevel: Silver
|
||||
isNew: true
|
||||
cover: /images/partners/covers/makeshyft.png
|
||||
category: agency
|
||||
website: http://www.makeshyft.com
|
||||
product:
|
||||
avatar: '/images/partners/avatars/makeshyft.png'
|
||||
vendor: SimbaLabs
|
||||
description: MakeShyft is a software company currently transitioning from client work to B2C & B2B software products. Our goal is to build productivity, communication and collaboration tools. We have big goals and dreams and we're just getting started.
|
||||
frameworks:
|
||||
- Livecode
|
||||
- Javascript
|
||||
- PHP
|
||||
capabilities:
|
||||
- Web
|
||||
regions:
|
||||
- Africa
|
||||
- Asia
|
||||
- Australia
|
||||
- New Zealand
|
||||
- Europe
|
||||
- Latin America
|
||||
- Middle East
|
||||
- North America
|
||||
languages:
|
||||
- English
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
MakeShyft is a software company currently transitioning from client work to B2C & B2B software products. Our goal is to build productivity, communication and collaboration tools. We have big goals and dreams and we are just getting started.
|
||||
|
||||
# Services
|
||||
|
||||
We develop software products, we do not currently accept external projects.
|
||||
|
||||
Useful desktop applications that run native and local first.
|
||||
43
src/routes/partners/catalog/mohesu-enterprises/+page.markdoc
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
layout: partner
|
||||
title: Mohesu Enterprises
|
||||
description: Mohesu specializes in creating bespoke digital solutions—from responsive websites and mobile applications to comprehensive managed cloud services, AI & machine learning solutions, and digital marketing strategies. Their approach emphasizes clean, user-friendly interfaces and scalable, customizable technology stacks utilizing frameworks like Next.js, Flutter, and Angular with Appwrite.
|
||||
date: 2025-03-21
|
||||
featured: false
|
||||
partnerLevel: Silver
|
||||
isNew: true
|
||||
cover: /images/partners/covers/mohesu.png
|
||||
category: agency
|
||||
website: https://mohesu.com/
|
||||
product:
|
||||
avatar: '/images/partners/avatars/mohesu.png'
|
||||
vendor: SimbaLabs
|
||||
description: 'Mohesu specializes in creating bespoke digital solutions—from responsive websites and mobile applications to comprehensive managed cloud services, AI & machine learning solutions, and digital marketing strategies. Their approach emphasizes clean, user-friendly interfaces and scalable, customizable technology stacks utilizing frameworks like Next.js, Flutter, and Angular with Appwrite.'
|
||||
frameworks:
|
||||
- Flutter
|
||||
- NextJS
|
||||
- Angular
|
||||
- Remix
|
||||
- Express.js
|
||||
- Dart
|
||||
- Typescript
|
||||
- Javascript
|
||||
- Python
|
||||
capabilities:
|
||||
- AI
|
||||
- Web
|
||||
- Mobile
|
||||
regions:
|
||||
- India
|
||||
languages:
|
||||
- English
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
Mohesu specializes in creating bespoke digital solutions—from responsive websites and mobile applications to comprehensive managed cloud services, AI & machine learning solutions, and digital marketing strategies. Their approach emphasizes clean, user-friendly interfaces and scalable, customizable technology stacks utilizing frameworks like Next.js, Flutter, and Angular with Appwrite.
|
||||
|
||||
# Services
|
||||
We specialize in web and mobile app development, managed cloud services, as well as SEO and digital marketing to help you build, scale, and grow your digital presence.
|
||||
|
||||
We rely on Appwrite as the backend server for our web and mobile applications, ensuring secure, scalable, and efficient development.
|
||||
42
src/routes/partners/catalog/nanornia/+page.markdoc
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
layout: partner
|
||||
title: Nanornia
|
||||
description: Nanornia is a digital agency that creates websites, apps, and visual designs. We help businesses of all sizes build professional and user-friendly digital solutions, using both custom development and low-code tools to deliver high-quality results.
|
||||
date: 2025-03-21
|
||||
featured: true
|
||||
partnerLevel: Silver
|
||||
isNew: true
|
||||
cover: /images/partners/covers/nanornia.png
|
||||
category: agency
|
||||
website: https://nanornia.se
|
||||
product:
|
||||
avatar: '/images/partners/avatars/nanornia.png'
|
||||
vendor: nanornia
|
||||
description: 'Nanornia is a digital agency that creates websites, apps, and visual designs. We help businesses of all sizes build professional and user-friendly digital solutions, using both custom development and low-code tools to deliver high-quality results.'
|
||||
frameworks:
|
||||
- Astro
|
||||
- Nuxt
|
||||
- Vue
|
||||
- Flutter
|
||||
capabilities:
|
||||
- AI
|
||||
- Web
|
||||
- Mobile
|
||||
regions:
|
||||
- Europe
|
||||
languages:
|
||||
- English
|
||||
- Swedish
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
Nanornia is a digital agency that creates websites, apps, and visual designs. We help businesses of all sizes build professional and user-friendly digital solutions, using both custom development and low-code tools to deliver high-quality results.
|
||||
|
||||
# Services
|
||||
|
||||
We provide end-to-end services in web development, app creation, and visual design, building everything from websites and digital platforms to fully custom applications tailored to your business needs.
|
||||
|
||||
We use Appwrite to power secure and scalable web and mobile apps, handling everything from user authentication and databases to file storage and server-side functions—accelerating development and boosting efficiency.
|
||||
|
||||
Our sweet spot is building SaaS platforms, web apps, and AI-powered solutions for businesses that need reliable, scalable, and high-performance digital tools.
|
||||
48
src/routes/partners/catalog/panara-studio/+page.markdoc
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
layout: partner
|
||||
title: Panra Studio
|
||||
description: Panara Studio started as a one-person agency in 2021 and has grown into a small team of experts. We've worked with clients from 10+ countries, including startups, early-stage ventures, angel investors, and creators. Collaborate directly with Kamal Panara, the founder and engineer, and our talented professionals.
|
||||
date: 2025-03-21
|
||||
featured: false
|
||||
partnerLevel: Silver
|
||||
isNew: true
|
||||
cover: /images/partners/covers/panara.png
|
||||
category: agency
|
||||
website: https://panara.studio
|
||||
product:
|
||||
avatar: '/images/partners/avatars/panara.png'
|
||||
vendor: Panara Studio
|
||||
description: Panara Studio started as a one-person agency in 2021 and has grown into a small team of experts. We've worked with clients from 10+ countries, including startups, early-stage ventures, angel investors, and creators. Collaborate directly with Kamal Panara, the founder and engineer, and our talented professionals.
|
||||
frameworks:
|
||||
- Flutter
|
||||
- ReactJS
|
||||
- NextJS
|
||||
- Typescript
|
||||
- Dart
|
||||
- Javascript
|
||||
- NodeJS
|
||||
capabilities:
|
||||
- UI/UX Design
|
||||
- Mobile App Development
|
||||
- Web App Development
|
||||
regions:
|
||||
- Africa
|
||||
- India
|
||||
- Australia
|
||||
- Europe
|
||||
- South America
|
||||
- Mid America
|
||||
- North America
|
||||
languages:
|
||||
- English
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
Panara Studio started as a one-person agency in 2021 and has grown into a small team of experts. We've worked with clients from 10+ countries, including startups, early-stage ventures, angel investors, and creators. Collaborate directly with Kamal Panara, the founder and engineer, and our talented professionals.
|
||||
|
||||
# Services
|
||||
|
||||
At Panera Studio, we specialize in UI/UX design, mobile app development, and web app development, creating high-quality digital products tailored to your needs. Whether it’s an e-commerce app, e-learning platform, CRM system, or a fully bespoke application, we bring ideas to life with a strong focus on performance, scalability, and user experience.
|
||||
|
||||
We use Appwrite as the backend foundation for our internal tools, SaaS products, and client projects, ensuring modern, secure, and efficient development every step of the way.
|
||||
43
src/routes/partners/catalog/simbalabs/+page.markdoc
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
layout: partner
|
||||
title: SimbaLabs
|
||||
description: We are a web engineering company focused on making scalable, efficient web and mobile experiences.
|
||||
date: 2025-03-21
|
||||
featured: false
|
||||
partnerLevel: Silver
|
||||
isNew: true
|
||||
cover: /images/partners/covers/simbalabs.png
|
||||
category: agency
|
||||
website: www.simbalabs.co.za
|
||||
product:
|
||||
avatar: '/images/partners/avatars/simbalabs.png'
|
||||
vendor: SimbaLabs
|
||||
description: 'We are a web engineering company focused on making scalable, efficient web and mobile experiences.'
|
||||
frameworks:
|
||||
- Javascript
|
||||
- Python
|
||||
- Swift
|
||||
capabilities:
|
||||
- AI
|
||||
- Web
|
||||
- Mobile
|
||||
regions:
|
||||
- Africa
|
||||
- Asia
|
||||
- Australia
|
||||
- New Zealand
|
||||
- Europe
|
||||
- Latin America
|
||||
- Middle East
|
||||
- North America
|
||||
languages:
|
||||
- English
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
We are a web engineering company focused on making scalable, efficient web and mobile experiences.
|
||||
|
||||
# Services
|
||||
|
||||
We build AI, web, and mobile applications for clients. We use Appwrite Databases, Functions, Auth & Storage to build innovative, scalable AI, web, and mobile apps.
|
||||
@@ -42,45 +42,45 @@
|
||||
</svg>`,
|
||||
image: DatabasesSlide
|
||||
},
|
||||
{
|
||||
label: 'Functions',
|
||||
icon: Functions,
|
||||
line: (
|
||||
isActive: boolean
|
||||
) => `<svg width="98" height="75" viewBox="0 0 98 75" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 74H35.3623C41.9897 74 47.3623 68.6274 47.3623 62V13C47.3623 6.37258 52.7349 0.999998 59.3623 0.999998H98" class="group-hover:stroke-white ${isActive && 'stroke-white'} group-focus-within:stroke-white transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
</svg>`,
|
||||
image: FunctionsSlide
|
||||
},
|
||||
{
|
||||
label: 'Storage',
|
||||
icon: Storage,
|
||||
line: (
|
||||
isActive: boolean
|
||||
) => `<svg width="98" height="75" viewBox="0 0 98 75" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M98 1H62.6377C56.0103 1 50.6377 6.37258 50.6377 13V62C50.6377 68.6274 45.2651 74 38.6377 74H-9.53674e-07" class="group-hover:stroke-white ${isActive && 'stroke-white'} group-focus-within:stroke-white transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
<path d="M0 74H35.3623C41.9897 74 47.3623 68.6274 47.3623 62V13C47.3623 6.37258 52.7349 0.999998 59.3623 0.999998H98" class="group-hover:stroke-white ${isActive && 'stroke-white'} group-focus-within:stroke-white transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
</svg>`,
|
||||
image: StorageSlide
|
||||
},
|
||||
{
|
||||
label: 'Realtime',
|
||||
icon: Realtime,
|
||||
label: 'Functions',
|
||||
icon: Functions,
|
||||
line: (
|
||||
isActive: boolean
|
||||
) => `<svg width="98" height="2" viewBox="0 0 98 2" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 1L98 1.00001" class="group-hover:stroke-white group-focus-within:stroke-white ${isActive && 'stroke-white'} transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
) => `<svg width="98" height="75" viewBox="0 0 98 75" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M98 1H62.6377C56.0103 1 50.6377 6.37258 50.6377 13V62C50.6377 68.6274 45.2651 74 38.6377 74H-9.53674e-07" class="group-hover:stroke-white ${isActive && 'stroke-white'} group-focus-within:stroke-white transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
</svg>`,
|
||||
image: RealtimeSlide
|
||||
image: FunctionsSlide
|
||||
},
|
||||
{
|
||||
label: 'Messaging',
|
||||
icon: Messaging,
|
||||
line: (
|
||||
isActive: boolean
|
||||
) => `<svg width="98" height="2" viewBox="0 0 98 2" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 1L98 1.00001" class="group-hover:stroke-white group-focus-within:stroke-white ${isActive && 'stroke-white'} transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
</svg>`,
|
||||
image: MessagingSlide
|
||||
},
|
||||
{
|
||||
label: 'Realtime',
|
||||
icon: Realtime,
|
||||
line: (
|
||||
isActive: boolean
|
||||
) => `<svg width="98" height="75" viewBox="0 0 98 75" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M98 74H62.6377C56.0103 74 50.6377 68.6274 50.6377 62V13C50.6377 6.37258 45.2651 0.999998 38.6377 0.999998H-9.53674e-07" class="group-hover:stroke-white ${isActive && 'stroke-white'} group-focus-within:stroke-white transition-all stroke-smooth" stroke-dasharray="4 4"/>
|
||||
</svg>`,
|
||||
image: MessagingSlide
|
||||
image: RealtimeSlide
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
BIN
static/images/bgs/building-blocks.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
static/images/blog/rethinking-saas-authentication/cover.png
Normal file
|
After Width: | Height: | Size: 470 KiB |
BIN
static/images/blog/startup-incubator-guide/1871.png
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
static/images/blog/startup-incubator-guide/antler.png
Normal file
|
After Width: | Height: | Size: 286 KiB |
BIN
static/images/blog/startup-incubator-guide/capitalfactory.png
Normal file
|
After Width: | Height: | Size: 478 KiB |
BIN
static/images/blog/startup-incubator-guide/codebase.png
Normal file
|
After Width: | Height: | Size: 239 KiB |
BIN
static/images/blog/startup-incubator-guide/cover.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
static/images/blog/startup-incubator-guide/dmz.png
Normal file
|
After Width: | Height: | Size: 155 KiB |
BIN
static/images/blog/startup-incubator-guide/idealab.png
Normal file
|
After Width: | Height: | Size: 362 KiB |
BIN
static/images/blog/startup-incubator-guide/mars.png
Normal file
|
After Width: | Height: | Size: 155 KiB |
BIN
static/images/blog/startup-incubator-guide/plugandplay.png
Normal file
|
After Width: | Height: | Size: 344 KiB |
BIN
static/images/blog/startup-incubator-guide/setsquared.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
static/images/blog/startup-incubator-guide/stationf.png
Normal file
|
After Width: | Height: | Size: 287 KiB |
BIN
static/images/partners/avatars/fraqtory.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
static/images/partners/avatars/inellipse.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
static/images/partners/avatars/makeshyft.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
static/images/partners/avatars/mohesu.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
static/images/partners/avatars/nanornia.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
static/images/partners/avatars/panara.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
static/images/partners/avatars/simbalabs.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
static/images/partners/covers/fraqtory.png
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
static/images/partners/covers/inellipse.png
Normal file
|
After Width: | Height: | Size: 316 KiB |
BIN
static/images/partners/covers/makeshyft.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
static/images/partners/covers/mohesu.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
BIN
static/images/partners/covers/nanornia.png
Normal file
|
After Width: | Height: | Size: 313 KiB |
BIN
static/images/partners/covers/panara.png
Normal file
|
After Width: | Height: | Size: 323 KiB |
BIN
static/images/partners/covers/simbalabs.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
static/images/partners/covers/wakka.png
Normal file
|
After Width: | Height: | Size: 316 KiB |
@@ -21,6 +21,7 @@ const config = {
|
||||
article: absolute('./src/markdoc/layouts/Article.svelte'),
|
||||
tutorial: absolute('./src/markdoc/layouts/Tutorial.svelte'),
|
||||
post: absolute('./src/markdoc/layouts/Post.svelte'),
|
||||
partner: absolute('./src/markdoc/layouts/Partner.svelte'),
|
||||
author: absolute('./src/markdoc/layouts/Author.svelte'),
|
||||
category: absolute('./src/markdoc/layouts/Category.svelte'),
|
||||
policy: absolute('./src/markdoc/layouts/Policy.svelte'),
|
||||
|
||||