Cal.com i fork Cal.diy, rezerwacje spotkań u siebie
Cal.com to otwarta platforma do umawiania spotkań, czyli strony rezerwacji, typy wydarzeń i synchronizacja z kalendarzami. Wiosną 2026 roku repozytorium calcom/cal.com zmieniło nazwę na calcom/cal.diy, licencję na MIT i straciło cały kod komercyjny. Bez znajomości tej daty połowa poradników w sieci prowadzi w złe miejsce.
Co Cal.com właściwie robi
Pod jedną nazwą siedzą dziś trzy różne rzeczy i mylenie ich ze sobą jest źródłem większości nieporozumień.
Pierwsza to usługa hostowana pod adresem cal.com. Zakładasz konto, dostajesz publiczną stronę, definiujesz typy wydarzeń z długością, buforami przed i po, minimalnym wyprzedzeniem oraz regułami dostępności, a osoba umawiająca się wybiera wolny termin. Cal.com zapisuje wydarzenie w Twoim kalendarzu, dokłada link do wideokonferencji i wysyła przypomnienia.
Druga to kod źródłowy. Do wiosny 2026 roku był to monorepo calcom/cal.com z podziałem na część otwartą i katalog komercyjny. Dziś ten adres odpowiada przekierowaniem 301 na calcom/cal.diy, a projekt pod nową nazwą opisuje siebie jako fork Cal.com z usuniętym kodem komercyjnym.
Trzecia to Cal.com Platform, czyli komponenty React i API v2 dla zespołów, które chcą wstawić rezerwacje do własnego produktu zamiast odsyłać użytkownika na stronę Cal.com. To osobny produkt płatny, mimo że biblioteka komponentów leży w publicznym rejestrze npm.
Warstwa techniczna jest wypisana w README: Next.js, tRPC, React, Tailwind CSS, Prisma i Daily.co. Skalę domeny widać w schemacie bazy: plik packages/prisma/schema.prisma na gałęzi main zawiera 100 modeli, od EventType i Booking, przez CalendarCache i OutOfOfficeEntry, po PlatformOAuthClient.
Licencja z trzech źródeł i przeprowadzka do Cal.diy
Licencję sprawdziłem trzema drogami, bo każda pokazuje co innego.
Źródło pierwsze to plik w repozytorium. Na gałęzi main plik LICENSE ma 21 linii i jest zwykłą licencją MIT z nagłówkiem Copyright (c) 2020-present Cal.com, Inc.. Sprawdziłem też warianty nazw i lokalizacji, które przy projektach z podziałem licencyjnym trzymają część zamkniętą osobno: LICENSE.md, LICENSE.txt, LICENSE-EE, licenses/LICENSE-EE, licenses/LICENSE-AGPL, licenses/LICENSE-MIT, COPYING, NOTICE, ee/LICENSE, packages/features/ee/LICENSE, packages/platform/LICENSE oraz apps/api/LICENSE. Wszystkie zwracają 404. Podziału nie ma.
Ale był. Pod tagiem v6.2.0 i pod starszym v5.0.0 ten sam plik LICENSE zaczyna się od zdania Portions of this software are licensed as follows i dzieli repozytorium na trzy części: katalogi packages/features/ee oraz apps/api/v2/src/ee na licencji komercyjnej zdefiniowanej w ee/LICENSE, komponenty zewnętrzne na licencjach ich autorów, cała reszta na AGPLv3. Plik packages/features/ee/LICENSE pod tagiem v5.0.0 nosi tytuł The Cal.com Commercial License. Ostatnia zmiana pliku LICENSE w historii gałęzi main to commit refactor: Cal.diy (#28903) z 15 kwietnia 2026 roku.
Stara licencja komercyjna warta jest przeczytania, bo wciąż obowiązuje każdego, kto pracuje na kodzie sprzed tej daty. Wolno używać produkcyjnie tylko wtedy, gdy masz ważną subskrypcję Cal.com Enterprise Edition na właściwą liczbę hostów zdefiniowaną w warunkach handlowych. Wolno modyfikować i publikować łatki, ale prawa do modyfikacji zostają przy Cal.com, a same łatki także wymagają subskrypcji. Wolno kopiować i modyfikować bez subskrypcji wyłącznie na potrzeby rozwoju i testów. Zabronione jest kopiowanie, łączenie, publikowanie, rozpowszechnianie, udzielanie sublicencji i sprzedaż. Progu liczbowego nie ma żadnego: liczba hostów jest ustalana w umowie, nie w tekście licencji, i nie ma tu daty przekształcenia w licencję otwartą, jaką znamy z BSL.
Kiedy uruchamiają się obowiązki AGPL, skoro narzędzie wbudowuje się w cudzy produkt? Sekcja 13 AGPLv3 mówi o modyfikacji programu i udostępnianiu go użytkownikom przez sieć. Jeśli stawiasz niezmienioną instancję sprzed kwietnia 2026, nie musisz nic publikować, bo źródła odpowiadające temu, co uruchamiasz, są już publiczne. Jeśli dopisujesz własne zmiany i Twoi klienci klikają w ten interfejs przez przeglądarkę, musisz zaoferować im źródła swojej wersji. Osadzenie rezerwacji przez iframe nie zaraża strony hosta, bo to osobne dzieło komunikujące się przez granicę ramki, ale skrypt embed serwowany z Twojej instancji jest już częścią programu i podlega tym samym regułom. Kod po 15 kwietnia 2026 roku znosi to pytanie w całości, bo MIT nie nakłada obowiązku udostępniania źródeł. Relicencja nie działa jednak wstecz: kopie rozpowszechnione wcześniej pozostają na AGPLv3 plus licencji komercyjnej i tak samo każdy fork zrobiony przed tą datą.
Osobno trzeba powiedzieć rzecz nieprzyjemną: komercyjny Cal.com nie ma już publicznego repozytorium. README nowego projektu odsyła po dostęp on-prem do formularza sprzedażowego. Kod, który realnie napędza usługę w chmurze, przestał być czytelny z zewnątrz.
Pakiety npm, czyli osobna historia licencyjna
Źródło drugie to pole license w rejestrze. Trzy pakiety embed deklarują SEE LICENSE IN LICENSE, czyli odsyłają do pliku w paczce. Pakiet @calcom/atoms w wersji oznaczonej jako latest, czyli 2.6.7 z 19 sierpnia 2026 roku, nie ma pola license w ogóle. Wycofane wersje 2.10.1 i 2.11.0 z 3 maja 2026 roku deklarowały AGPL-3.0-or-later.
Źródło trzecie to zawartość opublikowanej paczki. Rozpakowałem @calcom/embed-react 1.5.3. Archiwum ma 21 pozycji, w tym package/LICENSE. Nagłówek brzmi The Cal.com Commercial License (EE) license, a treść jest tą samą licencją komercyjną co w starym repozytorium. Kluczowe jest jednak przedostatnie zdanie: część oprogramowania serwowana po stronie klienta jako obraz, font, arkusz stylów albo plik kompilowany czy łączony w kliencki JavaScript jest objęta prawami autorskimi na AGPLv3. Cała zawartość tej paczki to dist/Cal.es.js, dist/Cal.es.mjs, dist/Cal.umd.js i deklaracje typów, czyli dokładnie kod kliencki. Czytając ten tekst dosłownie, wyjątek AGPL obejmuje wszystko, co paczka zawiera, a licencja komercyjna zostaje bez przedmiotu. To moja lektura tekstu, nie stanowisko Cal.com, i przy poważnym wdrożeniu warto ją potwierdzić u dostawcy.
Paczka @calcom/atoms 2.6.7 to drugi skrajny przypadek: 3136 plików i 13,77 MB po rozpakowaniu, ani jednego pliku licencyjnego i puste pole license w package.json. Skompilowany kod bez żadnego oświadczenia o warunkach użycia.
W rejestrze wisi też wersja nowsza od latest i oznaczona jako wycofana. Etykiety wyglądają tak: latest wskazuje 2.6.7, maintenance wskazuje 2.6.5 z 5 sierpnia 2026, beta wskazuje 1.9.0-types2. Wersje od 2.7.0 do 2.11.0 mają wyższe numery niż latest i wszystkie noszą komunikat Package no longer supported. Kto kiedyś przypiął 2.11.0, siedzi na wycofanej gałęzi, a menedżer pakietów nie zaproponuje mu cofnięcia się do 2.6.7, bo to numer niższy.
Zakresy zależności równorzędnych w tej samej rodzinie też się rozjeżdżają. @calcom/embed-react 1.5.3 wymaga react w zakresie ^18.2.0 || ^19.0.0, a @calcom/atoms 2.6.7 w zakresie ^18.0.0 || ^19.0.0. Przy Reakcie 18.0 lub 18.1 pierwszy pakiet zgłosi konflikt, drugi nie. Zależności zwykłe @calcom/embed-react to wyłącznie @calcom/embed-core 1.5.3 i @calcom/embed-snippet 1.3.3, przypięte dokładnie, bez zakresów. @calcom/atoms ma zupełnie inne drzewo i przypina je równie sztywno, między innymi @tanstack/react-query na 5.17.19, tailwindcss na 4.1.17, marked na 15.0.6, dompurify na 3.4.0 oraz aliasy w rodzaju @radix-ui/react-dialog-atoms wskazujące na @radix-ui/react-dialog@1.0.4. Jeśli Twoja aplikacja używa nowszego react-query, w drzewie wylądują dwie kopie.
W paczce @calcom/atoms jest jeszcze konkretny defekt. Pole exports opisuje kilkanaście podścieżek wskazujących na pliki źródłowe, a pole files publikuje tylko trzy katalogi.
{
"files": ["dist", "globals.min.css", "fonts"],
"exports": {
".": {
"import": "./dist/cal-atoms.js",
"types": "./dist/index.d.ts",
"require": "./dist/cal-atoms.umd.cjs"
},
"./availability/AvailabilitySettings": "./availability/AvailabilitySettings.tsx",
"./hooks/useAtomsContext": "./hooks/useAtomsContext.ts",
"./timezone": "./timezone/index.tsx",
"./globals.tw3.min.css": "./globals.tw3.min.css"
}
}W archiwum 2.6.7 nie ma ani katalogu availability, ani hooks, ani timezone, ani pliku globals.tw3.min.css. Jedyny arkusz stylów w paczce to globals.min.css. Import po którejkolwiek z tych podścieżek zakończy się błędem rozwiązywania modułu, więc trzymaj się wejścia głównego.
Samodzielne hostowanie w liczbach
Opinia o trudnym self-hoście bierze się głównie z rozmiaru pliku .env.example, a to mylący sygnał. Plik na gałęzi main ma 483 linie, 174 odkomentowane przypisania i 182 unikalne klucze, jeśli policzyć także te zakomentowane. Ale wymaganych jest pięć.
Tabela zmiennych czasu wykonania w README oznacza jako required dokładnie trzy: DATABASE_URL, NEXTAUTH_SECRET i CALENDSO_ENCRYPTION_KEY. Jako optional z podanymi wartościami domyślnymi idą NEXT_PUBLIC_WEBAPP_URL z domyślnym http://localhost:3000 oraz NEXTAUTH_URL, który domyślnie składa się jako {NEXT_PUBLIC_WEBAPP_URL}/api/auth. Przy budowaniu własnego obrazu dochodzi MAX_OLD_SPACE_SIZE z domyślną wartością 4096. README dopisuje przy dwóch kluczach uwagę Must match build variable, więc sekret ustawiony inaczej w buildzie i w kontenerze wywróci logowanie.
git clone https://github.com/calcom/cal.diy.git
cd cal.diy
cp .env.example .env
# klucz ciasteczek NextAuth, 32 losowe bajty
openssl rand -base64 32
# klucz szyfrowania danych aplikacji, 24 bajty dają 32 znaki base64
openssl rand -base64 24
# pełne środowisko deweloperskie: Postgres w Dockerze, migracje, dane testowe
yarn dxOstatnie polecenie wymaga zainstalowanego docker i docker compose. Podnosi lokalną bazę i zasiewa konta testowe, których poświadczenia wypisze w konsoli. Wśród nich są free@example.com z hasłem free, pro@example.com z hasłem pro oraz admin@example.com z hasłem ADMINadmin2022!. Pełną listę zobaczysz w yarn db-studio pod adresem http://localhost:5555.
Warunki wstępne z README to Node w wersji 18 lub nowszej, PostgreSQL w wersji 13 lub nowszej i Yarn jako zalecany menedżer pakietów. Baza to jedyna twarda zależność zewnętrzna. Serwer SMTP jest potrzebny, jeśli mają wychodzić maile z potwierdzeniami, i konfiguruje się go przez EMAIL_FROM, EMAIL_SERVER_HOST, EMAIL_SERVER_PORT, EMAIL_SERVER_USER i EMAIL_SERVER_PASSWORD. W pliku przykładowym siedzi też zakomentowany RESEND_API_KEY, więc jeśli wolisz nadawcę transakcyjnego zamiast własnego SMTP, Resend jest wspierany bez dopisywania kodu. Rate limiting przez Unkey jest opcjonalny i README mówi wprost, że bez niego aplikacja działa normalnie.
Osobny akapit należy się pamięci. README zaleca w trybie deweloperskim NODE_OPTIONS="--max-old-space-size=16384", czyli 16 GB dla procesu Node. Budowanie obrazu domyślnie dostaje 4096 MB. To nie jest aplikacja, którą postawisz na najmniejszej instancji u dostawcy. Obraz kontenerowy leży na Docker Hubie jako calcom/cal.diy, a warianty ARM mają sufiks w tagu. Przykład podany w README to calcom/cal.diy:v5.6.19-arm, czyli tag starszy niż bieżące wydania, co pokazuje, jak bardzo dokumentacja goni kod. Jeśli szukasz warstwy, która ustawi za Ciebie reverse proxy i certyfikaty, Dokploy robi dokładnie to zadanie.
Integracje z kalendarzami wymagają własnych aplikacji OAuth i tego nie da się obejść. Instrukcja dla Google ma w README jedenaście kroków: własny projekt w Google Cloud, włączenie Google Calendar API, ekran zgody, dodanie zakresów .../auth/calendar.events i .../auth/calendar.readonly, wpisanie kont testowych, utworzenie identyfikatora OAuth typu Web Application, dwa adresy przekierowania w postaci <adres>/api/integrations/googlecalendar/callback oraz <adres>/api/auth/callback/google, pobranie pliku JSON i wklejenie jego całej treści jako wartości GOOGLE_API_CREDENTIALS. Potem trzeba jeszcze uruchomić yarn seed-app-store w katalogu packages/prisma i opublikować ekran zgody, bo dopóki aplikacja jest w trybie testowym, zadziała wyłącznie dla kont dopisanych jako Test Users.
Microsoft to sześć kroków w Azure App Registration, z rejestracją wielodzierżawową, adresem przekierowania <adres>/api/integrations/office365calendar/callback oraz zmiennymi MS_GRAPH_CLIENT_ID i MS_GRAPH_CLIENT_SECRET. Zoom to dwanaście kroków z zakresami meeting:write:meeting i user:read:settings. Daily.co to cztery kroki i klucz DAILY_API_KEY.
Najważniejsza informacja o self-hoście dotyczy jednak tego, czego w otwartym repozytorium nie ma. README wymienia jako usunięte: Teams, Organizations, Insights, Workflows oraz SSO i SAML. Sprawdziłem to w schemacie bazy na gałęzi main i obraz jest mieszany. Modele Team, Membership, OrganizationSettings, TeamBilling i OrganizationBilling nadal w schemacie są, ale nie ma modelu Workflow ani modelu formularzy routingu, a katalog packages/app-store/routing-forms nie odpowiada na żadnym ze sprawdzonych plików. Routing formularzy, czyli funkcja, po którą wiele zespołów w ogóle sięga po Cal.com, w otwartym kodzie nie istnieje. Nie ma też wersji hostowanej Cal.diy: README mówi wprost, że projekt uruchamiasz wyłącznie na własnej infrastrukturze.
Wbudowanie rezerwacji we własny produkt
Drogi są dwie i różnią się wszystkim: ceną, licencją i stopniem kontroli nad wyglądem.
Pierwsza to embed, czyli ramka wskazująca na stronę rezerwacji. Komponent Cal z pakietu @calcom/embed-react przyjmuje calLink jako jedyną wymaganą właściwość, a poza tym calOrigin, namespace, config, initConfig z polami debug i uiDebug, embedJsUrl oraz wszystkie atrybuty zwykłego div.
import Cal, { getCalApi } from "@calcom/embed-react"
import { useEffect } from "react"
export function BookingPanel() {
useEffect(() => {
;(async () => {
const cal = await getCalApi({ namespace: "onboarding" })
cal("ui", {
theme: "light",
layout: "month_view",
hideEventTypeDetails: false,
cssVarsPerTheme: {
light: { "cal-brand": "#1f2937" },
dark: { "cal-brand": "#e5e7eb" }
}
})
})()
}, [])
return (
<Cal
namespace="onboarding"
calLink="zespol/rozmowa-wstepna"
calOrigin="https://cal.example.com"
config={{ layout: "month_view", theme: "light" }}
style={{ width: "100%", height: "100%", overflow: "scroll" }}
/>
)
}Nazwy pól w wywołaniu cal("ui", ...) pochodzą z typu UiConfig w @calcom/embed-core i są dokładnie takie: hideEventTypeDetails, theme, styles, cssVarsPerTheme, layout i colorScheme. Dopuszczalne układy to month_view, week_view i column_view. Typ EmbedStyles pozwala nadpisać tło elementów eventTypeListItem, enabledDateButton, disabledDateButton i availabilityDatePicker, i na tym kończy się stylowanie. To ramka, a nie komponent w Twoim drzewie React.
Druga droga to Cal.com Platform i pakiet @calcom/atoms. Tu dostajesz prawdziwe komponenty. Eksportowane są między innymi Booker, BookerEmbed, AvailabilitySettings, CalendarSettings, CalendarView, CreateEventType, EventTypeSettings, ListEventTypes, GcalConnect, OutlookConnect, StripeConnect, PaymentForm, Router, TroubleShooter i OnboardingEmbed, a obok nich haki useBookings, useBooking, useCancelBooking, useEventTypes, useAvailableSlots, useConnectedCalendars, useMe, useTeams i useAtomsContext.
import { CalProvider, Booker, useBookings } from "@calcom/atoms"
import "@calcom/atoms/globals.min.css"
export function Schedule({ accessToken }: { accessToken: string }) {
return (
<CalProvider
clientId={process.env.NEXT_PUBLIC_CAL_OAUTH_CLIENT_ID as string}
accessToken={accessToken}
options={{
apiUrl: "https://api.cal.com/v2",
refreshUrl: "/api/cal/refresh"
}}
autoUpdateTimezone={true}
onTokenRefreshError={(error) => console.error(error)}
>
<Booker eventSlug="rozmowa-wstepna" username="zespol" />
</CalProvider>
)
}Nazwy właściwości CalProvider pochodzą z deklaracji typów w paczce 2.6.7: clientId, accessToken, options z polami apiUrl i refreshUrl, autoUpdateTimezone, labels, language, onTimezoneChange, onTokenRefreshStart, onTokenRefreshSuccess, onTokenRefreshError, version, organizationId i isEmbed. Dokumentacja w kodzie zaznacza, że refreshUrl jest wymagany, jeśli podajesz accessToken, bo tokeny użytkowników zarządzanych wygasają i biblioteka sama uderzy pod ten adres po nowy.
I tu wraca reszta stosu. Atoms dają interfejs rezerwacji, ale użytkownicy zarządzani muszą skądś mieć tożsamość, więc warstwa logowania zostaje po Twojej stronie, czy to na Clerk, czy na Better Auth. Potwierdzenia i przypomnienia we własnym brandingu to maile transakcyjne, czyli znów Resend albo równorzędny nadawca. A jeśli rezerwacja ma wywołać powiadomienie w aplikacji, na Slacku i mailem według preferencji odbiorcy, przydaje się osobna warstwa w rodzaju Knock, bo webhooki Cal.com kończą się na wysłaniu zdarzenia.
Cennik chmury i to, za co się płaci
Cennik pod adresem cal.com/pricing renderuje się w surowym HTML, więc dało się go odczytać bez przeglądarki. Plan darmowy nosi opis Free forever i obejmuje jednego użytkownika, nielimitowane typy wydarzeń i kalendarze, powiadomienia mailowe i SMS, integracje z ponad setką aplikacji, aplikację mobilną, rozszerzenie do przeglądarki, płatności Stripe i PayPal, dwustronną synchronizację z Salesforce i HubSpot oraz import wydarzeń z Calendly.
Plan Teams kosztuje 12 dolarów za użytkownika miesięcznie, plan Organizations 28 dolarów za użytkownika miesięcznie, oba z czternastodniowym okresem próbnym. Enterprise ma cenę Custom z dopiskiem o rozliczeniu rocznym.
Jest tu rozbieżność, którą trzeba nazwać. Przełącznik na stronie stoi w pozycji YEARLY i obok widnieje Save 25%, ale w surowym HTML znajdują się wyłącznie kwoty 12 i 28. Cena miesięczna nie jest renderowana bez JavaScriptu, więc jej nie potwierdziłem. Jeśli obniżkę 25 procent liczyć od ceny miesięcznej, wychodzi około 16 i około 37,33 dolara, ale to moje wyliczenie, nie liczba ze strony. Podobnie adres cal.com/platform/pricing zwraca dokument identycznej długości co cal.com/pricing, czyli 1 587 789 bajtów, więc osobnego cennika Platform bez JavaScriptu nie widać.
Co jest płatne mimo otwartego kodu? W planie Teams: wspólna dostępność zespołu, round robin, typy wydarzeń zarządzane i zbiorowe, wydarzenia cykliczne, własne treści powiadomień, usunięcie brandingu Cal.com, formularze routingu, statystyki rezerwacji i dodatkowe API. W planie Organizations: nielimitowane podzespoły, routing po własnych zmiennych, subdomena firmowa, SAML SSO i SCIM, zgodność SOC 2, HIPAA i ISO 27001, spotkania natychmiastowe, delegacja na poziomie domeny i uprawnienia oparte o role. Zestawienie tego z poprzednią sekcją daje pełny obraz: formularze routingu są płatne w chmurze i jednocześnie usunięte z otwartego repozytorium, więc nie ma ścieżki, w której dostajesz je za darmo u siebie.
Cal.com a alternatywy
| Cecha | Cal.com w chmurze | Cal.diy u siebie | Calendly |
|---|---|---|---|
| Licencja kodu | brak publicznego repozytorium | MIT | zamknięta |
| Wejście bez opłat | 1 użytkownik, plan Free | pełny kod, koszt serwera | 1 typ wydarzenia, 1 kalendarz |
| Cena za miejsce, rozliczenie roczne | 12 USD Teams, 28 USD Organizations | brak opłat licencyjnych | 10 USD Standard, 16 USD Teams |
| Próg wejścia dla planu firmowego | brak podanego minimum miejsc | nie dotyczy | od 15 000 USD rocznie, od 50 miejsc |
| Round robin i zespoły | plan Teams | usunięte z repozytorium | plan Teams |
| Formularze routingu | plan Teams | brak w kodzie | plan Teams |
| SAML SSO | plan Organizations | usunięte z repozytorium | dodatek w Teams, pełne w Enterprise |
| Komponenty React | Platform, pakiet @calcom/atoms | nie dotyczy | brak |
Arytmetyka progu Calendly domyka się ładnie: 15 000 dolarów rocznie przy 50 miejscach to 300 dolarów za miejsce rocznie, czyli 25 dolarów miesięcznie, a więc niewiele poniżej 28 dolarów planu Organizations w Cal.com. Różnica jest w tym, że Cal.com nie podaje minimalnej liczby miejsc, a Calendly stawia próg pięćdziesięciu i zaznacza, że rozliczenie jest wyłącznie w dolarach.
Wybór da się sprowadzić do trzech pytań. Jeśli chcesz gotowego narzędzia dla zespołu i nie planujesz go dotykać kodem, różnica między Cal.com a Calendly sprowadza się do ceny za round robin, bo u Cal.com jest on w planie za 12 dolarów, a u Calendly w planie za 16. Jeśli chcesz wstawić rezerwacje do własnego produktu, licząca się jest tylko jedna opcja, bo Calendly nie publikuje komponentów React. A jeśli powodem wyboru jest samodzielne hostowanie, sprawdź najpierw listę funkcji usuniętych z Cal.diy, zanim policzysz oszczędności.
Typowe błędy
Pierwszy to szukanie repozytorium calcom/cal.com i przyjmowanie, że nic się nie zmieniło. Adres nadal działa, bo GitHub przekierowuje, ale prowadzi do innego projektu o innej licencji i innym zakresie funkcji. Każdy poradnik napisany przed kwietniem 2026 opisuje kod, którego pod tym adresem już nie ma.
Drugi to założenie, że MIT działa wstecz. Twój fork zrobiony w 2025 roku albo instancja zbudowana z tagu v6.2.0 pozostają na AGPLv3, a katalogi packages/features/ee i apps/api/v2/src/ee w tych wersjach nadal wymagają subskrypcji do użytku produkcyjnego. Relicencja obejmuje kod od commita, w którym ją wprowadzono.
Trzeci to planowanie samodzielnego hostowania pod zespoły. Kto stawia Cal.diy z myślą o wspólnej dostępności i formularzach routingu, odkryje ich brak dopiero po skonfigurowaniu bazy, poczty i aplikacji OAuth, czyli po kilku godzinach pracy.
Czwarty to przypięcie @calcom/atoms do najwyższego numeru wersji. Wersje od 2.7.0 do 2.11.0 mają wyższe numery niż latest, ale są oznaczone jako wycofane. Prawidłowy zapis to "@calcom/atoms": "2.6.7" albo zakres nieprzekraczający linii 2.6.
Piąty to import po podścieżce z @calcom/atoms. Pole exports obiecuje ./availability/AvailabilitySettings czy ./timezone, ale pole files nie publikuje tych katalogów i w archiwum ich nie ma. Wszystko, co realnie działa, wychodzi z wejścia głównego.
Szósty to wypełnianie wszystkich 174 zmiennych z pliku przykładowego. Wymagane są trzy, a dwie kolejne mają sensowne wartości domyślne. Reszta to konfiguracja integracji, których w danym wdrożeniu najczęściej nie włączasz.
Siódmy to rozjazd sekretów między budowaniem obrazu a jego uruchomieniem. README pisze przy NEXTAUTH_SECRET i CALENDSO_ENCRYPTION_KEY uwagę Must match build variable, a objawem niedopasowania jest wylogowywanie użytkowników zaraz po zalogowaniu.
Ósmy to sięganie po NODE_TLS_REJECT_UNAUTHORIZED=0 jako pierwsze rozwiązanie problemu za load balancerem. README rzeczywiście je podaje przy terminacji SSL na brzegu, ale zaznacza, że robisz to na własną odpowiedzialność, bo wyłączasz weryfikację certyfikatów w całym procesie.
FAQ
Czy Cal.com nadal jest otwarty?
Otwarty jest fork calcom/cal.diy na licencji MIT, z usuniętymi funkcjami firmowymi. Produkt komercyjny działający w chmurze nie ma publicznego repozytorium, a README nowego projektu odsyła po dostęp on-prem do kontaktu ze sprzedażą. Do wiosny 2026 roku całość leżała w jednym repozytorium z podziałem na AGPLv3 i licencję komercyjną.
Kiedy uruchamiają się obowiązki AGPL przy wersjach sprzed relicencji?
Przy modyfikacji kodu i udostępnieniu go użytkownikom przez sieć. Niezmieniona instancja nie wymaga publikowania niczego, bo odpowiadające jej źródła są już dostępne. Zmieniona wymaga zaoferowania źródeł Twojej wersji osobom, które z niej korzystają przez przeglądarkę. Strona hosta osadzająca rezerwację w ramce jest osobnym dziełem, ale skrypt embed serwowany z Twojej instancji już nie.
Czy da się postawić u siebie Cal.com z zespołami i formularzami routingu?
Nie z otwartego repozytorium. README Cal.diy wymienia Teams, Organizations, Insights, Workflows oraz SSO i SAML jako usunięte, a w schemacie bazy na gałęzi main nie ma ani modelu Workflow, ani modelu formularzy routingu. Same tabele Team i Membership w schemacie zostały, co nie znaczy, że interfejs do nich istnieje.
Ile zmiennych środowiskowych trzeba naprawdę ustawić?
Trzy oznaczone jako wymagane: DATABASE_URL, NEXTAUTH_SECRET i CALENDSO_ENCRYPTION_KEY. Dwie kolejne, NEXT_PUBLIC_WEBAPP_URL i NEXTAUTH_URL, mają wartości domyślne dobre na start lokalny. Plik .env.example ma 174 odkomentowane przypisania, ale prawie wszystkie dotyczą integracji opcjonalnych.
Czy do integracji z Google Calendar wystarczy klucz API?
Nie. Trzeba założyć własny projekt w Google Cloud, włączyć Google Calendar API, skonfigurować ekran zgody z zakresami .../auth/calendar.events i .../auth/calendar.readonly, utworzyć identyfikator OAuth typu Web Application z dwoma adresami przekierowania i wkleić całą treść pobranego pliku JSON jako wartość GOOGLE_API_CREDENTIALS. Analogicznie Microsoft wymaga rejestracji w Azure i pary MS_GRAPH_CLIENT_ID oraz MS_GRAPH_CLIENT_SECRET.
Czy @calcom/embed-react wolno używać komercyjnie?
Pakiet deklaruje w rejestrze SEE LICENSE IN LICENSE, a plik w archiwum to licencja komercyjna Cal.com z wyjątkiem obejmującym wszystko, co jest serwowane po stronie klienta i objęte AGPLv3. Ponieważ paczka zawiera wyłącznie zbudowany kod kliencki i deklaracje typów, wyjątek obejmuje jej całość. To odczytanie tekstu, a nie oficjalna wykładnia, więc przy wdrożeniu o wysokiej stawce potwierdź to u dostawcy.
Kod źródłowy znajdziesz w repozytorium Cal.diy, cennik usługi hostowanej na stronie Cal.com, a paczki do wbudowania rezerwacji w rejestrze npm.