Overview
This guide will walk you through creating your first event on EventPalour, from signing up to publishing your event.
You’ll need a valid email address to get started. OAuth authentication with Google is also supported.
Step 1: Create Your Account
EventPalour offers multiple ways to sign up:
Visit the Sign Up Page
Navigate to /auth/sign-up to create your account
Choose Your Sign Up Method
Email & Password : Traditional signup with email verification
Google OAuth : Sign up with your Google account
Verify Your Email
If using email/password, check your inbox for a 6-digit verification code
Sign Up Implementation
Here’s how the signup process works under the hood:
// From app/(auth)/auth/sign-up/action.ts
export async function signupAction ({
email ,
password ,
} : {
email : string ;
password : string ;
}) : Promise < ActionResult > {
// Validate email format
if ( ! verifyEmailInput ( email )) {
return {
errorMessage: "Please enter a valid email address!" ,
message: null ,
};
}
// Check email availability
const emailAvailable = await checkEmailAvailability ( email );
if ( emailAvailable ) {
return {
errorMessage: "This email address is already registered." ,
message: null ,
};
}
// Verify password strength
const strongPassword = await verifyPasswordStrength ( password );
if ( ! strongPassword ) {
return {
errorMessage: "Password is too weak. Use at least 8 characters." ,
message: null ,
};
}
// Create user and send verification email
const user = await createUser ({
email ,
username: generateRandomUsername (),
avatar: "/images/one.svg" ,
email_verified: false ,
passwordHash: await hashPassword ( password ),
});
// Create verification request
const emailVerificationRequest = await createEmailVerificationRequest (
user . id ,
user . email
);
return {
errorMessage: null ,
message: "Account created! Check your email for verification code." ,
};
}
For production deployments, ensure you configure the email service properly. EventPalour uses Resend for transactional emails.
Step 2: Choose Your Role
After verifying your email, you’ll be asked to select your role:
Event Organizer Create and manage events, sell tickets, and engage attendees
Attendee Discover events, purchase tickets, and join experiences
Role Selection Process
// From app/(auth)/auth/onboarding/action.ts
export async function updateUserRoleAction ({
role ,
} : {
role : "organizer" | "attendee" ;
}) : Promise < ActionResult > {
// Update user's platform role
await db
. update ( user )
. set ({
platform_role:
role === "organizer" ? PlatformRole . ORGANIZER : PlatformRole . ATTENDEE ,
})
. where ( eq ( user . id , currentUser . id ));
return {
errorMessage: null ,
message: `Role updated to ${ role } successfully!` ,
data: {
userRole: role ,
redirectPath:
role === "attendee" ? "/dashboard" : "/auth/onboarding/organizer" ,
},
};
}
You can always change your role later from your account settings.
Step 3: Create Your Workspace (Organizers Only)
If you selected “Event Organizer”, you’ll need to create a workspace:
Enter Business Details
Provide your organization name, description, and contact information
Add Social Links (Optional)
Connect your social media profiles (X/Twitter, Facebook, LinkedIn, Instagram)
Create Workspace
Click “Create Workspace” to complete the setup
Workspace Creation
// From app/(auth)/auth/onboarding/organizer/action.ts
export async function createWorkspaceAction ({
businessName ,
description ,
website ,
phone ,
social_x ,
social_facebook ,
social_linkedin ,
social_instagram ,
social_github ,
} : WorkspaceData ) : Promise < ActionResult > {
// Validate input
if ( businessName . length < 2 ) {
return {
errorMessage: "Business name must be at least 2 characters!" ,
message: null ,
};
}
// Generate unique invite code
const inviteCode =
Math . random (). toString ( 36 ). substring ( 2 , 15 ) +
Math . random (). toString ( 36 ). substring ( 2 , 15 );
// Create workspace
const [ newWorkspace ] = await db
. insert ( tables . workspace )
. values ({
name: businessName ,
description: description || undefined ,
website: website || undefined ,
phone: phone || undefined ,
social_x: social_x || undefined ,
social_facebook: social_facebook || undefined ,
social_linkedin: social_linkedin || undefined ,
social_instagram: social_instagram || undefined ,
social_github: social_github || undefined ,
image_url: "" ,
invite_code: inviteCode ,
user_id: currentUser . id ,
})
. returning ({ id: tables . workspace . id });
// Add creator as admin
await db . insert ( tables . workspace_members ). values ({
user_id: currentUser . id ,
workspace_id: newWorkspace . id ,
role: WorkspaceRole . ADMIN ,
});
return {
errorMessage: null ,
message: "Workspace created successfully!" ,
data: {
workspaceId: newWorkspace . id ,
redirectPath: `/workspace/ ${ newWorkspace . id } ` ,
},
};
}
Workspace invite codes are automatically generated and should be kept secure. Share them only with team members you want to invite.
Step 4: Create Your First Event
Now you’re ready to create your first event!
Navigate to Event Creation
Go to your workspace and click “Create Event”
Enter Event Details
Fill in the basic information:
Event title
Description (minimum 10 characters)
Event type (Physical, Online, or Hybrid)
Start and end dates
Configure Event Type
Physical Events : Add venue, country, and cityOnline Events : Add meeting link (Google Meet, Zoom, Teams, or custom)Hybrid Events : Add both venue and meeting link
Set Up Pricing
Choose between free or paid events:
Free : No charge for attendees
Paid : Requires KYC verification (ticket types, pricing, currency)
Add Optional Details
Event category
Event image
Speakers
Partners/Sponsors
Ticket types (for paid events)
Publish Event
Review and publish your event to make it live
Event Creation Schema
// Event validation schema from app/actions/events.ts
const createEventSchema = z
. object ({
title: z
. string ()
. min ( 1 , "Title is required" )
. max ( 255 , "Title must be 255 characters or less" ),
description: z
. string ()
. refine (
( val ) => getPlainTextLength ( val ) >= 10 ,
{ message: "Description must be at least 10 characters" }
),
workspaceId: z . string (). min ( 1 , "Workspace ID is required" ),
type: z . nativeEnum ( EventType ). default ( EventType . PHYSICAL ),
pricing: z . nativeEnum ( EventPricing ). default ( EventPricing . FREE ),
venue: z . string (). optional (),
country: z . string (). optional (),
city: z . string (). optional (),
startDate: z . date (),
endDate: z . date (),
meetingLink: z . string (). optional (),
})
. refine (( data ) => data . endDate > data . startDate , {
message: "End date must be after start date" ,
path: [ "endDate" ],
});
Event Data Model
// From lib/db/schema/events.ts
export const events = pgTable ( "events" , {
id: varchar ( "id" , { length: 16 }). primaryKey (),
short_id: varchar ( "short_id" , { length: 6 }). notNull (). unique (),
title: varchar ( "title" , { length: 255 }). notNull (),
status: event_status_enum ( "status" ). notNull (). default ( EventStatus . ACTIVE ),
description: text ( "description" ). notNull (),
workspace_id: varchar ( "workspace_id" , { length: 16 }). notNull (),
category_id: varchar ( "category_id" , { length: 16 }). notNull (),
type: event_type_enum ( "type" ). notNull (). default ( EventType . PHYSICAL ),
pricing: event_pricing_enum ( "pricing" ). notNull (). default ( EventPricing . FREE ),
venue: text ( "venue" ),
country: text ( "country" ),
city: text ( "city" ),
online_link: text ( "online_link" ),
start_date: timestamp ( "start_date" , { withTimezone: true }). notNull (),
end_date: timestamp ( "end_date" , { withTimezone: true }). notNull (),
is_recurring: boolean ( "is_recurring" ). notNull (). default ( false ),
});
Physical Event Example
Online Event Example
Hybrid Event Example
const physicalEvent = {
title: "Tech Conference 2026" ,
description: "<p>Join us for an amazing tech conference featuring industry leaders.</p>" ,
type: EventType . PHYSICAL ,
pricing: EventPricing . FREE ,
venue: "Convention Center" ,
country: "Kenya" ,
city: "Nairobi" ,
startDate: new Date ( "2026-06-01T09:00:00Z" ),
endDate: new Date ( "2026-06-01T17:00:00Z" ),
};
KYC Requirement for Paid Events Before creating paid events, organizers must complete KYC verification. This ensures compliance and builds trust with attendees.
Step 5: Manage Your Event
Once your event is published, you can:
View Event Dashboard : See registrations, ticket sales, and analytics
Manage Attendees : Track who’s registered and check-in status
Send Announcements : Communicate updates to registered attendees
Add Speakers : Showcase speakers with bios and social links
Monitor Sales : Track ticket sales and revenue (for paid events)
Event Management Features
Attendee Management Track registrations, send check-in codes, and manage attendee lists
Announcements Send important updates to all registered attendees
Speaker Management Add speakers with profiles, topics, and scheduled times
Analytics View event performance metrics and attendee insights
Next Steps
Customize Your Event
Add speakers, partners, and detailed schedules
Set Up Ticketing
Create multiple ticket tiers with different pricing
Promote Your Event
Share your event link and leverage social media
Monitor Registrations
Track attendee signups and send reminders
Common Operations
Update Event Status
// Event can have different statuses
export enum EventStatus {
DRAFT = "draft" ,
ACTIVE = "active" ,
CANCELLED = "cancelled" ,
COMPLETED = "completed"
}
Add Event Speakers
// From lib/db/schema/events.ts
export const events_speakers = pgTable ( "events_speakers" , {
id: varchar ( "id" , { length: 16 }). primaryKey (),
event_id: varchar ( "event_id" , { length: 16 }). notNull (),
name: varchar ( "name" , { length: 255 }). notNull (),
email: varchar ( "email" , { length: 255 }),
title: varchar ( "title" , { length: 255 }),
talk: text ( "talk" ),
bio: text ( "bio" ),
image_url: text ( "image_url" ),
twitter_handle: varchar ( "twitter_handle" , { length: 255 }),
linkedin_url: text ( "linkedin_url" ),
status: speaker_status_enum ( "status" ). notNull (). default ( SpeakerStatus . PENDING ),
scheduled_time: timestamp ( "scheduled_time" , { withTimezone: true }),
});
// From lib/db/schema/events.ts
export const events_partners = pgTable ( "events_partners" , {
id: varchar ( "id" , { length: 16 }). primaryKey (),
event_id: varchar ( "event_id" , { length: 16 }). notNull (),
name: varchar ( "name" , { length: 255 }). notNull (),
logo_url: text ( "logo_url" ),
website_url: text ( "website_url" ),
type: varchar ( "type" , { length: 50 }). notNull (). default ( "sponsor" ),
});
Troubleshooting
Email verification code not received
Check your spam folder. The verification email is sent from the configured email service. If you still don’t see it, you can request a new code from the verification page.
Paid events require KYC verification. Complete the KYC process in your workspace settings before creating paid events.
Event dates validation error
Ensure your end date is after the start date. Both dates must be in the future when creating a new event.
Permission denied when creating events
You need at least Moderator permissions in the workspace to create events. Contact your workspace admin to update your role.
For more detailed API documentation and advanced features, check out the API Reference section.