Every mutation in the kit uses Next.js Server Actions. They run server-side, use the Supabase admin client for writes (bypassing RLS), and call revalidatePath() to refresh page data.
Architecture
Client Component --> Server Action --> createClient() for auth check
--> createAdminClient() for DB writes
--> revalidatePath() --> Page Refresh
All Server Actions are in lib/actions/ and marked with "use server" at the top of each file. The kit has 17 action files.
Auth Actions (lib/actions/auth.ts)
| Action |
Parameters |
Description |
signIn |
email, password |
Sign in with email/password |
signUp |
email, password, fullName |
Create account with student role |
signOut |
-- |
Clear session and redirect to /login |
resetPassword |
email |
Send password reset email |
signInWithProvider |
provider ("google" or "github") |
Redirect to OAuth provider |
Course Actions (lib/actions/courses.ts)
| Action |
Parameters |
Description |
getCourses |
options? (status, category, search, limit) |
Filtered course list |
getCourse |
id |
Single course by ID with instructor and category |
getCourseBySlug |
slug |
Single course by slug |
getPublishedCourses |
-- |
All published courses |
getCoursesByInstructor |
instructorId? |
Courses by instructor |
getCoursesByCategory |
categorySlug |
Courses in a category |
createCourse |
title, description, price, level, etc. |
Create new course |
updateCourse |
id, data |
Update course details |
deleteCourse |
id |
Delete course |
searchCourses |
query |
Search courses by title |
getCategories |
-- |
All categories |
Lesson Actions (lib/actions/lessons.ts)
| Action |
Parameters |
Description |
getLessons |
moduleId |
Lessons for a module |
getLesson |
id |
Single lesson |
createLesson |
moduleId, data |
Create lesson |
updateLesson |
id, data |
Update lesson |
deleteLesson |
id |
Delete lesson |
completeLesson |
lessonId, courseId |
Mark lesson completed for current user |
getLessonCompletions |
courseId |
User's completed lessons for a course |
Module Actions (lib/actions/modules.ts)
| Action |
Parameters |
Description |
getModules |
courseId |
Modules for a course with lessons |
createModule |
courseId, data |
Create module |
updateModule |
id, data |
Update module |
deleteModule |
id |
Delete module |
reorderModules |
courseId, orderedIds |
Reorder modules |
Enrollment Actions (lib/actions/enrollments.ts)
| Action |
Parameters |
Description |
getEnrollments |
userId? |
User's enrollments with course data |
enrollInCourse |
courseId |
Enroll current user (checks for duplicates) |
updateProgress |
enrollmentId, progress |
Update enrollment progress |
getStudentProgress |
userId, courseId |
Enrollment + lesson completions |
getEnrolledStudents |
courseId |
Students enrolled in a course |
Quiz Actions (lib/actions/quizzes.ts)
| Action |
Parameters |
Description |
getQuiz |
id |
Single quiz with questions |
getQuizzes |
courseId |
Quizzes for a course |
createQuiz |
courseId, data |
Create quiz with JSONB questions |
updateQuiz |
id, data |
Update quiz |
deleteQuiz |
id |
Delete quiz |
submitQuizAttempt |
quizId, answers |
Score and save quiz attempt |
getQuizResults |
quizId, userId? |
Quiz results for a user |
Assignment Actions (lib/actions/assignments.ts)
| Action |
Parameters |
Description |
getAssignments |
courseId? |
Assignments with submission status |
getAssignment |
id |
Single assignment |
createAssignment |
courseId, data |
Create assignment |
updateAssignment |
id, data |
Update assignment |
deleteAssignment |
id |
Delete assignment |
submitAssignment |
assignmentId, data |
Submit assignment |
gradeSubmission |
submissionId, grade, feedback |
Grade a submission |
getSubmissions |
assignmentId |
All submissions for an assignment |
Review Actions (lib/actions/reviews.ts)
| Action |
Parameters |
Description |
getCourseReviews |
courseId |
Reviews for a course |
createReview |
courseId, data |
Submit a review |
updateReview |
id, data |
Update review |
deleteReview |
id |
Delete review |
Gamification Actions (lib/actions/gamification.ts)
| Action |
Parameters |
Description |
getCertificates |
userId? |
User's certificates |
issueCertificate |
userId, courseId |
Generate certificate |
getBadges |
-- |
All badge definitions |
getUserBadges |
userId? |
User's earned badges |
awardBadge |
userId, badgeId |
Award badge to user |
getLeaderboard |
limit? |
XP leaderboard |
getUserXp |
userId? |
User's XP and level |
awardXp |
userId, amount |
Add XP to user |
Discussion Actions (lib/actions/discussions.ts)
| Action |
Parameters |
Description |
getThreads |
options? (category, courseId) |
Discussion threads |
getThread |
id |
Single thread with replies |
createThread |
data |
Create thread |
updateThread |
id, data |
Update thread |
deleteThread |
id |
Delete thread |
getReplies |
threadId |
Replies for a thread |
createReply |
threadId, data |
Post reply |
voteThread |
id |
Upvote thread |
voteReply |
id |
Upvote reply |
markAnswer |
replyId, threadId |
Mark reply as accepted answer |
| Action |
Parameters |
Description |
getLiveSessions |
options? (status) |
Live sessions list |
getLiveSession |
id |
Single session |
createLiveSession |
data |
Schedule live session |
updateLiveSession |
id, data |
Update session |
registerForSession |
sessionId |
Register current user |
getStudyGroups |
options? (privacy) |
Study groups list |
createStudyGroup |
data |
Create study group |
joinGroup |
groupId |
Join a study group |
leaveGroup |
groupId |
Leave a study group |
Message Actions (lib/actions/messages.ts)
| Action |
Parameters |
Description |
getContacts |
-- |
All users for recipient picker |
getMessages |
options? (folder, read) |
Inbox or sent messages |
getConversation |
otherUserId |
Messages between two users |
sendMessage |
receiver_id, subject, content |
Send direct message |
markAsRead |
messageId |
Mark message as read |
deleteMessage |
id |
Delete message |
Student Actions (lib/actions/student.ts)
| Action |
Parameters |
Description |
getBookmarks |
-- |
User's bookmarks |
addBookmark |
data |
Add bookmark |
removeBookmark |
id |
Remove bookmark |
getNotes |
-- |
User's notes |
createNote |
data |
Create note |
updateNote |
id, data |
Update note |
deleteNote |
id |
Delete note |
getNotifications |
-- |
User's notifications |
markNotificationRead |
id |
Mark notification read |
markAllNotificationsRead |
-- |
Mark all read |
getUnreadNotificationCount |
-- |
Count of unread |
getCalendarEvents |
-- |
Calendar events |
Admin Actions (lib/actions/admin.ts)
| Action |
Parameters |
Description |
getApprovals |
-- |
Course approval requests |
reviewCourse |
id, status, feedback |
Approve/reject course |
getCoupons |
-- |
All coupons |
createCoupon |
data |
Create coupon |
updateCoupon |
id, data |
Update coupon |
deleteCoupon |
id |
Delete coupon |
getAnnouncements |
-- |
All announcements |
createAnnouncement |
data |
Create announcement |
updateAnnouncement |
id, data |
Update announcement |
deleteAnnouncement |
id |
Delete announcement |
Ticket Actions (lib/actions/tickets.ts)
| Action |
Parameters |
Description |
getTickets |
-- |
Support tickets |
getTicket |
id |
Single ticket with messages |
createTicket |
data |
Create support ticket |
updateTicket |
id, data |
Update ticket status |
addTicketMessage |
ticketId, content |
Add message to ticket |
getAuditLog |
-- |
Admin audit log entries |
Analytics Actions (lib/actions/analytics.ts)
| Action |
Parameters |
Description |
getStudentDashboardStats |
-- |
Student KPI stats |
getInstructorDashboardStats |
instructorId? |
Instructor KPI stats |
getAdminDashboardStats |
-- |
Platform-wide stats |
getDailyMetrics |
days? |
Daily enrollment/revenue/completion metrics |
getRevenueData |
-- |
Revenue analytics |
getInstructorRevenue |
instructorId? |
Instructor earnings |
getBillingRecords |
-- |
User's billing history |
getPaymentMethods |
-- |
User's payment methods |
addPaymentMethod |
data |
Add payment method |
Settings Actions (lib/actions/settings.ts)
| Action |
Parameters |
Description |
getSiteSettings |
-- |
Platform settings |
updateSiteSettings |
key, value |
Update a setting |
updateProfile |
data |
Update user profile |
updateAvatar |
avatarUrl |
Update avatar URL |
Supabase Client Selection
| Context |
Client |
RLS |
Auth checks (getUser()) |
Server client (createClient) |
Yes (user session) |
| Read queries |
Server client (createClient) |
Yes (user session) |
| All mutations |
Admin client (createAdminClient) |
Bypassed (service role) |
| Auth operations |
Server client (createClient) |
N/A (Supabase Auth API) |
Important: The admin client (lib/supabase/admin.ts) uses SUPABASE_SERVICE_ROLE_KEY and is used for ALL mutation operations. This pattern was chosen because the default user role is student, and RLS policies for instructor/admin tables would block mutations.
Error Handling Pattern
All Server Actions follow the same pattern:
"use server"
import { createClient } from "@/lib/supabase/server"
import { createAdminClient } from "@/lib/supabase/admin"
import { revalidatePath } from "next/cache"
export async function enrollInCourse(courseId: string) {
try {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) return { error: "Not authenticated", data: null }
const admin = createAdminClient()
// Check for duplicate
const { data: existing } = await admin
.from("enrollments")
.select("id")
.eq("user_id", user.id)
.eq("course_id", courseId)
.maybeSingle()
if (existing) return { error: null, data: existing }
const { data, error } = await admin
.from("enrollments")
.insert({ user_id: user.id, course_id: courseId, progress: 0 })
.select()
.single()
if (error) return { error: error.message, data: null }
revalidatePath("/dashboard")
return { error: null, data }
} catch (e) {
return { error: (e as Error).message, data: null }
}
}