Skip to content

feat: designed and implemented database schema and tables#38

Merged
Berny-ft merged 12 commits intodevfrom
feature/4-db-schema
Apr 2, 2026
Merged

feat: designed and implemented database schema and tables#38
Berny-ft merged 12 commits intodevfrom
feature/4-db-schema

Conversation

@Berny-ft
Copy link
Copy Markdown
Contributor

@Berny-ft Berny-ft commented Apr 1, 2026

Closes #4

Overview

Designed and implemented the PostgreSQL database schema for the MCLD platform using Drizzle ORM. Created tables for profiles, services, schedules, service bookings, webinars, webinar registrations, and coaching sessions. Also added Stripe payment infrastructure (subscriptions, purchases tables, webhook handler, and Stripe sync helpers) to support the upcoming payment feature.

Testing

Manually pushed the schema to Supabase using pnpm db:push and verified all tables appear in the Supabase dashboard under the database section.
Screenshots / Screencasts
N/A — no frontend changes in this PR.

Checklist
[x] Code is neat, readable, and works
[x] Code is commented where appropriate and well-documented
[x] Commit messages follow our guidelines
[x] Issue number is linked
[x] Branch is linked
[x] Reviewers are assigned (one of your tech leads)

Notes

Coach availability was intentionally excluded from this schema — coaches do not set recurring availability in this version of the platform. This decision is reflected in the docs.

Copilot AI review requested due to automatic review settings April 1, 2026 02:19
@RenaudBernier RenaudBernier requested review from achneerov and martin0024 and removed request for Copilot April 1, 2026 02:35
@martin0024 martin0024 requested a review from Copilot April 1, 2026 02:35
@RenaudBernier RenaudBernier review requested due to automatic review settings April 1, 2026 02:35
@Berny-ft Berny-ft closed this Apr 1, 2026
@Berny-ft Berny-ft reopened this Apr 1, 2026
@Berny-ft Berny-ft changed the base branch from main to dev April 1, 2026 02:40
Copy link
Copy Markdown
Contributor

@martin0024 martin0024 left a comment

Choose a reason for hiding this comment

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

Please before reviewing the PR remove any code snippets related to stripe. This PR should only include db schema. Thanks!

@Berny-ft Berny-ft force-pushed the feature/4-db-schema branch from a9342d9 to 7ba83a7 Compare April 1, 2026 12:01
Copilot AI review requested due to automatic review settings April 1, 2026 12:01
@Berny-ft Berny-ft changed the title Feature/4 db schema Feat : Designed and implemented database schema and tables Apr 1, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Designs and documents an initial PostgreSQL schema for the MCLD platform using Drizzle ORM, along with dependency updates.

Changes:

  • Expanded lib/db/schema.ts with enums and tables for profiles, services/schedules/bookings, webinars/registrations, coaching sessions, and Stripe-related tables.
  • Added Mermaid ERD documentation under docs/ (plus a broader stack explainer).
  • Added an initial Drizzle SQL migration and updated Drizzle/other dependencies.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
pnpm-lock.yaml Locks updated dependency versions (Supabase, Drizzle, lint tooling, etc.).
package.json Bumps drizzle-orm version.
lib/db/schema.ts Defines the intended Drizzle schema (enums + tables incl. Stripe tables).
drizzle/0000_thick_nemesis.sql Adds a SQL migration (currently inconsistent with schema.ts).
drizzle.config.ts Adds schemaFilter: ["public"] configuration.
docs/schema-overview.md Mermaid overview ERD for the intended schema.
docs/profiles.md Profiles table documentation.
docs/services.md Services/schedules/bookings documentation.
docs/webinars.md Webinars/registrations documentation.
docs/coaching.md Coaching sessions documentation.
docs/stack-explainer.md Broad project stack reference.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/db/schema.ts
Comment on lines +3 to +6
export const roleEnum = pgEnum("role", ["user", "admin", "coach"]);
export const serviceTypeEnum = pgEnum('service_type', ["coaching_session", "booking"]);
export const bookingStatusEnum = pgEnum('booking_status', ["pending", "confirmed", "cancelled"]);
export const webinarTierEnum = pgEnum('webinar_tier', ["free", "premium"]);
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The PR description mentions service types “preset date” and “user-scheduling”, but the newly introduced service_type enum here is coaching_session vs booking. Either update the PR description (and any docs) to reflect the new meaning, or rename/adjust the enum values to match the originally described service-type model.

Copilot uses AI. Check for mistakes.
Comment thread lib/db/schema.ts
Comment on lines +82 to 104
export const subscriptions = pgTable("subscriptions", {
id: uuid("id").primaryKey().defaultRandom(),
userId: uuid("user_id").references(() => profiles.id, { onDelete: "cascade" }).notNull().unique(),
stripeSubscriptionId: text("stripe_subscription_id").unique(),
status: text("status").notNull().default("none"),
stripePriceId: text("stripe_price_id"),
cancelAtPeriodEnd: boolean("cancel_at_period_end").notNull().default(false),
paymentMethodBrand: text("payment_method_brand"),
paymentMethodLast4: text("payment_method_last4"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});

export const purchases = pgTable("purchases", {
id: uuid("id").primaryKey().defaultRandom(),
userId: uuid("user_id").references(() => profiles.id, { onDelete: "cascade" }).notNull(),
stripePriceId: text("stripe_price_id").notNull(),
stripeSessionId: text("stripe_session_id").notNull().unique(),
productName: text("product_name").notNull(),
amount: integer("amount").notNull(),
currency: text("currency").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The PR description claims a Stripe webhook handler and Stripe sync helpers were added, but the PR changes only add schema tables (no webhook route handler or helper modules are present in the codebase). Either include the webhook/sync code in this PR, or update the PR description to accurately reflect what’s actually being shipped.

Copilot uses AI. Check for mistakes.
Comment thread docs/profiles.md
@@ -0,0 +1,20 @@
# Profiles Table

Mirrors Supabase `auth.users` — populated via a database trigger on signup. Stores display data and the user's role within the platform.
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This doc states the profiles table is populated via a database trigger on signup, but there is no trigger defined in the committed Drizzle migration(s). Unless triggers are managed elsewhere (e.g., Supabase UI), this is inaccurate; either add the trigger to migrations or revise the documentation to reflect the actual population mechanism.

Suggested change
Mirrors Supabase `auth.users` — populated via a database trigger on signup. Stores display data and the user's role within the platform.
Mirrors Supabase `auth.users`. Stores display data and the user's role within the platform.

Copilot uses AI. Check for mistakes.
Comment thread docs/services.md
Comment on lines +3 to +8
## Services

The central catalog of offerings on the platform. Two types:
- **`booking`** — a bookable service; has an associated `schedules` row (via `scheduling_id`).
- **`coaching_session`** — a coaching offering; `scheduling_id` is null — the scheduling is handled through the `coaching_sessions` table.

Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The relationship description here says booking services “have an associated schedules row (via scheduling_id)”, but the schema links schedules to services via schedules.service_id and does not enforce services.scheduling_id as a foreign key. Update the docs (or the schema) so the described relationship matches the actual constraints and intended source of truth.

Copilot uses AI. Check for mistakes.
@Berny-ft
Copy link
Copy Markdown
Contributor Author

Berny-ft commented Apr 1, 2026

Please before reviewing the PR remove any code snippets related to stripe. This PR should only include db schema. Thanks!

Done, plz check again. Thx!

Comment thread docs/webinars.md Outdated
Comment on lines +22 to +24
webinar_registrations {
uuid id PK
uuid user_id FK
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This shouldn't exist since the flow is either :

  • free to watch webinars
  • subscribers only webinars

They don't need to register, it's like youtube videos.
Please update the schema as well as the documentation.

Comment thread docs/services.md

```mermaid
erDiagram
services {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please add updatedAt on the flow, since services can be modified/edited.

@martin0024
Copy link
Copy Markdown
Contributor

@RenaudBernier does the coach sessions flow works for you ? Good work Berny

Copy link
Copy Markdown
Contributor

@RenaudBernier RenaudBernier left a comment

Choose a reason for hiding this comment

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

Looks good overall, just some variable name changes and the time slots. good job overall, i'm sure that everything will be perfect after your changes

Comment thread docs/coaching.md Outdated
session_status status "pending | confirmed | cancelled | completed"
text meeting_url
text notes
time[] selected_time_slots
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We need a way to store timeslots of different lengths. The user might for example select April 14th 2-5pm and April 17th 10am-3pm. time[] is just an array of timestamps, it can't store timeslots. Please work on finding a solution to this. Should we use a certain string format? Maybe some better solution?

Comment thread docs/schema-overview.md Outdated
Comment on lines +26 to +31
schedules {
uuid id PK
uuid service_id FK
jsonb data
timestamp created_at
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't understand this table, just explain it to me here please

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When a service is of type “booking,” it has a linked row in the schedules table and accepts a JSON blob containing data about the format, such as specific time slots within a given period. I'll rename the table to maybe something that is easier to understand

Comment thread docs/schema-overview.md Outdated
Comment on lines +43 to +52
webinars {
uuid id PK
text title
text description
webinar_tier tier
int duration_minutes
text meeting_url
boolean is_active
timestamp created_at
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Webinars aren't meetings, they're recordings on youtube. change meeting_url to youtube_url please

Comment thread docs/schema-overview.md
Comment on lines +61 to +73
coaching_sessions {
uuid id PK
uuid service_id FK
uuid coach_id FK
uuid user_id FK
timestamp scheduled_at
int duration_minutes
session_status status
text meeting_url
text notes
time[] selected_time_slots
timestamp created_at
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as my comment in the .md, please review how we will store timeslots

Copy link
Copy Markdown
Contributor

@RenaudBernier RenaudBernier left a comment

Choose a reason for hiding this comment

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

Thanks for the changes, Berny. lgtm

@Berny-ft Berny-ft merged commit b606166 into dev Apr 2, 2026
@khoa-l khoa-l changed the title Feat : Designed and implemented database schema and tables feat: designed and implemented database schema and tables Apr 7, 2026
@martin0024 martin0024 deleted the feature/4-db-schema branch April 14, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Issue]: Design and implement database schema and tables

4 participants