import { zodResolver } from '@hookform/resolvers/zod' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { useForm } from 'react-hook-form' import { Button, Card, CardContent, CardFooter, CardHeader, CardTitle, Form, FormControl, FormField, Input, } from 'ui' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { z } from 'zod' import CopyButton from '@/components/ui/CopyButton' import { DocsButton } from '@/components/ui/DocsButton' import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query' import { useCheckCNAMERecordMutation } from '@/data/custom-domains/check-cname-mutation' import { useCustomDomainCreateMutation } from '@/data/custom-domains/custom-domains-create-mutation' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { DOCS_URL } from '@/lib/constants' const schema = z.object({ domain: z.string().trim().min(1, 'A value for your custom domain is required'), }) export const CustomDomainsConfigureHostname = () => { const { ref } = useParams() const { data: project } = useSelectedProjectQuery() const { mutate: checkCNAMERecord, isPending: isCheckingRecord } = useCheckCNAMERecordMutation() const { mutate: createCustomDomain, isPending: isCreating } = useCustomDomainCreateMutation() const { data: settings } = useProjectSettingsV2Query({ projectRef: ref }) const endpoint = settings?.app_config?.endpoint const { can: canConfigureCustomDomain } = useAsyncCheckPermissions( PermissionAction.UPDATE, 'projects', { resource: { project_id: project?.id, }, } ) const form = useForm>({ resolver: zodResolver(schema as any), defaultValues: { domain: '', }, mode: 'onSubmit', reValidateMode: 'onBlur', }) const onCreateCustomDomain = async (values: z.infer) => { if (!ref) return console.error('Project ref is required') checkCNAMERecord( { domain: values.domain.trim() }, { onSuccess: () => { createCustomDomain({ projectRef: ref, customDomain: values.domain.trim() }) }, } ) } const domain = form.watch('domain') const trimmedDomain = domain.trim() const isSubmitting = isCheckingRecord || isCreating return (
Add a custom domain
( )} />

Configure a CNAME record

Set up a CNAME record for{' '} {domain ? {domain} : 'your custom domain'}{' '} resolving to{' '} {endpoint ? ( {endpoint} ) : ( "your project's API URL" )}{' '} with as low a TTL as possible. If you're using Cloudflare as your DNS provider, disable the proxy option.
{trimmedDomain.includes('.') ? ( <> Some DNS providers expect only the subdomain label{' '} {trimmedDomain.split('.')[0]}, while others accept the full hostname{' '} {trimmedDomain}. ) : ( 'Some DNS providers expect only the subdomain label, while others accept the full hostname.' )}

{form.formState.isDirty && ( )}
{!canConfigureCustomDomain && (

You need additional permissions to update your project's custom domain settings.

)}
) }