EventsPlug
Multi-Tenant Event Management SaaS with Embeddable Web Components
What it is
EventsPlug is a multi-tenant event management platform that allows organizers to create events, build custom registration forms, and drop a lightweight registration widget directly into any website. It runs as a framework-agnostic Web Component with zero external redirects and zero CSS style collisions.
Tech Stack
System Architecture
Organizer landing pages embedding the ticket checkout card directly on their primary domain with zero checkout redirects.
Core Engineering Highlight
Framework-Agnostic Shadow DOM Encapsulation
Embedding checkout widgets into any third-party website with 100% style isolation.
Third-party websites run vastly different CSS frameworks (Tailwind, Bootstrap, normalize resets). Traditional iframe embeds are heavy and break mobile keyboard interactions, while inline JavaScript widgets suffer from severe styling bleed. EventsPlug packages the registration widget as a native Custom Element with a closed Shadow Root, guaranteeing total visual isolation in and out of the host page.
export class EventsPlugWidget extends HTMLElement {
private shadow: ShadowRoot;
constructor() {
super();
// Attach closed shadow root to isolate styles completely from host website
this.shadow = this.attachShadow({ mode: "closed" });
}
connectedCallback() {
const eventId = this.getAttribute("event-id");
const theme = this.getAttribute("theme") || "light";
this.render(eventId, theme);
}
private render(eventId: string | null, theme: string) {
this.shadow.innerHTML = `
<style>
:host { display: block; font-family: system-ui, sans-serif; box-sizing: border-box; }
.widget-card { border: 1px solid #e5e7eb; border-radius: 1rem; padding: 1.5rem; background: #fff; }
.btn-register { background: #7c3aed; color: #fff; padding: 0.75rem 1.5rem; border-radius: 0.75rem; border: none; font-weight: 600; cursor: pointer; width: 100%; }
</style>
<div class="widget-card">
<div id="form-container">Loading event registration...</div>
<button class="btn-register" id="btn-submit">Register Now</button>
</div>
`;
}
}
customElements.define("events-plug-widget", EventsPlugWidget);Key Challenges & Trade-offs
Cross-Framework Styling Bleed on Host Sites
Host sites running opinionated CSS resets (e.g. `* { margin: 0; box-sizing: border-box; }`) distorted widget form inputs and buttons.
Encapsulated the entire widget using native Web Components and Shadow DOM, completely isolating host page CSS rules.
Multi-Tenant Data Boundary Protection
Handling dynamic custom registration questions across multiple organizations required strict tenant isolation without excessive database connection overhead.
Enforced organization-scoped foreign key guards at the NestJS API layer paired with Prisma tenant middleware.