Skip to main content

Server Actions Reference

The web dashboard uses Next.js Server Actions for all server-side mutations. Every action file is marked with 'use server' and runs exclusively on the server. Actions are organized into two layers: top-level actions for authentication and global concerns, and dashboard-scoped actions under actions/dashboard/ for work, generation, and plugin operations.

File Organization

src/app/actions/
auth.ts # Login, register, logout, OAuth, password reset
email-verification.ts # (Reserved, currently empty)
notifications.ts # Notification CRUD and read status
plugins.ts # Global plugin enable/disable/settings
settings.ts # Profile, password, notification preferences, danger zone
validation.ts # Shared validation constants
dashboard/
index.ts # Re-exports oauth, works, navigation, generator
comparisons.ts # Comparison CRUD and AI config
deploy.ts # Deployment and website repository actions
works.ts # Work CRUD, import, schedule, advanced prompts
work-schedule.ts # Schedule-specific update/run/cancel
generator.ts # Item generation, update, markdown regeneration
generator-form.ts # Generator form schema fetching
items.ts # Item add/remove/update, screenshot, extraction
members.ts # Work member invite/update/remove/leave
navigation.ts # Programmatic redirect helpers
oauth.ts # Git provider and OAuth connection management
organizations.ts # Git provider organization fetching
taxonomy.ts # Category, tag, and collection CRUD

Common Patterns

All server actions follow a consistent return shape:

// Standard success/error result
interface ActionResult<T = unknown> {
success: boolean;
data?: T;
error?: string;
}

Validation: Actions use Zod schemas for input validation. Translation-aware schemas are created inside each function via getTranslations() to support i18n error messages.

Authentication Checks: Dashboard actions call getAuthFromCookie() and redirect to the login page if no user session exists.

Cache Invalidation: After mutations, actions call revalidatePath() to invalidate Next.js page caches for affected routes.

Authentication Actions

File: src/app/actions/auth.ts

ActionParametersReturnDescription
loginidentifier: string, password: string, redirectUrl: string | null{ success, error? }Validates credentials with Zod, calls authAPI.login, sets auth cookies, redirects
registerusername: string, email: string, password: string{ success, error? }Validates with min-length and regex rules, calls authAPI.register, sets cookies
logoutnone{ success }Revokes refresh token, removes cookies, redirects to login
connectProviderproviderId: OAuthProvider{ success, url?, error? }Generates OAuth state, returns provider-specific auth URL for GitHub/Google
forgotPasswordemail: string{ success, message?, error? }Sends password reset email via authAPI.forgotPassword
resetPasswordtoken: string, newPassword: string{ success, error? }Validates token and new password strength, calls authAPI.resetPassword

Password Validation Rules (applied in both register and resetPassword):

  • Minimum 6 characters
  • Must contain at least one lowercase letter
  • Must contain a number or special character
  • Cannot start with a period or newline

Settings Actions

File: src/app/actions/settings.ts

ActionParametersReturnDescription
resendVerificationEmailnone{ success, message?, error? }Sends email verification via authAPI.sendVerification
updateProfile{ username: string }{ success, data?, error? }Updates username with min-length validation
updatePassword{ currentPassword, newPassword }{ success, message?, error? }Changes password with strength validation
updateNotificationPreferences{ email: {...}, app: {...} }{ success, message?, error? }Updates email and in-app notification toggles
deleteAccountnone{ success, error? }Currently disabled -- returns error by design

Notification Actions

File: src/app/actions/notifications.ts

ActionParametersReturn TypeDescription
getNotifications{ unreadOnly?, limit?, category? }NotificationsResultFetches notification list with filters
getUnreadNotificationCountnoneUnreadCountResultReturns unread notification count
getPersistentNotificationsnoneNotificationsResultFetches critical/persistent banner notifications
markNotificationAsReadnotificationId: stringActionResultMarks single notification as read
markAllNotificationsAsReadnoneActionResultMarks all notifications as read
dismissNotificationnotificationId: stringActionResultDismisses a notification

Plugin Actions

File: src/app/actions/plugins.ts

ActionParametersReturnDescription
enablePluginpluginId, { settings?, secretSettings?, autoEnableForWorks? }ActionResultEnables a plugin for the current user
disablePluginpluginIdActionResultDisables a plugin for the current user
updatePluginSettingspluginId, { settings?, secretSettings?, metadata? }ActionResultUpdates user-level plugin configuration
enableWorkPluginworkId, pluginId, { settings?, activeCapability?, priority? }ActionResultEnables a plugin for a specific work
disableWorkPluginworkId, pluginIdActionResultDisables a work plugin
updateWorkPluginSettingsworkId, pluginId, { settings?, secretSettings?, metadata? }ActionResultUpdates work-level plugin settings
fetchModelspluginIdActionResult<any[]>Lists available AI models for a provider plugin
setActiveCapabilityworkId, pluginId, capabilityActionResultSets which capability is active for a work plugin

Work Actions

File: src/app/actions/dashboard/works.ts

This is the largest action file with 20+ exported functions covering the full work lifecycle.

ActionKey ParametersDescription
createWorkCreateWorkDtoCreates a work with slug, name, description, git/deploy providers
createWorkWithAIAIWorkOptionsAI-generated work: generates details, creates work, starts generation
updateWorkworkId, UpdateWorkDtoUpdates name, description, owner, readme config
deleteWorkworkId, DeleteWorkDto?Validates UUID, deletes work
getWorks{ search?, limit?, offset? }Paginated work list
syncWorkDataworkIdSyncs work data from git repository
analyzeRepositorysourceUrl, providerId?Analyzes a repository URL for import
importWorkImportWorkRequestImports a work from an external source
getUserRepositories{ gitProvider, page?, search?, owner?, type? }Lists user's git repositories
updateWorkScheduleworkId, UpdateWorkSchedulePayloadUpdates auto-generation schedule
getAdvancedPromptsworkIdFetches custom prompt overrides
updateAdvancedPromptsworkId, UpdateWorkAdvancedPromptsDtoUpdates 7 prompt types (max 2000 chars each)
getWebsiteSettingsworkIdFetches website configuration
updateWebsiteSettingsworkId, dataUpdates header, homepage, footer, custom menu settings
updateCommunityPrSettingsworkId, settingsToggles community PR and auto-close settings
getRepositoryVisibilityworkIdGets visibility status of data/work/website repos
toggleRepositoryVisibilityworkId, repoType, isPrivateToggles public/private for a specific repo

Generator Actions

File: src/app/actions/dashboard/generator.ts

ActionParametersDescription
generateItemsworkId, CreateItemsGeneratorDtoSanitizes inputs, validates git connection and org access, triggers generation
updateItemsworkId, UpdateItemsGeneratorDtoTriggers item update generation
regenerateMarkdownworkIdRegenerates markdown for all work items

The sanitizePluginConfig helper processes plugin config values, sanitizing string arrays and URL arrays before sending them to the API.

Item Actions

File: src/app/actions/dashboard/items.ts

ActionParametersDescription
addItemworkId, SubmitItemDtoAdds item, returns PR info and merge status
removeItemworkId, itemSlug, { reason?, create_pull_request? }Removes item with optional PR creation
updateItemworkId, UpdateItemDtoUpdates item metadata
extractItemDetailssourceUrl, existingCategories?AI-extracts item details from a URL
captureScreenshotsourceUrlCaptures a website screenshot via screenshot plugin
checkScreenshotAvailabilitynoneChecks if screenshot plugin is configured

Taxonomy Actions

File: src/app/actions/dashboard/taxonomy.ts

Full CRUD for three taxonomy types, all following the same pattern with auth checks and path revalidation:

EntityActions
CategoriescreateCategory, updateCategory, deleteCategory
TagscreateTag, updateTag, deleteTag
CollectionscreateCollection, updateCollection, deleteCollection

Comparison Actions

File: src/app/actions/dashboard/comparisons.ts

ActionParametersDescription
listComparisonsworkIdLists all comparisons for a work
getRemainingComparisonCountworkIdGets count of remaining comparisons to generate
generateNextComparisonworkIdAuto-generates the next comparison pair
generateManualComparisonworkId, itemASlug, itemBSlugGenerates comparison for specific item pair
deleteComparisonworkId, slugDeletes a comparison
getComparisonAiConfigworkIdGets AI provider and model config for comparisons
saveComparisonAiConfigworkId, { provider, model, extendedAnalysis? }Saves AI config, auto-enables plugin if needed
saveComparisonCustomPromptworkId, customPromptSaves custom comparison prompt
getAiProviderModelspluginIdLists models for an AI provider

Deploy Actions

File: src/app/actions/dashboard/deploy.ts

ActionParametersDescription
deployworkId, teamScope?Triggers deployment, verifies git provider connection
updateWebsiteRepositoryworkIdUpdates the website repository
getDeploymentTeamsworkId?Lists available deployment teams
lookupExistingDeploymentworkIdChecks for existing deployment and returns state
updateWebsiteTemplateSettingsworkId, { websiteTemplateAutoUpdate?, websiteTemplateUseBeta? }Updates template auto-update settings

File: src/app/actions/dashboard/navigation.ts

Simple redirect helpers using next-intl locale-aware routing:

redirectToWorks(); // -> /works
redirectToNewWork(); // -> /works/new
redirectToDashboard(); // -> /dashboard
redirectToSettings(); // -> /settings
redirectToAnalytics(); // -> /analytics
redirectToNotifications(); // -> /notifications

Validation Constants

File: src/app/actions/validation.ts

export const VALIDATION_RULES = {
PASSWORD_MIN_LENGTH: 6,
USERNAME_MIN_LENGTH: 3
} as const;

These constants are shared across auth.ts and settings.ts for consistent validation rules.

Error Handling Pattern

All server actions wrap API calls in try/catch blocks and return structured error responses:

try {
const result = await someAPI.method(data);
revalidatePath('/affected/route');
return { success: true, data: result };
} catch (error) {
console.error('Failed to perform action:', error);
return {
success: false,
error: error instanceof Error ? error.message : t('genericError')
};
}

Actions never throw errors to the client -- they always return a result object that the calling component can check via result.success.