From 77368a6975db932582ed0a72c2914a6ff1ca3e61 Mon Sep 17 00:00:00 2001
From: flipvanhaaren <flip@shareworks.nl>
Date: Thu, 9 Jan 2025 17:27:13 +0100
Subject: [PATCH 1/2] improvements: dev onboarding

---
 backend/package.json                          |  2 +-
 backend/scripts/drizzle-studio.ts             | 26 +++++++--------
 backend/scripts/quick.ts                      |  2 ++
 backend/scripts/seeds/organizations/seed.ts   | 10 ++++--
 backend/scripts/seeds/user/seed.ts            |  6 +++-
 backend/src/index.ts                          |  9 ++---
 backend/src/lib/mailer.ts                     | 11 ++++++-
 cli/create-cella/src/create.ts                |  5 ++-
 frontend/package.json                         |  3 +-
 frontend/src/alert-config.tsx                 | 33 ++++++++++++++++---
 frontend/src/modules/auth/sign-up-form.tsx    |  2 +-
 frontend/src/modules/common/public-layout.tsx |  2 ++
 .../{legals-text.tsx => legal-texts.tsx}      |  6 ++--
 .../marketing/{legals.tsx => legal.tsx}       |  6 ++--
 frontend/src/routes/marketing.tsx             |  4 +--
 frontend/vite.config.ts                       |  1 +
 info/ARCHITECTURE.md                          | 11 +++++--
 info/QUICKSTART.md                            |  4 +--
 pnpm-lock.yaml                                | 23 +++++++++++++
 19 files changed, 119 insertions(+), 47 deletions(-)
 rename frontend/src/modules/marketing/{legals-text.tsx => legal-texts.tsx} (99%)
 rename frontend/src/modules/marketing/{legals.tsx => legal.tsx} (91%)

diff --git a/backend/package.json b/backend/package.json
index a282ee632..6b67f1b95 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -8,7 +8,7 @@
   "scripts": {
     "quick": "cross-env PGLITE=true tsx scripts/quick.ts && cross-env PGLITE=true pnpm dev",
     "start": "tsx dist/index.js",
-    "dev": "cross-env NODE_ENV=development tsx --watch src/index.ts",
+    "dev": "tsx scripts/drizzle-studio.ts && cross-env NODE_ENV=development tsx --watch src/index.ts",
     "check:types": "tsc",
     "build": "cross-env NODE_ENV=production tsup",
     "build:dev": "tsup",
diff --git a/backend/scripts/drizzle-studio.ts b/backend/scripts/drizzle-studio.ts
index e2aba418e..2babb5f25 100644
--- a/backend/scripts/drizzle-studio.ts
+++ b/backend/scripts/drizzle-studio.ts
@@ -1,21 +1,19 @@
 import { spawn } from 'node:child_process';
+import chalk from 'chalk';
 
-// Function to start Drizzle Studio
-export const startDrizzleStudio = () => {
+const startDrizzleStudioInBackground = () => {
   const studioProcess = spawn('npx', ['drizzle-kit', 'studio'], {
-    stdio: 'inherit',
-    shell: true,
+    detached: true, // Detach the process
+    stdio: 'ignore', // Ignore its output to let the parent process exit cleanly
+    shell: true, // Use shell for compatibility
   });
 
-  studioProcess.on('close', (code) => {
-    if (code === 0) {
-      console.log('Drizzle Studio exited successfully.');
-    } else {
-      console.error(`Drizzle Studio exited with code ${code}.`);
-    }
-  });
+  // Detach the child process from the parent
+  studioProcess.unref();
 
-  studioProcess.on('error', (err) => {
-    console.error('Failed to start Drizzle Studio:', err);
-  });
+  console.log(' ');
+  console.log(`${chalk.greenBright.bold('✔')} Drizzle Studio started in the background`);
+  console.log(' ');
 };
+
+startDrizzleStudioInBackground();
diff --git a/backend/scripts/quick.ts b/backend/scripts/quick.ts
index 832c519f7..1ff47d6ca 100644
--- a/backend/scripts/quick.ts
+++ b/backend/scripts/quick.ts
@@ -11,7 +11,9 @@ await migrate(db, { migrationsFolder: 'drizzle', migrationsSchema: 'drizzle-back
 const res = await db.execute(sql`SELECT * FROM users`);
 
 if (res.rows.length > 0) {
+  console.info(' ');
   console.info(`${chalk.greenBright.bold('✔')} Database is already seeded`);
+  console.info(' ');
   process.exit(0);
 }
 
diff --git a/backend/scripts/seeds/organizations/seed.ts b/backend/scripts/seeds/organizations/seed.ts
index ea92e0492..a4e123def 100644
--- a/backend/scripts/seeds/organizations/seed.ts
+++ b/backend/scripts/seeds/organizations/seed.ts
@@ -20,7 +20,8 @@ const SYSTEM_ADMIN_MEMBERSHIP_COUNT = 10;
 
 // Seed organizations with data
 export const organizationsSeed = async () => {
-  console.info('Seeding organizations...');
+  console.info(' ');
+  console.info('◔ Seeding organizations...');
 
   const organizationsInTable = await db.select().from(organizationsTable).limit(1);
 
@@ -53,7 +54,8 @@ export const organizationsSeed = async () => {
   });
 
   await db.insert(organizationsTable).values(organizations).onConflictDoNothing();
-  console.info('Seeding members and memberships, this can take a while...');
+  console.info(' ');
+  console.info('◔ Seeding members and memberships, this can take a while...');
 
   const hashedPassword = await hashPasswordWithArgon('12345678');
 
@@ -138,5 +140,7 @@ export const organizationsSeed = async () => {
     await db.insert(membershipsTable).values(memberships).onConflictDoNothing();
   }
 
-  console.info(`${chalk.greenBright.bold('✔')} Created ${ORGANIZATIONS_COUNT} organizations with ${MEMBERS_COUNT} members each.`);
+  console.info(' ');
+  console.info(`${chalk.greenBright.bold('✔')} Created ${ORGANIZATIONS_COUNT} organizations with ${MEMBERS_COUNT} members each`);
+  console.info(' ');
 };
diff --git a/backend/scripts/seeds/user/seed.ts b/backend/scripts/seeds/user/seed.ts
index 73850ae25..bac1bf7ab 100644
--- a/backend/scripts/seeds/user/seed.ts
+++ b/backend/scripts/seeds/user/seed.ts
@@ -36,5 +36,9 @@ export const userSeed = async () => {
     })
     .onConflictDoNothing();
 
-  console.info(`${chalk.greenBright.bold('✔')} Created admin user with verified email ${adminUser.email} and password ${adminUser.password}.`);
+  console.info(' ');
+  console.info(
+    `${chalk.greenBright.bold('✔')} Created admin user with verified email ${chalk.greenBright.bold(adminUser.email)} and password ${chalk.greenBright.bold(adminUser.password)}.`,
+  );
+  console.info(' ');
 };
diff --git a/backend/src/index.ts b/backend/src/index.ts
index 111365eb2..49d15d42a 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -6,7 +6,6 @@ import { migrate as pgliteMigrate } from 'drizzle-orm/pglite/migrator';
 import { db } from '#/db/db';
 import ascii from '#/utils/ascii';
 import { env } from '../env';
-import { startDrizzleStudio } from '../scripts/drizzle-studio';
 import docs from './lib/docs';
 import app from './routes';
 
@@ -33,9 +32,6 @@ const main = async () => {
     await pgMigrate(db, migrateConfig);
   }
 
-  // Start Drizzle Studio in development mode
-  if (config.mode === 'development') startDrizzleStudio();
-
   // Start server
   serve(
     {
@@ -45,10 +41,11 @@ const main = async () => {
     },
     () => {
       ascii();
+      console.info(' ');
       console.info(
-        `Open ${chalk.greenBright.bold(config.name)} on ${chalk.cyanBright(config.frontendUrl)}. Backend on ${chalk.cyanBright(config.backendUrl)}`,
+        `${chalk.greenBright.bold(config.name)} (Frontend) runs on ${chalk.cyanBright.bold(config.frontendUrl)}. Backend: ${chalk.cyanBright.bold(config.backendUrl)}. Docs: ${chalk.cyanBright(`${config.backendUrl}/docs`)}`,
       );
-      console.info(`Read API docs on ${chalk.cyanBright(`${config.backendUrl}/docs`)}`);
+      console.info(' ');
     },
   );
 };
diff --git a/backend/src/lib/mailer.ts b/backend/src/lib/mailer.ts
index 04f5ebca9..175c28820 100644
--- a/backend/src/lib/mailer.ts
+++ b/backend/src/lib/mailer.ts
@@ -3,12 +3,21 @@ import { config } from 'config';
 import { env } from '../../env';
 
 const sendgrid = new MailService();
+// Check if the API key is set
+const hasApiKey = !!env.SENDGRID_API_KEY;
 
-sendgrid.setApiKey(env.SENDGRID_API_KEY ?? '');
+if (hasApiKey) {
+  sendgrid.setApiKey(env.SENDGRID_API_KEY ?? '');
+}
 
 // Send email, currently hardcoded to use SendGrid but can be changed to any other service
 export const emailSender = {
   send: async (to: string, subject: string, html: string, replyTo?: string) => {
+    if (!hasApiKey) {
+      console.info(`Email to ${to} is not sent because API key is missing.`);
+      return;
+    }
+
     await sendgrid.send({
       to: env.SEND_ALL_TO_EMAIL || to,
       replyTo: replyTo ? replyTo : config.supportEmail,
diff --git a/cli/create-cella/src/create.ts b/cli/create-cella/src/create.ts
index 6994b56b2..9e2f77b59 100644
--- a/cli/create-cella/src/create.ts
+++ b/cli/create-cella/src/create.ts
@@ -168,7 +168,6 @@ export async function create({
 
   if (needsCd) {
     // Calculate the relative path between the original working directory and the target folder
-
     console.info('now go to your project using:');
     console.info(colors.cyan(`  cd ${relativePath}`)); // Adding './' to make it clear it's a relative path
     console.info();
@@ -184,6 +183,10 @@ export async function create({
   console.info(colors.cyan(`  ${packageManager} seed`));
   console.info();
 
+  console.info(`You can directly sign in using:`);
+  console.info(`email: ${colors.greenBright('admin-test@cellajs.com')}`);
+  console.info(`password: ${colors.greenBright('12345678')}`);
+  console.info();
   console.info(`For more info, check out: ${relativePath}/README.md`);
   console.info(`Enjoy building ${projectName} using cella! 🎉`);
   console.info();
diff --git a/frontend/package.json b/frontend/package.json
index c058f44ed..cb2e93e43 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -7,9 +7,9 @@
   },
   "scripts": {
     "quick": "cross-env VITE_QUICK=true pnpm dev",
+    "dev": "cross-env NODE_ENV=development vite --mode development && node --trace-warnings",
     "start": "cross-env NODE_ENV=production pnpm preview",
     "check:types": "tsc",
-    "dev": "cross-env NODE_ENV=development vite --mode development && node --trace-warnings",
     "build": "tsc && vite build",
     "build:dev": "cross-env NODE_ENV=development vite build --mode development",
     "preview": "vite preview --port 3000",
@@ -141,6 +141,7 @@
     "@vitejs/plugin-react": "^4.3.4",
     "autoprefixer": "^10.4.20",
     "cross-env": "^7.0.3",
+    "kill-port": "^2.0.1",
     "postcss": "^8.4.49",
     "postcss-import": "^16.1.0",
     "postcss-preset-env": "^10.1.3",
diff --git a/frontend/src/alert-config.tsx b/frontend/src/alert-config.tsx
index 35401fb2d..635372833 100644
--- a/frontend/src/alert-config.tsx
+++ b/frontend/src/alert-config.tsx
@@ -1,10 +1,30 @@
+import { config } from 'config';
 import { t } from 'i18next';
 import { Info } from 'lucide-react';
 import type { MainAlert } from '~/modules/common/main-alert';
 
-// Here you can set app-specific global alerts
-export const alertsConfig: MainAlert[] = [
-  {
+const alerts = [];
+
+// Explain how to sign in using test account
+if (config.mode === 'development') {
+  alerts.push({
+    id: 'test-credentials',
+    Icon: Info,
+    className: 'rounded-none border-0 border-t z-10 fixed bottom-0 left-0 right-0',
+    children: (
+      <>
+        <strong className="mr-2">Testing credentials</strong>
+        <p>
+          Hi there! New developer? Welcome to Cella! Sign in using <strong>admin-test@cellajs.com</strong> and password <strong>12345678</strong>.
+        </p>
+      </>
+    ),
+  });
+}
+
+// In production mode, show a notice that the app is a pre-release version
+if (config.mode === 'production') {
+  alerts.push({
     id: 'prerelease',
     Icon: Info,
     className: 'rounded-none border-0 border-b',
@@ -14,5 +34,8 @@ export const alertsConfig: MainAlert[] = [
         {t('common:experiment_notice.text')}
       </>
     ),
-  },
-];
+  });
+}
+
+// Here you can set app-specific global alerts
+export const alertsConfig: MainAlert[] = alerts;
diff --git a/frontend/src/modules/auth/sign-up-form.tsx b/frontend/src/modules/auth/sign-up-form.tsx
index d961f786d..2c02c4976 100644
--- a/frontend/src/modules/auth/sign-up-form.tsx
+++ b/frontend/src/modules/auth/sign-up-form.tsx
@@ -17,7 +17,7 @@ import { Input } from '~/modules/ui/input';
 import type { TokenData } from '.';
 
 const PasswordStrength = lazy(() => import('~/modules/auth/password-strength'));
-const LegalText = lazy(() => import('~/modules/marketing/legals-text'));
+const LegalText = lazy(() => import('~/modules/marketing/legal-texts'));
 
 const formSchema = authBodySchema;
 
diff --git a/frontend/src/modules/common/public-layout.tsx b/frontend/src/modules/common/public-layout.tsx
index 09a8b4079..8c7177676 100644
--- a/frontend/src/modules/common/public-layout.tsx
+++ b/frontend/src/modules/common/public-layout.tsx
@@ -2,11 +2,13 @@ import { Outlet } from '@tanstack/react-router';
 import { Dialoger } from '~/modules/common/dialoger';
 import { DropDowner } from '~/modules/common/dropdowner';
 import { Sheeter } from '~/modules/common/sheeter';
+import AlertRenderer from './main-alert/alert-render';
 
 // Also in public routes, some components need to be initialized.
 function PublicLayout() {
   return (
     <>
+      <AlertRenderer />
       <Dialoger />
       <Sheeter />
       <DropDowner />
diff --git a/frontend/src/modules/marketing/legals-text.tsx b/frontend/src/modules/marketing/legal-texts.tsx
similarity index 99%
rename from frontend/src/modules/marketing/legals-text.tsx
rename to frontend/src/modules/marketing/legal-texts.tsx
index e18f5bc65..ec087fdc5 100644
--- a/frontend/src/modules/marketing/legals-text.tsx
+++ b/frontend/src/modules/marketing/legal-texts.tsx
@@ -1,8 +1,8 @@
 import { Link } from '@tanstack/react-router';
 import { config } from 'config';
-import type { LegalTypes } from './legals';
+import type { LegalTypes } from './legal';
 
-const LegalText = ({ textFor }: { textFor: LegalTypes }) => {
+const LegalTexts = ({ textFor }: { textFor: LegalTypes }) => {
   const appName = config.name;
   const companyFull = config.company.name;
   const companyShort = config.company.shortName;
@@ -566,4 +566,4 @@ const LegalText = ({ textFor }: { textFor: LegalTypes }) => {
   );
 };
 
-export default LegalText;
+export default LegalTexts;
diff --git a/frontend/src/modules/marketing/legals.tsx b/frontend/src/modules/marketing/legal.tsx
similarity index 91%
rename from frontend/src/modules/marketing/legals.tsx
rename to frontend/src/modules/marketing/legal.tsx
index 2fbb79163..bed14b689 100644
--- a/frontend/src/modules/marketing/legals.tsx
+++ b/frontend/src/modules/marketing/legal.tsx
@@ -7,7 +7,7 @@ import { SimpleHeader } from '~/modules/common/simple-header';
 import StickyBox from '~/modules/common/sticky-box';
 import PublicPage from '~/modules/marketing/page';
 
-const LegalText = lazy(() => import('~/modules/marketing/legals-text'));
+const LegalTexts = lazy(() => import('~/modules/marketing/legal-texts'));
 
 export type LegalTypes = 'privacy' | 'terms';
 
@@ -15,7 +15,7 @@ const Legal = ({ type }: { type: LegalTypes }) => {
   return (
     <section className="bg-background">
       <div className="mx-auto max-w-[48rem] font-light px-4 md:px-8 min-h-screen">
-        <LegalText textFor={type} />
+        <LegalTexts textFor={type} />
       </div>
     </section>
   );
@@ -26,7 +26,7 @@ const tabs = [
   { id: 'privacy', label: 'common:privacy_policy' },
 ] as const;
 
-export const LegalsMenu = () => {
+export const LegalMenu = () => {
   const { t } = useTranslation();
   return (
     <PublicPage title={t('common:legal')}>
diff --git a/frontend/src/routes/marketing.tsx b/frontend/src/routes/marketing.tsx
index 51eef6ae8..f1fb26503 100644
--- a/frontend/src/routes/marketing.tsx
+++ b/frontend/src/routes/marketing.tsx
@@ -2,7 +2,7 @@ import { createRoute } from '@tanstack/react-router';
 import About from '~/modules/marketing/about';
 import Accessibility from '~/modules/marketing/accessibility';
 import Contact from '~/modules/marketing/contact';
-import { LegalsMenu } from '~/modules/marketing/legals';
+import { LegalMenu } from '~/modules/marketing/legal';
 import { PublicRoute, rootRoute } from './general';
 
 export const AboutRoute = createRoute({
@@ -23,7 +23,7 @@ export const LegalRoute = createRoute({
   path: '/legal',
   staticData: { pageTitle: 'Legal', isAuth: false },
   getParentRoute: () => rootRoute,
-  component: () => <LegalsMenu />,
+  component: () => <LegalMenu />,
 });
 
 export const AccessibilityRoute = createRoute({
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index f23f59f96..d8b46fb74 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -21,6 +21,7 @@ export default defineConfig(() => {
     server: {
       host: '0.0.0.0',
       port: Number(frontendUrl.port),
+      strictPort: true,
     },
     build: {
       rollupOptions: {
diff --git a/info/ARCHITECTURE.md b/info/ARCHITECTURE.md
index 3bf644374..9b751715a 100644
--- a/info/ARCHITECTURE.md
+++ b/info/ARCHITECTURE.md
@@ -8,8 +8,10 @@ This document describes the high-level architecture of Cella.
  5. Open standards. Our long term vision is that each Cella - as in each cell - can speak fluently with other cells. 
 
 ### Backend
-- [Hono](https://hono.dev) + [NodeJS](https://nodejs.org)
-- [Postgres](https://www.postgresql.org) / [PGLite](https://pglite.dev/) + [Drizzle ORM](https://orm.drizzle.team/)
+- [NodeJS](https://nodejs.org)
+- [Hono](https://hono.dev)
+- [Postgres](https://www.postgresql.org)
+- [Drizzle ORM](https://orm.drizzle.team/)
 - [Zod](https://github.com/colinhacks/zod)
 - [OpenAPI](https://www.openapis.org)
 - [Lucia Auth](https://lucia-auth.com/)
@@ -29,10 +31,13 @@ This document describes the high-level architecture of Cella.
 - [Lucide icons](https://lucide.dev)
 
 ### Build tools
-- [Vite](https://vitejs.dev) + [Vite-PWA](https://github.com/antfu/vite-plugin-pwa)
 - [pnpm](https://pnpm.io)
+- [Vite](https://vitejs.dev)
+- [Vite-PWA](https://github.com/antfu/vite-plugin-pwa)
 - [Biome](https://biomejs.dev)
 - [Lefthook](https://github.com/evilmartians/lefthook)
+- [PGLite](https://pglite.dev/)
+
 
 ## File structure
 ```
diff --git a/info/QUICKSTART.md b/info/QUICKSTART.md
index e1b37ef45..3a60ed04f 100644
--- a/info/QUICKSTART.md
+++ b/info/QUICKSTART.md
@@ -23,8 +23,8 @@ pnpm seed
 ## Customize
 1. Customize your config in `/config/default.ts`
 2. Update package.json with your own data
-3. Look at you .env file to understand what is required and update accordingly 
-4. There are many config files, which end with '-config.ts'. Here you can set for example your entity structure or your navigation structure.
+3. Look at your .env file to understand what is required, for example to send emails you will need an API key.
+4. There are many config files with filenames like `-config.ts`. For example for entities or navigation structure.
 
 
 ## Cella CLI
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cbeb9f4c7..1428270f1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -675,6 +675,9 @@ importers:
       cross-env:
         specifier: ^7.0.3
         version: 7.0.3
+      kill-port:
+        specifier: ^2.0.1
+        version: 2.0.1
       postcss:
         specifier: ^8.4.49
         version: 8.4.49
@@ -2844,6 +2847,7 @@ packages:
 
   '@evilmartians/lefthook@1.10.1':
     resolution: {integrity: sha512-G1NPLB4yLYYEyz8oH7yWgHsxUiF546aS1ChSRPNFPSosLxZFM8wqDxek/J9sT447v83gJbKdrnstxeQW/9CIRA==}
+    cpu: [x64, arm64, ia32]
     os: [darwin, linux, win32]
     hasBin: true
 
@@ -7558,6 +7562,9 @@ packages:
     resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
     engines: {node: '>= 0.4'}
 
+  get-them-args@1.3.2:
+    resolution: {integrity: sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==}
+
   get-tsconfig@4.8.1:
     resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
 
@@ -8261,6 +8268,10 @@ packages:
   jws@3.2.2:
     resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
 
+  kill-port@2.0.1:
+    resolution: {integrity: sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==}
+    hasBin: true
+
   kind-of@3.2.2:
     resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
     engines: {node: '>=0.10.0'}
@@ -10194,6 +10205,9 @@ packages:
     resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
     engines: {node: '>=8'}
 
+  shell-exec@1.0.2:
+    resolution: {integrity: sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==}
+
   shiki@1.26.1:
     resolution: {integrity: sha512-Gqg6DSTk3wYqaZ5OaYtzjcdxcBvX5kCy24yvRJEgjT5U+WHlmqCThLuBUx0juyxQBi+6ug53IGeuQS07DWwpcw==}
 
@@ -18907,6 +18921,8 @@ snapshots:
       es-errors: 1.3.0
       get-intrinsic: 1.2.7
 
+  get-them-args@1.3.2: {}
+
   get-tsconfig@4.8.1:
     dependencies:
       resolve-pkg-maps: 1.0.0
@@ -19867,6 +19883,11 @@ snapshots:
       jwa: 1.4.1
       safe-buffer: 5.2.1
 
+  kill-port@2.0.1:
+    dependencies:
+      get-them-args: 1.3.2
+      shell-exec: 1.0.2
+
   kind-of@3.2.2:
     dependencies:
       is-buffer: 1.1.6
@@ -22162,6 +22183,8 @@ snapshots:
 
   shebang-regex@3.0.0: {}
 
+  shell-exec@1.0.2: {}
+
   shiki@1.26.1:
     dependencies:
       '@shikijs/core': 1.26.1

From 87be0a7c4d5ecb144d30a5dde970e3a465598a5f Mon Sep 17 00:00:00 2001
From: flipvanhaaren <flip@shareworks.nl>
Date: Thu, 9 Jan 2025 17:28:15 +0100
Subject: [PATCH 2/2] bump create cella

---
 cli/create-cella/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cli/create-cella/package.json b/cli/create-cella/package.json
index b98fafde3..c97423636 100644
--- a/cli/create-cella/package.json
+++ b/cli/create-cella/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@cellajs/create-cella",
-  "version": "0.1.0",
+  "version": "0.1.1",
   "private": false,
   "license": "MIT",
   "description": "Cella is a TypeScript template to create web apps with sync and offline capabilities.",