No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗tertulia.cloud (formerly Cueline). Webinars with the engagement built in. The presenter uploads a deck as a PDF, presents it in the room, and launches polls, quizzes, word clouds and calls to action as overlays for everyone watching. Each activity can carry a timer; when it runs out the presenter reveals the results as an overlay. Participants react at any time and see a waiting room before the session starts.
The full design is in docs/DESIGN.md; a feature and landing-page comparison with Univid is in docs/COMPETITOR-UNIVID.md; tiers, costs and capacity on the self-hosted LiveKit node are in docs/BUSINESS-MODEL.md. This repo is the Phase 1 build: rooms the host creates (each with its own events, email sequence, deck, activities and waiting room), presenters on WebRTC, viewers on HLS, PDF deck, activities, Q&A, reactions, waiting room, recording. No tiers, billing or signup yet.
| Path | What |
|---|---|
supabase/migrations | Schema. Every table carries org_id; session tables carry session_id. RLS, the session:{id} broadcast trigger, timer and quiz-scoring triggers, run_tallies and quiz_scores views, storage buckets, room email sequences and their inheritance by events. |
supabase/tests | Stubs + smoke test that exercise the migration against plain Postgres (pnpm db:test). |
apps/web | Next.js on Vercel: landing page (/), the public directory (/explore, /explore/[slug]), invite link and registration (/join/[token]), the typed door (/join, email + code) and the personal link (/a/[token]), participant room (/r/[slug]), the host's rooms (/host) and the host panel per room (/host/[slug]), and the functions that need the service key (/api/*). |
Landing page. The community front door, on the Meetup pattern and with its restraint (a white page, one big promise, whitespace and type for hierarchy, no panels or product mocks): a search box into Explore, the next public events and the listed rooms (read live from the directory; empty states when there are none or it cannot be reached), topic chips, how it works for someone joining and for someone organising, the plans, and Start a community as the host door. Google Analytics 4 (components/Analytics, measurement ID in NEXT_PUBLIC_GA_MEASUREMENT_ID) loads from the root layout in production builds only; every call to action carries a data-track value that is reported as a cta_click event. Attendees who already registered join with the email and the six-character code from their welcome email, or skip the typing with the personal link in that email.
Rooms. A host creates rooms from /host. A room is a standing space: its own plan, events and invite links, email sequence, deck, activities, waiting room and branding. The plan belongs to the room: an organisation's first room is free, upgrading it makes it a Starter or Pro room, and every further room is bought as its own Starter or Pro subscription from /host/billing. A free room never sits next to a paid one: a second room cannot be added until the first is upgraded, and a paid room whose subscription lapses while the organisation has other rooms is locked (cannot open, go live or take new events) until it is paid again or the others are deleted down to one (roomAccess() in apps/web/src/lib/billing.ts). Platform admins are exempt from all of this: the rooms they create are complimentary, run at Pro, and are never capped or locked. On the way in the host says what the room is about, picking topics the way a Meetup group picks categories (TopicPicker, suggestions in apps/web/src/lib/topics.ts), so it lands under the right filters on Explore; the Settings tab changes the topics, renames the room, changes its /r/ address, sets its branding, or deletes it (which cancels the reminders still scheduled for its registrants).
Branding. Per room (rooms.branding, helpers in apps/web/src/lib/branding.ts): an accent colour, a logo and a standing call to action. The accent is applied as CSS variables on the room and on the invite page, so every button, badge, chosen answer and result bar takes the room's colour; the text on it flips to dark for light colours. The logo (PNG/JPEG/WebP/GIF in the media bucket) replaces the product mark in the room header and sits by the room name on the invite page. The call to action is a label and an https link, shown as a button in the room header (and under the stage on phones) for the whole session. The Settings tab previews all three with the real components before saving; /api/rooms validates the colour and the links.
Invite link and registration. The organiser creates an event (title, start time, blurb, seats) in the host panel, which is also an invite link. Attendees open /join/<token>, see how many seats are left, register with a name and email, and the same page becomes the door on the day: its button follows the session state. /r/<slug> sends anyone without a seat to the room's current link; org members walk in. Registrations bind to the attendee's anonymous identity; the personal link (/a/<token>) and the email + code form re-bind it, so a second device works. The host panel shows seated, waiting and joined. The reasoning and what to measure are in docs/INVITE-FLOW.md.
This is the beginning of the README. Read the rest at the original. Read the full README ↗