diff --git a/apps/sim/app/(auth)/components/auth-background-svg.tsx b/apps/sim/app/(auth)/components/auth-background/auth-background-svg.tsx similarity index 100% rename from apps/sim/app/(auth)/components/auth-background-svg.tsx rename to apps/sim/app/(auth)/components/auth-background/auth-background-svg.tsx diff --git a/apps/sim/app/(auth)/components/auth-background.tsx b/apps/sim/app/(auth)/components/auth-background/auth-background.tsx similarity index 100% rename from apps/sim/app/(auth)/components/auth-background.tsx rename to apps/sim/app/(auth)/components/auth-background/auth-background.tsx diff --git a/apps/sim/app/(auth)/components/index.ts b/apps/sim/app/(auth)/components/index.ts new file mode 100644 index 0000000000..3ad7bcb5b7 --- /dev/null +++ b/apps/sim/app/(auth)/components/index.ts @@ -0,0 +1,4 @@ +import AuthBackground from './auth-background/auth-background' +import OauthButtons from './oauth-buttons/oauth-buttons' + +export { OauthButtons, AuthBackground } diff --git a/apps/sim/app/(auth)/components/social-login-buttons.tsx b/apps/sim/app/(auth)/components/oauth-buttons/oauth-buttons.tsx similarity index 94% rename from apps/sim/app/(auth)/components/social-login-buttons.tsx rename to apps/sim/app/(auth)/components/oauth-buttons/oauth-buttons.tsx index 7c76325b6f..719a9a1046 100644 --- a/apps/sim/app/(auth)/components/social-login-buttons.tsx +++ b/apps/sim/app/(auth)/components/oauth-buttons/oauth-buttons.tsx @@ -1,24 +1,24 @@ 'use client' import { useEffect, useState } from 'react' -import { GithubIcon, GoogleIcon } from '@/components/icons' +import { GithubIcon, GoogleIcon } from '@/components/icons/icons' import { Button } from '@/components/ui/button' import { client } from '@/lib/auth-client' -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' -interface SocialLoginButtonsProps { +interface OauthButtonsProps { githubAvailable: boolean googleAvailable: boolean callbackURL?: string isProduction: boolean } -export function SocialLoginButtons({ +export default function OauthButtons({ githubAvailable, googleAvailable, callbackURL = '/workspace', isProduction, -}: SocialLoginButtonsProps) { +}: OauthButtonsProps) { const [isGithubLoading, setIsGithubLoading] = useState(false) const [isGoogleLoading, setIsGoogleLoading] = useState(false) const [mounted, setMounted] = useState(false) diff --git a/apps/sim/app/(auth)/components/oauth-provider-checker.tsx b/apps/sim/app/(auth)/components/oauth-provider-checker.tsx deleted file mode 100644 index 43766112bb..0000000000 --- a/apps/sim/app/(auth)/components/oauth-provider-checker.tsx +++ /dev/null @@ -1,12 +0,0 @@ -'use server' - -import { env } from '@/lib/env' -import { isProd } from '@/lib/environment' - -export async function getOAuthProviderStatus() { - const githubAvailable = !!(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET) - - const googleAvailable = !!(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) - - return { githubAvailable, googleAvailable, isProduction: isProd } -} diff --git a/apps/sim/app/(auth)/layout.tsx b/apps/sim/app/(auth)/layout.tsx index fcc6570847..ba7cddcddc 100644 --- a/apps/sim/app/(auth)/layout.tsx +++ b/apps/sim/app/(auth)/layout.tsx @@ -2,7 +2,7 @@ import { useEffect } from 'react' import Nav from '@/app/(landing)/components/nav/nav' -import AuthBackground from './components/auth-background' +import AuthBackground from './components/auth-background/auth-background' // Helper to detect if a color is dark function isColorDark(hexColor: string): boolean { diff --git a/apps/sim/app/(auth)/login/login-form.tsx b/apps/sim/app/(auth)/login/login-client.tsx similarity index 95% rename from apps/sim/app/(auth)/login/login-form.tsx rename to apps/sim/app/(auth)/login/login-client.tsx index d30b03b634..0f9e1b55c3 100644 --- a/apps/sim/app/(auth)/login/login-form.tsx +++ b/apps/sim/app/(auth)/login/login-client.tsx @@ -18,9 +18,9 @@ import { client } from '@/lib/auth-client' import { quickValidateEmail } from '@/lib/email/validation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' -import { SocialLoginButtons } from '@/app/(auth)/components/social-login-buttons' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { OauthButtons } from '@/app/(auth)/components' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' const logger = createLogger('LoginForm') @@ -85,7 +85,7 @@ const validatePassword = (passwordValue: string): string[] => { return errors } -export default function LoginPage({ +function LoginFormContent({ githubAvailable, googleAvailable, isProduction, @@ -347,12 +347,13 @@ export default function LoginPage({ setResetStatus({ type: 'success', - message: 'Password reset link sent to your email', + message: '', }) setTimeout(() => { setForgotPasswordOpen(false) setResetStatus({ type: null, message: '' }) + setForgotPasswordEmail('') }, 2000) } catch (error) { logger.error('Error requesting password reset:', { error }) @@ -476,7 +477,7 @@ export default function LoginPage({ )} - )} - {resetStatus.type === 'success' && ( -
-

{resetStatus.message}

-
- )} @@ -570,3 +570,23 @@ export default function LoginPage({ ) } + +interface LoginFormProps { + githubAvailable: boolean + googleAvailable: boolean + isProduction: boolean +} + +export default function LoginForm({ + githubAvailable, + googleAvailable, + isProduction, +}: LoginFormProps) { + return ( + + ) +} diff --git a/apps/sim/app/(auth)/login/login-server.tsx b/apps/sim/app/(auth)/login/login-server.tsx new file mode 100644 index 0000000000..bc38dc6771 --- /dev/null +++ b/apps/sim/app/(auth)/login/login-server.tsx @@ -0,0 +1,20 @@ +import { env } from '@/lib/env' +import { isProd } from '@/lib/environment' +import LoginForm from '@/app/(auth)/login/login-client' + +/** + * Server component wrapper for login page + * Handles server-side OAuth provider checks + */ +export default function LoginServerWrapper() { + const githubAvailable = !!(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET) + const googleAvailable = !!(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) + + return ( + + ) +} diff --git a/apps/sim/app/(auth)/login/page.tsx b/apps/sim/app/(auth)/login/page.tsx index 91648a5e00..55e91c6d7c 100644 --- a/apps/sim/app/(auth)/login/page.tsx +++ b/apps/sim/app/(auth)/login/page.tsx @@ -1,17 +1,2 @@ -import { getOAuthProviderStatus } from '@/app/(auth)/components/oauth-provider-checker' -import LoginForm from '@/app/(auth)/login/login-form' - -// Force dynamic rendering to avoid prerender errors with search params +export { default } from '@/app/(auth)/login/login-server' export const dynamic = 'force-dynamic' - -export default async function LoginPage() { - const { githubAvailable, googleAvailable, isProduction } = await getOAuthProviderStatus() - - return ( - - ) -} diff --git a/apps/sim/app/(auth)/reset-password/page.tsx b/apps/sim/app/(auth)/reset-password/page.tsx index 8474d054e0..fa40b3addb 100644 --- a/apps/sim/app/(auth)/reset-password/page.tsx +++ b/apps/sim/app/(auth)/reset-password/page.tsx @@ -1,117 +1,2 @@ -'use client' - -import { Suspense, useEffect, useState } from 'react' -import Link from 'next/link' -import { useRouter, useSearchParams } from 'next/navigation' -import { createLogger } from '@/lib/logs/console/logger' -import { SetNewPasswordForm } from '@/app/(auth)/reset-password/reset-password-form' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' - -const logger = createLogger('ResetPasswordPage') - -function ResetPasswordContent() { - const router = useRouter() - const searchParams = useSearchParams() - const token = searchParams.get('token') - - const [isSubmitting, setIsSubmitting] = useState(false) - const [statusMessage, setStatusMessage] = useState<{ - type: 'success' | 'error' | null - text: string - }>({ - type: null, - text: '', - }) - - useEffect(() => { - if (!token) { - setStatusMessage({ - type: 'error', - text: 'Invalid or missing reset token. Please request a new password reset link.', - }) - } - }, [token]) - - const handleResetPassword = async (password: string) => { - try { - setIsSubmitting(true) - setStatusMessage({ type: null, text: '' }) - - const response = await fetch('/api/auth/reset-password', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - token, - newPassword: password, - }), - }) - - if (!response.ok) { - const errorData = await response.json() - throw new Error(errorData.message || 'Failed to reset password') - } - - setStatusMessage({ - type: 'success', - text: 'Password reset successful! Redirecting to login...', - }) - - setTimeout(() => { - router.push('/login?resetSuccess=true') - }, 1500) - } catch (error) { - logger.error('Error resetting password:', { error }) - setStatusMessage({ - type: 'error', - text: error instanceof Error ? error.message : 'Failed to reset password', - }) - } finally { - setIsSubmitting(false) - } - } - - return ( - <> -
-

- Reset your password -

-

- Enter a new password for your account -

-
- -
- -
- -
- - Back to login - -
- - ) -} - -export default function ResetPasswordPage() { - return ( - Loading...} - > - - - ) -} +export { default } from '@/app/(auth)/reset-password/reset-password' +export const dynamic = 'force-dynamic' diff --git a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx b/apps/sim/app/(auth)/reset-password/reset-password.tsx similarity index 71% rename from apps/sim/app/(auth)/reset-password/reset-password-form.tsx rename to apps/sim/app/(auth)/reset-password/reset-password.tsx index fe1377e1bc..8e51c3a35b 100644 --- a/apps/sim/app/(auth)/reset-password/reset-password-form.tsx +++ b/apps/sim/app/(auth)/reset-password/reset-password.tsx @@ -1,12 +1,18 @@ 'use client' -import { useEffect, useState } from 'react' +import { Suspense, useEffect, useState } from 'react' import { Eye, EyeOff } from 'lucide-react' +import Link from 'next/link' +import { useRouter, useSearchParams } from 'next/navigation' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' +import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' + +const logger = createLogger('ResetPasswordPage') interface RequestResetFormProps { email: string @@ -246,13 +252,8 @@ export function SetNewPasswordForm({ )} - {statusType && statusMessage && ( -
+ {statusType === 'error' && statusMessage && ( +

{statusMessage}

)} @@ -263,8 +264,114 @@ export function SetNewPasswordForm({ type='submit' className={`${buttonClass} flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`} > - {isSubmitting ? 'Resetting...' : 'Reset Password'} + {isSubmitting ? 'Resetting...' : statusType === 'success' ? 'Success!' : 'Reset Password'} ) } + +function ResetPasswordPageContent() { + const router = useRouter() + const searchParams = useSearchParams() + const token = searchParams.get('token') + + const [isSubmitting, setIsSubmitting] = useState(false) + const [statusMessage, setStatusMessage] = useState<{ + type: 'success' | 'error' | null + text: string + }>({ + type: null, + text: '', + }) + + useEffect(() => { + if (!token) { + setStatusMessage({ + type: 'error', + text: 'Invalid or missing reset token. Please request a new password reset link.', + }) + } + }, [token]) + + const handleResetPassword = async (password: string) => { + try { + setIsSubmitting(true) + setStatusMessage({ type: null, text: '' }) + + const response = await fetch('/api/auth/reset-password', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + token, + newPassword: password, + }), + }) + + if (!response.ok) { + const errorData = await response.json() + throw new Error(errorData.message || 'Failed to reset password') + } + + setStatusMessage({ + type: 'success', + text: '', + }) + + setTimeout(() => { + router.push('/login?resetSuccess=true') + }, 1500) + } catch (error) { + logger.error('Error resetting password:', { error }) + setStatusMessage({ + type: 'error', + text: error instanceof Error ? error.message : 'Failed to reset password', + }) + } finally { + setIsSubmitting(false) + } + } + + return ( + <> +
+

+ Reset your password +

+

+ Enter a new password for your account +

+
+ +
+ +
+ +
+ + Back to login + +
+ + ) +} + +export default function ResetPasswordForm() { + return ( + Loading...
} + > + + + ) +} diff --git a/apps/sim/app/(auth)/signup/page.tsx b/apps/sim/app/(auth)/signup/page.tsx index 6e0734a1f9..8480d4a8d1 100644 --- a/apps/sim/app/(auth)/signup/page.tsx +++ b/apps/sim/app/(auth)/signup/page.tsx @@ -1,21 +1,2 @@ -import { env, isTruthy } from '@/lib/env' -import { getOAuthProviderStatus } from '@/app/(auth)/components/oauth-provider-checker' -import SignupForm from '@/app/(auth)/signup/signup-form' - +export { default } from '@/app/(auth)/signup/signup-server' export const dynamic = 'force-dynamic' - -export default async function SignupPage() { - const { githubAvailable, googleAvailable, isProduction } = await getOAuthProviderStatus() - - if (isTruthy(env.DISABLE_REGISTRATION)) { - return
Registration is disabled, please contact your admin.
- } - - return ( - - ) -} diff --git a/apps/sim/app/(auth)/signup/signup-form.tsx b/apps/sim/app/(auth)/signup/signup-client.tsx similarity index 98% rename from apps/sim/app/(auth)/signup/signup-form.tsx rename to apps/sim/app/(auth)/signup/signup-client.tsx index 0dbba30255..22432d772a 100644 --- a/apps/sim/app/(auth)/signup/signup-form.tsx +++ b/apps/sim/app/(auth)/signup/signup-client.tsx @@ -11,9 +11,9 @@ import { client, useSession } from '@/lib/auth-client' import { quickValidateEmail } from '@/lib/email/validation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' -import { SocialLoginButtons } from '@/app/(auth)/components/social-login-buttons' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { OauthButtons } from '@/app/(auth)/components' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' const logger = createLogger('SignupForm') @@ -503,7 +503,7 @@ function SignupFormContent({ )} - Loading...} diff --git a/apps/sim/app/(auth)/signup/signup-server.tsx b/apps/sim/app/(auth)/signup/signup-server.tsx new file mode 100644 index 0000000000..e2dd88fada --- /dev/null +++ b/apps/sim/app/(auth)/signup/signup-server.tsx @@ -0,0 +1,25 @@ +import { env, isTruthy } from '@/lib/env' +import { isProd } from '@/lib/environment' +import SignupForm from '@/app/(auth)/signup/signup-client' + +/** + * Server component wrapper for signup page + * Handles server-side OAuth provider and registration checks + */ +export default function SignupServerWrapper() { + const githubAvailable = !!(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET) + const googleAvailable = !!(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) + const isRegistrationDisabled = isTruthy(env.DISABLE_REGISTRATION) + + if (isRegistrationDisabled) { + return
Registration is disabled, please contact your admin.
+ } + + return ( + + ) +} diff --git a/apps/sim/app/(auth)/verify/page.tsx b/apps/sim/app/(auth)/verify/page.tsx index c841e42c35..ecf5cf4915 100644 --- a/apps/sim/app/(auth)/verify/page.tsx +++ b/apps/sim/app/(auth)/verify/page.tsx @@ -1,17 +1,2 @@ -import { hasEmailService } from '@/lib/email/mailer' -import { isEmailVerificationEnabled, isProd } from '@/lib/environment' -import { VerifyContent } from '@/app/(auth)/verify/verify-content' - +export { default } from '@/app/(auth)/verify/verify-server' export const dynamic = 'force-dynamic' - -export default function VerifyPage() { - const emailServiceConfigured = hasEmailService() - - return ( - - ) -} diff --git a/apps/sim/app/(auth)/verify/verify-content.tsx b/apps/sim/app/(auth)/verify/verify-client.tsx similarity index 98% rename from apps/sim/app/(auth)/verify/verify-content.tsx rename to apps/sim/app/(auth)/verify/verify-client.tsx index a635796cc7..a27edcede0 100644 --- a/apps/sim/app/(auth)/verify/verify-content.tsx +++ b/apps/sim/app/(auth)/verify/verify-client.tsx @@ -6,14 +6,8 @@ import { Button } from '@/components/ui/button' import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp' import { cn } from '@/lib/utils' import { useVerification } from '@/app/(auth)/verify/use-verification' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' - -interface VerifyContentProps { - hasEmailService: boolean - isProduction: boolean - isEmailVerificationEnabled: boolean -} +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' function VerificationForm({ hasEmailService, @@ -250,7 +244,13 @@ function VerificationFormFallback() { ) } -export function VerifyContent({ +interface VerifyContentProps { + hasEmailService: boolean + isProduction: boolean + isEmailVerificationEnabled: boolean +} + +export default function VerifyContent({ hasEmailService, isProduction, isEmailVerificationEnabled, diff --git a/apps/sim/app/(auth)/verify/verify-server.tsx b/apps/sim/app/(auth)/verify/verify-server.tsx new file mode 100644 index 0000000000..7f42541b1c --- /dev/null +++ b/apps/sim/app/(auth)/verify/verify-server.tsx @@ -0,0 +1,19 @@ +import { hasEmailService } from '@/lib/email/mailer' +import { isEmailVerificationEnabled, isProd } from '@/lib/environment' +import VerifyContent from '@/app/(auth)/verify/verify-client' + +/** + * Server component wrapper for email verification page + * Handles server-side checks and passes results to client component + */ +export default function VerifyServerWrapper() { + const emailServiceConfigured = hasEmailService() + + return ( + + ) +} diff --git a/apps/sim/app/(landing)/components/footer/footer.tsx b/apps/sim/app/(landing)/components/footer/footer.tsx index 67a45c6283..04a9a28bb0 100644 --- a/apps/sim/app/(landing)/components/footer/footer.tsx +++ b/apps/sim/app/(landing)/components/footer/footer.tsx @@ -6,8 +6,8 @@ import { HIPAABadgeIcon, LinkedInIcon, xIcon as XIcon, -} from '@/components/icons' -import { inter } from '@/app/fonts/inter' +} from '@/components/icons/icons' +import { inter } from '@/app/styles/fonts/inter' const blocks = [ 'Agent', diff --git a/apps/sim/app/(landing)/components/hero/hero.tsx b/apps/sim/app/(landing)/components/hero/hero.tsx index 7169925df1..0d659b8d8e 100644 --- a/apps/sim/app/(landing)/components/hero/hero.tsx +++ b/apps/sim/app/(landing)/components/hero/hero.tsx @@ -31,9 +31,9 @@ import { SlackIcon, StripeIcon, SupabaseIcon, -} from '@/components/icons' +} from '@/components/icons/icons' import { LandingPromptStorage } from '@/lib/browser-storage' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/styles/fonts/soehne/soehne' import { CARD_WIDTH, IconButton, diff --git a/apps/sim/app/(landing)/components/integrations/integrations.tsx b/apps/sim/app/(landing)/components/integrations/integrations.tsx index 7bb016ea07..3e85022990 100644 --- a/apps/sim/app/(landing)/components/integrations/integrations.tsx +++ b/apps/sim/app/(landing)/components/integrations/integrations.tsx @@ -1,5 +1,5 @@ -import * as Icons from '@/components/icons' -import { inter } from '@/app/fonts/inter' +import * as Icons from '@/components/icons/icons' +import { inter } from '@/app/styles/fonts/inter' // AI models and providers const modelProviderIcons = [ diff --git a/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx b/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx index 0809e76db3..e2bc6ed9d9 100644 --- a/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx +++ b/apps/sim/app/(landing)/components/landing-pricing/landing-pricing.tsx @@ -14,7 +14,7 @@ import { import { useRouter } from 'next/navigation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' import { ENTERPRISE_PLAN_FEATURES, PRO_PLAN_FEATURES, diff --git a/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx b/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx index 883965fec1..83597ce7d9 100644 --- a/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx +++ b/apps/sim/app/(landing)/components/landing-templates/components/landing-template-preview.tsx @@ -1,4 +1,4 @@ -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' interface LandingTemplatePreviewProps { previewImage: string diff --git a/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx b/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx index 93cb74773a..dc6f643e66 100644 --- a/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx +++ b/apps/sim/app/(landing)/components/landing-templates/landing-templates.tsx @@ -1,4 +1,4 @@ -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' import LandingTemplatePreview from './components/landing-template-preview' // Mock data for templates diff --git a/apps/sim/app/(landing)/components/legal-layout.tsx b/apps/sim/app/(landing)/components/legal-layout.tsx index 7060f27348..a887bbc927 100644 --- a/apps/sim/app/(landing)/components/legal-layout.tsx +++ b/apps/sim/app/(landing)/components/legal-layout.tsx @@ -3,7 +3,7 @@ import { isHosted } from '@/lib/environment' import Footer from '@/app/(landing)/components/footer/footer' import Nav from '@/app/(landing)/components/nav/nav' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/styles/fonts/soehne/soehne' interface LegalLayoutProps { title: string diff --git a/apps/sim/app/(landing)/components/nav/nav.tsx b/apps/sim/app/(landing)/components/nav/nav.tsx index ed05a58736..71bec35677 100644 --- a/apps/sim/app/(landing)/components/nav/nav.tsx +++ b/apps/sim/app/(landing)/components/nav/nav.tsx @@ -5,12 +5,12 @@ import { ArrowRight, ChevronRight } from 'lucide-react' import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/navigation' -import { GithubIcon } from '@/components/icons' +import { GithubIcon } from '@/components/icons/icons' import { useBrandConfig } from '@/lib/branding/branding' import { isHosted } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' import { getFormattedGitHubStars } from '@/app/(landing)/actions/github' -import { soehne } from '@/app/fonts/soehne/soehne' +import { soehne } from '@/app/styles/fonts/soehne/soehne' const logger = createLogger('nav') diff --git a/apps/sim/app/(landing)/components/testimonials/testimonials.tsx b/apps/sim/app/(landing)/components/testimonials/testimonials.tsx index e3d01cc5c5..016fe0074c 100644 --- a/apps/sim/app/(landing)/components/testimonials/testimonials.tsx +++ b/apps/sim/app/(landing)/components/testimonials/testimonials.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from 'react' import Image from 'next/image' import { getAssetUrl } from '@/lib/utils' -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' interface Testimonial { text: string diff --git a/apps/sim/app/api/schedules/execute/route.ts b/apps/sim/app/api/schedules/execute/route.ts index 6d682465c6..1d859c044f 100644 --- a/apps/sim/app/api/schedules/execute/route.ts +++ b/apps/sim/app/api/schedules/execute/route.ts @@ -10,6 +10,7 @@ import { getPersonalAndWorkspaceEnv } from '@/lib/environment/utils' import { createLogger } from '@/lib/logs/console/logger' import { LoggingSession } from '@/lib/logs/execution/logging-session' import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans' +import { RateLimiter } from '@/lib/queue' import { type BlockState, calculateNextRunTime as calculateNextTime, @@ -21,7 +22,6 @@ import { loadDeployedWorkflowState } from '@/lib/workflows/db-helpers' import { updateWorkflowRunCounts } from '@/lib/workflows/utils' import { Executor } from '@/executor' import { Serializer } from '@/serializer' -import { RateLimiter } from '@/services/queue' import { mergeSubblockState } from '@/stores/workflows/server-utils' export const dynamic = 'force-dynamic' diff --git a/apps/sim/app/api/users/me/usage-limits/route.ts b/apps/sim/app/api/users/me/usage-limits/route.ts index df8804feef..dc0e13df03 100644 --- a/apps/sim/app/api/users/me/usage-limits/route.ts +++ b/apps/sim/app/api/users/me/usage-limits/route.ts @@ -4,8 +4,8 @@ import { checkServerSideUsageLimits } from '@/lib/billing' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { getEffectiveCurrentPeriodCost } from '@/lib/billing/core/usage' import { createLogger } from '@/lib/logs/console/logger' +import { RateLimiter } from '@/lib/queue' import { createErrorResponse } from '@/app/api/workflows/utils' -import { RateLimiter } from '@/services/queue' const logger = createLogger('UsageLimitsAPI') diff --git a/apps/sim/app/api/v1/logs/meta.ts b/apps/sim/app/api/v1/logs/meta.ts index df29f8ad12..ecf01610ca 100644 --- a/apps/sim/app/api/v1/logs/meta.ts +++ b/apps/sim/app/api/v1/logs/meta.ts @@ -1,7 +1,7 @@ import { checkServerSideUsageLimits } from '@/lib/billing' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { getEffectiveCurrentPeriodCost } from '@/lib/billing/core/usage' -import { RateLimiter } from '@/services/queue' +import { RateLimiter } from '@/lib/queue' export interface UserLimits { workflowExecutionRateLimit: { diff --git a/apps/sim/app/api/v1/middleware.ts b/apps/sim/app/api/v1/middleware.ts index ebf27a489b..b44407e8f5 100644 --- a/apps/sim/app/api/v1/middleware.ts +++ b/apps/sim/app/api/v1/middleware.ts @@ -1,7 +1,7 @@ import { type NextRequest, NextResponse } from 'next/server' import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription' import { createLogger } from '@/lib/logs/console/logger' -import { RateLimiter } from '@/services/queue/RateLimiter' +import { RateLimiter } from '@/lib/queue/RateLimiter' import { authenticateV1Request } from './auth' const logger = createLogger('V1Middleware') diff --git a/apps/sim/app/api/workflows/[id]/execute/route.ts b/apps/sim/app/api/workflows/[id]/execute/route.ts index fd4239e9d5..a9074809ec 100644 --- a/apps/sim/app/api/workflows/[id]/execute/route.ts +++ b/apps/sim/app/api/workflows/[id]/execute/route.ts @@ -12,6 +12,7 @@ import { getPersonalAndWorkspaceEnv } from '@/lib/environment/utils' import { createLogger } from '@/lib/logs/console/logger' import { LoggingSession } from '@/lib/logs/execution/logging-session' import { buildTraceSpans } from '@/lib/logs/execution/trace-spans/trace-spans' +import { RateLimitError, RateLimiter, type TriggerType } from '@/lib/queue' import { decryptSecret, generateRequestId } from '@/lib/utils' import { loadDeployedWorkflowState } from '@/lib/workflows/db-helpers' import { TriggerUtils } from '@/lib/workflows/triggers' @@ -24,7 +25,6 @@ import { validateWorkflowAccess } from '@/app/api/workflows/middleware' import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils' import { Executor } from '@/executor' import { Serializer } from '@/serializer' -import { RateLimitError, RateLimiter, type TriggerType } from '@/services/queue' import { mergeSubblockState } from '@/stores/workflows/server-utils' const logger = createLogger('WorkflowExecuteAPI') diff --git a/apps/sim/app/changelog/components/changelog-content.tsx b/apps/sim/app/changelog/components/changelog-content.tsx index 6fea9d5581..264b2d1588 100644 --- a/apps/sim/app/changelog/components/changelog-content.tsx +++ b/apps/sim/app/changelog/components/changelog-content.tsx @@ -1,7 +1,7 @@ import { BookOpen, Github, Rss } from 'lucide-react' import Link from 'next/link' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' import ChangelogList from './timeline-list' export interface ChangelogEntry { @@ -83,7 +83,7 @@ export default async function ChangelogContent() { Documentation diff --git a/apps/sim/app/changelog/components/timeline-list.tsx b/apps/sim/app/changelog/components/timeline-list.tsx index 4a6cb7c96b..f5ca84b824 100644 --- a/apps/sim/app/changelog/components/timeline-list.tsx +++ b/apps/sim/app/changelog/components/timeline-list.tsx @@ -3,8 +3,8 @@ import React from 'react' import ReactMarkdown from 'react-markdown' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' import type { ChangelogEntry } from './changelog-content' type Props = { initialEntries: ChangelogEntry[] } diff --git a/apps/sim/app/changelog.xml/route.ts b/apps/sim/app/changelog/feed.xml/route.ts similarity index 100% rename from apps/sim/app/changelog.xml/route.ts rename to apps/sim/app/changelog/feed.xml/route.ts diff --git a/apps/sim/app/chat/components/auth/email/email-auth.tsx b/apps/sim/app/chat/components/auth/email/email-auth.tsx index 5010ea5ccd..38409f6266 100644 --- a/apps/sim/app/chat/components/auth/email/email-auth.tsx +++ b/apps/sim/app/chat/components/auth/email/email-auth.tsx @@ -10,8 +10,8 @@ import { quickValidateEmail } from '@/lib/email/validation' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' const logger = createLogger('EmailAuth') diff --git a/apps/sim/app/chat/components/auth/password/password-auth.tsx b/apps/sim/app/chat/components/auth/password/password-auth.tsx index 74035b8cc7..19b85eadd1 100644 --- a/apps/sim/app/chat/components/auth/password/password-auth.tsx +++ b/apps/sim/app/chat/components/auth/password/password-auth.tsx @@ -8,8 +8,8 @@ import { Label } from '@/components/ui/label' import { createLogger } from '@/lib/logs/console/logger' import { cn } from '@/lib/utils' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' const logger = createLogger('PasswordAuth') diff --git a/apps/sim/app/chat/components/error-state/error-state.tsx b/apps/sim/app/chat/components/error-state/error-state.tsx index 66c8127a30..0e5f855a86 100644 --- a/apps/sim/app/chat/components/error-state/error-state.tsx +++ b/apps/sim/app/chat/components/error-state/error-state.tsx @@ -5,8 +5,8 @@ import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' import { useBrandConfig } from '@/lib/branding/branding' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' interface ChatErrorStateProps { error: string diff --git a/apps/sim/app/chat/components/header/header.tsx b/apps/sim/app/chat/components/header/header.tsx index 7c7e8b414f..d4f47ba940 100644 --- a/apps/sim/app/chat/components/header/header.tsx +++ b/apps/sim/app/chat/components/header/header.tsx @@ -2,9 +2,9 @@ import Image from 'next/image' import Link from 'next/link' -import { GithubIcon } from '@/components/icons' +import { GithubIcon } from '@/components/icons/icons' import { useBrandConfig } from '@/lib/branding/branding' -import { inter } from '@/app/fonts/inter' +import { inter } from '@/app/styles/fonts/inter' interface ChatHeaderProps { chatConfig: { diff --git a/apps/sim/app/invite/[id]/invite.tsx b/apps/sim/app/invite/[id]/invite.tsx index f82b7fa218..0f35042327 100644 --- a/apps/sim/app/invite/[id]/invite.tsx +++ b/apps/sim/app/invite/[id]/invite.tsx @@ -201,7 +201,6 @@ export default function Invite() { ? 'Create an account to join this workspace on Sim' : 'Sign in to your account to accept this invitation' } - icon='userPlus' actions={[ ...(isNewUser ? [ @@ -265,7 +264,6 @@ export default function Invite() { ? `You are currently a member of "${currentOrgName}". You must leave your current organization before accepting a new invitation.` : 'You are already a member of an organization. Leave your current organization before accepting a new invitation.' } - icon='users' actions={[ { label: 'Manage Team Settings', @@ -292,7 +290,6 @@ export default function Invite() { type='error' title='Invitation Error' description={errorMessage} - icon='error' isExpiredError={isExpiredError} actions={[ { @@ -314,7 +311,6 @@ export default function Invite() { type='success' title='Welcome!' description={`You have successfully joined ${invitationDetails?.name || 'the workspace'}. Redirecting to your workspace...`} - icon='success' actions={[ { label: 'Return to Home', @@ -334,7 +330,6 @@ export default function Invite() { invitationType === 'organization' ? 'Organization Invitation' : 'Workspace Invitation' } description={`You've been invited to join ${invitationDetails?.name || `a ${invitationType}`}. Click accept below to join.`} - icon={invitationType === 'organization' ? 'users' : 'mail'} actions={[ { label: 'Accept Invitation', diff --git a/apps/sim/app/invite/components/status-card.tsx b/apps/sim/app/invite/components/status-card.tsx index 092e182cd2..2b266b7409 100644 --- a/apps/sim/app/invite/components/status-card.tsx +++ b/apps/sim/app/invite/components/status-card.tsx @@ -1,19 +1,18 @@ 'use client' import { useEffect, useState } from 'react' -import { AlertCircle, CheckCircle2, Mail, RotateCcw, ShieldX, UserPlus, Users2 } from 'lucide-react' +import { RotateCcw } from 'lucide-react' import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' import { LoadingAgent } from '@/components/ui/loading-agent' import { useBrandConfig } from '@/lib/branding/branding' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' interface InviteStatusCardProps { type: 'login' | 'loading' | 'error' | 'success' | 'invitation' | 'warning' title: string description: string | React.ReactNode - icon?: 'userPlus' | 'mail' | 'users' | 'error' | 'success' | 'warning' actions?: Array<{ label: string onClick: () => void @@ -24,38 +23,10 @@ interface InviteStatusCardProps { isExpiredError?: boolean } -const iconMap = { - userPlus: UserPlus, - mail: Mail, - users: Users2, - error: ShieldX, - success: CheckCircle2, - warning: AlertCircle, -} - -const iconColorMap = { - userPlus: 'text-[var(--brand-primary-hex)]', - mail: 'text-[var(--brand-primary-hex)]', - users: 'text-[var(--brand-primary-hex)]', - error: 'text-red-500 dark:text-red-400', - success: 'text-green-500 dark:text-green-400', - warning: 'text-yellow-600 dark:text-yellow-500', -} - -const iconBgMap = { - userPlus: 'bg-[var(--brand-primary-hex)]/10', - mail: 'bg-[var(--brand-primary-hex)]/10', - users: 'bg-[var(--brand-primary-hex)]/10', - error: 'bg-red-50 dark:bg-red-950/20', - success: 'bg-green-50 dark:bg-green-950/20', - warning: 'bg-yellow-50 dark:bg-yellow-950/20', -} - export function InviteStatusCard({ type, title, description, - icon, actions = [], isExpiredError = false, }: InviteStatusCardProps) { @@ -114,10 +85,6 @@ export function InviteStatusCard({ ) } - const IconComponent = icon ? iconMap[icon] : null - const iconColor = icon ? iconColorMap[icon] : '' - const iconBg = icon ? iconBgMap[icon] : '' - return (
diff --git a/apps/sim/app/layout.tsx b/apps/sim/app/layout.tsx index 50bbd857b3..b2726f1048 100644 --- a/apps/sim/app/layout.tsx +++ b/apps/sim/app/layout.tsx @@ -1,16 +1,16 @@ import { Analytics } from '@vercel/analytics/next' import type { Metadata, Viewport } from 'next' import { PublicEnvScript } from 'next-runtime-env' -import { BrandedLayout } from '@/components/branded-layout' +import { BrandedLayout } from '@/components/branded-layout/branded-layout' import { generateThemeCSS } from '@/lib/branding/inject-theme' import { generateBrandedMetadata, generateStructuredData } from '@/lib/branding/metadata' import { isHosted } from '@/lib/environment' import { createLogger } from '@/lib/logs/console/logger' -import '@/app/globals.css' +import './styles/globals.css' +import { ThemeProvider } from '@/components/theme-provider/theme-provider' +import { ZoomPrevention } from '@/components/zoom-prevention/zoom-prevention' import { SessionProvider } from '@/lib/session/session-context' -import { ThemeProvider } from '@/app/theme-provider' -import { ZoomPrevention } from '@/app/zoom-prevention' const logger = createLogger('RootLayout') diff --git a/apps/sim/app/not-found.tsx b/apps/sim/app/not-found.tsx index d9756c5a70..8ba0072f34 100644 --- a/apps/sim/app/not-found.tsx +++ b/apps/sim/app/not-found.tsx @@ -3,14 +3,13 @@ import { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' -import { useBrandConfig } from '@/lib/branding/branding' +import AuthBackground from '@/app/(auth)/components/auth-background/auth-background' import Nav from '@/app/(landing)/components/nav/nav' -import { inter } from '@/app/fonts/inter' -import { soehne } from '@/app/fonts/soehne/soehne' +import { inter } from '@/app/styles/fonts/inter' +import { soehne } from '@/app/styles/fonts/soehne/soehne' export default function NotFound() { const [buttonClass, setButtonClass] = useState('auth-button-gradient') - const brandConfig = useBrandConfig() const router = useRouter() useEffect(() => { @@ -49,46 +48,39 @@ export default function NotFound() { }, []) return ( -
-