Server Actions

Last updated on 2026-09-13

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

Community Actions (lib/actions/community.ts)

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 }
  }
}