arrow_back 바이브코딩 목록으로
2026.07.28

How to Connect a Custom Domain to Your Vibe-Coded App

A developer connects frontend and API custom domains to deployed services through DNS, domain verification, and HTTPS.

A hosting platform gives your application a working URL after deployment.

For the appointment app used throughout this series, the initial addresses might resemble:

Frontend:
https://appointment-web.onrender.com

Backend:
https://appointment-api.onrender.com

These addresses are enough for initial testing, but a public service usually benefits from a domain that belongs to the project:

Frontend:
https://appointments.example.com

Backend:
https://api.appointments.example.com

A custom domain improves recognition and gives you an address that can remain stable even if the hosting platform changes later.

Connecting the domain is not the same as transferring the application. Your code and services continue running on Render. You change the Domain Name System, or DNS, so requests for your domain are directed to those services.

That change affects more than the browser address bar. It can also affect:

  • Frontend API URLs
  • CORS rules
  • Authentication cookies
  • OAuth callback URLs
  • Password-reset links
  • Email links
  • Webhook destinations
  • Content security policies
  • Monitoring checks
  • Search-engine indexing
  • HTTPS certificates

A domain should therefore be connected as a controlled production change rather than an isolated DNS edit.

This article continues with the architecture from the previous guides:

Frontend:
- React and Vite
- Render Static Site

Backend:
- Node.js and Express
- Render Web Service

Database:
- Render PostgreSQL

Current frontend URL:
https://appointment-web.onrender.com

Current backend URL:
https://appointment-api.onrender.com

The example domain example.com is reserved for documentation. Replace it with a domain you control.

Render’s custom-domain process currently has three main stages: add the domain to the Render service, configure the required DNS records with the DNS provider, and verify the domain in Render. After verification, Render issues and renews TLS certificates and redirects HTTP requests to HTTPS.

What DNS Does

DNS connects human-readable hostnames to internet services.

A user enters:

appointments.example.com

The browser asks DNS where that hostname should go. DNS records return the information needed to reach the hosting service.

A simplified request flow is:

User enters appointments.example.com
                |
                v
        DNS provider answers
                |
                v
      Render service receives request
                |
                v
       React application is returned

The DNS provider is the service responsible for publishing the domain’s DNS records. It may be:

  • The domain registrar
  • A dedicated DNS provider
  • A CDN or security provider
  • Another company selected by the domain owner

The registrar and DNS provider can be the same company, but they do not have to be.

Before changing records, identify which provider currently manages the domain’s authoritative DNS. Editing records in the registrar’s dashboard will have no effect when the domain uses nameservers belonging to another provider.

Understand the Domain Names You Are Connecting

A domain can contain several related hostnames.

Using example.com:

Apex or root domain:
example.com

www subdomain:
www.example.com

Application subdomain:
appointments.example.com

API subdomain:
api.example.com

The apex is the domain without an additional label before it. DNS dashboards often represent it with @.

A subdomain adds a name before the apex:

api.example.com

For the sample application, a clean production structure is:

Frontend:
appointments.example.com

Backend:
api.appointments.example.com

Another valid structure is:

Frontend:
example.com

Backend:
api.example.com

The correct choice depends on whether the domain represents only this application or will host other content.

A project domain dedicated entirely to the app can use the apex:

https://example.com

A company or publication domain hosting several services may use a subdomain:

https://appointments.example.com

Choose this structure before editing DNS because it influences application configuration and certificate issuance.

Choose One Primary Frontend Address

Avoid treating every hostname as a separate public version of the site.

For example, users might reach the same site through:

https://example.com
https://www.example.com
https://appointment-web.onrender.com

Choose one primary address:

https://example.com

Then redirect alternative public hostnames to it where the platform supports that behavior.

A consistent primary address helps prevent:

  • Different cookies across hostnames
  • Inconsistent OAuth callbacks
  • Duplicate search-engine URLs
  • Confusing links in emails
  • CORS configuration mistakes
  • Users bookmarking a temporary platform address

Render automatically adds the www form when you add an apex custom domain, and it redirects one form to the other based on which domain you choose as the primary custom domain. Its current documentation recommends adding both forms when applicable and selecting the intended primary domain in the dashboard.

For an application hosted at a subdomain such as appointments.example.com, there is usually no need to create an additional www.appointments.example.com address unless you have a specific reason.

Plan the Final Domain Structure

For the appointment application, this guide uses:

Frontend:
https://appointments.example.com

Backend:
https://api.appointments.example.com

The required application settings will become:

Frontend build variable:
VITE_API_URL=https://api.appointments.example.com

Backend runtime variables:
APP_BASE_URL=https://appointments.example.com
ALLOWED_ORIGINS=https://appointments.example.com

You may also need to update:

OAuth callback:
https://appointments.example.com/auth/callback

Password reset:
https://appointments.example.com/reset-password

Webhook:
https://api.appointments.example.com/webhooks/provider

Health check:
https://api.appointments.example.com/health

Create an inventory before the DNS change. This reduces the risk that the homepage works while authentication, email links, or API requests continue using old addresses.

Back Up the Existing DNS Configuration

Before changing DNS, record the existing configuration.

Most DNS dashboards display records such as:

A
AAAA
CNAME
MX
TXT
CAA
NS

Export the zone when your provider supports it, or save a private administrative record of the existing entries.

Do not publish screenshots containing:

  • Domain-verification tokens
  • Email-service records
  • Internal hostnames
  • Private notes
  • Account identifiers

Pay particular attention to email records:

MX
SPF-related TXT records
DKIM-related records
DMARC records

Removing unrelated email records while connecting the website can interrupt email delivery even though the application itself deploys correctly.

Only modify records associated with the hostname you are connecting.

Cloudflare’s current DNS tools support creating, editing, deleting, importing, and exporting records. Its documentation also notes that record TTL influences how long cached DNS information remains valid.

Step 1: Confirm the Existing Render Services Work

Do not begin the domain change while the application is already broken.

Verify the current Render addresses:

https://appointment-web.onrender.com
https://appointment-api.onrender.com/health

Confirm:

  • The frontend loads.
  • The backend health endpoint succeeds.
  • A controlled test appointment can be created.
  • Authentication works.
  • No deployment is currently in progress.
  • The database is reachable.
  • The current deployed commit is recorded.

This gives you a known-good baseline.

If the custom domain later fails, you can separate a DNS problem from an application problem.

Step 2: Add the Frontend Domain in Render

Open the Render dashboard and select the frontend Static Site.

Navigate to its custom-domain settings and add:

appointments.example.com

Do not create the DNS record first and assume Render will detect it automatically. Render’s documented workflow begins by adding the custom domain to the service, then configuring DNS, and finally verifying it in the dashboard.

Render will display the DNS target or record values required for that hostname.

For a non-root hostname, the configuration commonly uses a CNAME record pointing to the service’s onrender.com hostname. Render’s DNS-provider guidance distinguishes root domains from non-root domains and instructs users to follow the exact record values presented for their provider and service.

Record the required value without copying unrelated dashboard secrets.

An illustrative record might be:

Type:
CNAME

Name:
appointments

Target:
appointment-web.onrender.com

Use the exact target Render shows for your service.

Step 3: Create the Frontend DNS Record

Open the dashboard of the provider that manages the domain’s DNS.

Create the record Render requested:

Type: CNAME
Name: appointments
Target: appointment-web.onrender.com
TTL: provider default

DNS providers use different field labels.

The name might appear as:

appointments

or:

appointments.example.com

The target may be called:

Target
Value
Content
Destination
Points to

Do not enter:

https://appointment-web.onrender.com

A CNAME target is a hostname, not a complete URL. It should not include:

  • https://
  • A path
  • A query string
  • A trailing page route

Correct:

appointment-web.onrender.com

Incorrect:

https://appointment-web.onrender.com/

Cloudflare’s DNS documentation describes CNAME records as records that direct a hostname to another hostname. When Cloudflare manages DNS, A, AAAA, and CNAME records can also have a proxy status that changes whether traffic passes through Cloudflare.

Step 4: Add the Backend Domain

Open the Render Web Service for the Express backend.

Add:

api.appointments.example.com

Render will display the required DNS configuration.

Create the corresponding DNS record:

Type: CNAME
Name: api.appointments
Target: appointment-api.onrender.com
TTL: provider default

Again, use the actual target displayed by Render.

Do not point the API hostname to the frontend service. The two DNS records should map to their respective services:

appointments.example.com
        |
        v
Frontend Static Site

api.appointments.example.com
        |
        v
Backend Web Service

Every Render Web Service already has an onrender.com hostname and can also accept verified custom domains.

Step 5: Handle Cloudflare Proxying Carefully

Cloudflare DNS records can be either:

Proxied
Traffic passes through Cloudflare

DNS only
DNS points directly to the hosting service

When connecting a Render domain through Cloudflare, follow Render’s current Cloudflare-specific instructions rather than selecting a proxy mode by habit.

Render’s current Cloudflare guide instructs users to configure Cloudflare’s SSL/TLS encryption mode as Full and create the required CNAME pointing to the Render service.

An incorrect proxy or TLS configuration can cause:

  • Redirect loops
  • Certificate errors
  • Domain-verification failure
  • Requests reaching the wrong service
  • Confusing HTTP-to-HTTPS behavior

Do not use an insecure encryption mode merely to make an error disappear. Diagnose the connection among the browser, Cloudflare, and Render.

When initially troubleshooting domain verification, compare the provider-specific Render instructions with the DNS record currently published.

Step 6: Verify Both Domains in Render

Return to each Render service and use the domain-verification action.

Verify:

appointments.example.com
api.appointments.example.com

Render checks whether DNS points the hostname to the correct service. If verification succeeds, it issues a TLS certificate for the domain. If verification fails immediately after a record change, DNS caches may still contain the old record.

Do not repeatedly delete and recreate the record after only a few seconds. That can make troubleshooting harder.

Instead, confirm:

  • The hostname is spelled correctly.
  • The correct DNS provider was edited.
  • The record type matches Render’s instruction.
  • The target contains no https://.
  • No conflicting record uses the same hostname.
  • The CNAME points to the correct Render service.
  • Cloudflare proxy settings match Render’s guidance.
  • The domain has been added to the correct Render service.

Cloudflare documents that CNAME records have special same-name restrictions and may conflict with other records using that hostname.

Step 7: Wait for DNS to Propagate

DNS updates do not always appear everywhere at the same moment.

Resolvers cache records according to their TTL and other DNS behavior. Cloudflare describes TTL as the period a DNS record remains valid in cache, which affects how quickly changes reach users.

Check the record from your terminal:

dig appointments.example.com
dig api.appointments.example.com

On systems without dig, try:

nslookup appointments.example.com
nslookup api.appointments.example.com

You are looking for evidence that:

appointments.example.com

resolves toward the frontend target, while:

api.appointments.example.com

resolves toward the backend target.

DNS tools may display intermediate aliases or resolved IP addresses depending on the provider.

When Cloudflare uses CNAME flattening, a DNS lookup may return Cloudflare or resolved IP addresses instead of displaying the original CNAME in the way you expect. Cloudflare currently supports flattening at the zone apex and applies it automatically for apex CNAME records.

Do not diagnose DNS by browser behavior alone. Browsers, operating systems, routers, and internet providers may each cache earlier results.

Step 8: Confirm HTTPS Is Active

After verification, open:

https://appointments.example.com
https://api.appointments.example.com/health

Render automatically provisions and renews TLS certificates for custom domains and redirects HTTP requests to HTTPS. Its static-site documentation states that it currently uses Let’s Encrypt and Google Trust Services for managed certificate issuance.

Also test the HTTP versions:

http://appointments.example.com
http://api.appointments.example.com/health

They should redirect to HTTPS.

Check:

  • The browser reports a secure HTTPS connection.
  • The certificate covers the exact hostname.
  • There is no certificate-name mismatch.
  • The redirect does not loop.
  • The backend health endpoint responds.
  • The frontend assets load over HTTPS.

A TLS certificate confirms that the connection is encrypted and that the certificate issuer validated control of the domain according to its certificate process. It does not prove that the application itself is safe, trustworthy, or free from vulnerabilities.

The next article in this series explains HTTPS and TLS in more detail.

Step 9: Update the Frontend API URL

The current frontend build may still call:

https://appointment-api.onrender.com

Change the Render Static Site’s build variable:

VITE_API_URL=https://api.appointments.example.com

Because Vite substitutes VITE_ variables during the build, create a new frontend build after changing the value.

Do not store a private API key in this variable. The API hostname is public configuration and will be visible in the browser bundle.

After the deployment finishes:

  1. Open the frontend.
  2. Open browser developer tools.
  3. Select the Network panel.
  4. Create a controlled test request.
  5. Confirm it goes to:
https://api.appointments.example.com
  1. Confirm no request goes to localhost or the old Render API hostname.

The old Render hostname may remain reachable, but the public frontend should use the custom API hostname consistently.

Step 10: Update Backend Origins and Public URLs

Update the backend environment:

APP_BASE_URL=https://appointments.example.com
ALLOWED_ORIGINS=https://appointments.example.com

When both the old and new frontend addresses must work temporarily during the transition, you may use a controlled list:

ALLOWED_ORIGINS=https://appointments.example.com,https://appointment-web.onrender.com

Remove the temporary old origin after the migration is verified unless it remains intentionally supported.

The Express CORS configuration might parse the list:

const allowedOrigins = new Set(
  (process.env.ALLOWED_ORIGINS || "")
    .split(",")
    .map((origin) => origin.trim())
    .filter(Boolean)
);

Do not use:

ALLOWED_ORIGINS=*

to avoid diagnosing a configuration problem in an authenticated application.

CORS does not replace server-side authorization. A request from an allowed origin can still be unauthorized.

Restart or redeploy the backend after updating runtime variables.

Step 11: Review Cookie Configuration

Authentication cookies are sensitive to domain and HTTPS settings.

An illustrative Express session configuration is:

app.set("trust proxy", 1);

app.use(
  session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
      httpOnly: true,
      secure: true,
      sameSite: "lax"
    }
  })
);

This example is not a universal configuration.

Your correct settings depend on:

  • Whether frontend and backend are considered the same site
  • Whether cross-site requests are required
  • Whether a reverse proxy terminates TLS
  • How authentication is implemented
  • Which browsers must be supported
  • Whether a cookie needs a specific domain

Avoid setting an unnecessarily broad cookie domain:

.example.com

A broad domain can make the cookie available to more subdomains than required.

When possible, use a host-only cookie rather than sharing authentication across every subdomain.

After the change:

  • Sign in through the custom domain.
  • Refresh the page.
  • Open a protected route.
  • Sign out.
  • Confirm the session is removed.
  • Check that cookies are marked Secure and HttpOnly where appropriate.
  • Confirm no session cookie is transmitted over HTTP.

Step 12: Update Authentication Providers

OAuth providers usually require an allowlist of callback URLs.

Update provider settings from:

https://appointment-web.onrender.com/auth/callback

to:

https://appointments.example.com/auth/callback

During a controlled transition, the provider may allow both addresses temporarily.

Review:

  • Authorized redirect URLs
  • Allowed JavaScript origins
  • Logout URLs
  • Webhook URLs
  • Application homepage
  • Privacy-policy URL
  • Terms-of-service URL

An exact hostname, protocol, path, or trailing-slash mismatch can cause authentication failure.

Do not add broad wildcard callbacks merely to avoid entering each environment’s URL. A permissive callback configuration can introduce account-security risks.

Staging and production should use separate OAuth applications or clearly separated callback configurations when practical.

Step 13: Update Emails and External Integrations

Search the code and provider dashboards for the old Render hostnames:

git grep -n "onrender.com"

The old URL may appear in:

  • Appointment confirmation links
  • Password-reset emails
  • Account-verification emails
  • Calendar invitations
  • Webhook registrations
  • Storage CORS policies
  • Monitoring checks
  • Analytics configuration
  • Support templates
  • Documentation
  • QR codes

Use environment-based URL construction:

const confirmationUrl =
  `${config.appBaseUrl}/appointments/${appointment.id}`;

Do not derive security-sensitive links from an untrusted incoming Host header without validation. Use an approved application base URL from server configuration.

Trigger controlled test messages and confirm every link points to the new HTTPS domain.

Step 14: Decide What to Do With the Old Render URLs

Render-provided hostnames may remain reachable after a custom domain is added.

That can be useful as a platform fallback, but it can also create multiple public entry points.

At minimum:

  • Use the custom domain in all public links.
  • Use the custom domain in API configuration.
  • Use the custom domain in authentication callbacks.
  • Use the custom domain in monitoring.
  • Avoid publishing the old URL.
  • Decide whether alternate-host redirects are required.
  • Ensure authorization does not depend on the hostname being obscure.

Do not treat the old onrender.com URL as a secret. Anyone who knows or discovers it may be able to access it.

Security must come from authentication, authorization, input validation, and service configuration—not from hiding the platform hostname.

Step 15: Test the Complete Domain Migration

Run a structured verification.

DNS verification

Confirm:

appointments.example.com

resolves to the frontend service.

Confirm:

api.appointments.example.com

resolves to the backend service.

Confirm no conflicting DNS record exists for either hostname.

HTTPS verification

Open both HTTPS addresses.

Confirm:

  • The certificate is valid.
  • The hostname matches the certificate.
  • HTTP redirects to HTTPS.
  • No redirect loop occurs.
  • No mixed-content warning appears.

Frontend verification

Confirm:

  • The homepage loads.
  • JavaScript and CSS load.
  • Client-side routes work after direct navigation.
  • Refreshing a nested route does not produce an unexpected 404.
  • The browser uses the custom API domain.

Backend verification

Confirm:

  • /health succeeds.
  • Invalid input returns a controlled error.
  • Logs identify requests without exposing secrets.
  • CORS accepts only intended frontend origins.
  • Authentication and authorization remain enforced.

End-to-end verification

Create a synthetic appointment.

Confirm:

  • The database record is created once.
  • The frontend displays the result.
  • A duplicate booking is rejected.
  • Generated links use the custom domain.
  • Test email links use HTTPS.
  • Logout and sign-in work after a browser refresh.

Environment verification

Confirm:

  • Staging still uses staging domains.
  • Production uses production domains.
  • Staging callbacks do not point to production.
  • Production credentials were not copied into another environment.

Connecting an Apex Domain

You may prefer:

https://example.com

instead of:

https://appointments.example.com

An apex domain requires different DNS handling because traditional DNS rules do not normally use a standard CNAME at the zone root in the same way as a subdomain.

Providers solve this in different ways:

  • A records
  • ALIAS records
  • ANAME records
  • CNAME flattening
  • Provider-specific apex handling

Render’s Namecheap guide currently instructs users to create A records for root custom domains and CNAME records for non-root domains. Cloudflare supports apex CNAME behavior through CNAME flattening.

Do not copy the record type from a tutorial using a different DNS provider. Follow the exact Render instructions shown for your custom domain and DNS provider.

When adding the apex to Render, also review the related www hostname and select which one should be primary.

Common Custom-Domain Problems

Render cannot verify the domain

Check:

  • You edited the authoritative DNS provider.
  • The hostname is correct.
  • The target contains no URL protocol.
  • The record points to the correct Render service.
  • No old record conflicts with it.
  • The DNS update has propagated.
  • Proxy settings match provider-specific instructions.

The frontend loads, but API calls fail

The frontend may still use the old API URL, or the backend may reject the new origin.

Check:

VITE_API_URL
ALLOWED_ORIGINS
APP_BASE_URL

Rebuild the frontend after changing VITE_API_URL.

The browser reports a certificate error

Confirm:

  • Render verified the exact hostname.
  • The certificate was issued for that hostname.
  • DNS points to the correct service.
  • Cloudflare’s encryption mode matches Render’s guidance.
  • An old proxy or forwarding rule is not intercepting traffic.

Do not disable HTTPS validation.

HTTP causes a redirect loop

A proxy and hosting platform may both be applying incompatible redirects.

For Cloudflare with Render, review the current Render Cloudflare guide and use Full encryption mode rather than weakening transport security.

Authentication stops working

Review:

  • OAuth callbacks
  • Cookie settings
  • Trusted proxy configuration
  • CORS origin
  • Frontend request credentials
  • Session storage
  • Logout URLs

The problem may be domain-specific even when the application code did not change.

Emails still contain the old URL

The email process may use a separate worker or environment variable.

Update the configuration of every component that generates links, then restart or redeploy those components.

The apex works, but www does not

Add and verify both hostnames where appropriate, then configure one as the primary domain.

DNS changes broke email

A required MX or TXT record may have been removed while editing the zone.

Restore it from the DNS backup and verify the email provider’s current setup.

AI Prompt for Reviewing a Custom-Domain Change

Goal:
Review this application before connecting custom production domains.

Application:
- React and Vite frontend
- Node.js and Express backend
- PostgreSQL database
- Render Static Site
- Render Web Service

Current URLs:
- Frontend: [current Render URL]
- Backend: [current Render URL]

Planned URLs:
- Frontend: [new custom domain]
- Backend: [new API domain]

Constraints:
- Do not change DNS records.
- Do not request registrar or DNS account credentials.
- Do not request production secrets.
- Do not weaken HTTPS.
- Do not allow every CORS origin.
- Do not create wildcard OAuth callbacks.
- Do not delete email-related DNS records.
- Do not assume a certificate proves the app is secure.
- Identify required changes before editing files.

Review:
1. Frontend API URLs
2. Backend public base URL
3. CORS allowlist
4. Cookie configuration
5. OAuth callback URLs
6. Password-reset and confirmation links
7. Webhook destinations
8. Content security policy
9. Storage CORS configuration
10. Monitoring URLs
11. References to old hosting domains
12. Staging and production separation
13. DNS records that must not be removed
14. Post-change verification
15. Rollback steps

Expected output:
- Affected files and platform settings
- Proposed changes without applying them
- DNS-independent code changes
- Required rebuilds and restarts
- Verification sequence
- Risks requiring manual review

Do not provide an AI assistant with domain-registrar credentials, DNS API tokens, certificate private keys, or unrestricted screenshots of the DNS dashboard.

Custom Domain Checklist

  • The current Render frontend works before the DNS change.
  • The current Render backend works before the DNS change.
  • The deployed commit is recorded.
  • The authoritative DNS provider has been identified.
  • Existing DNS records have been exported or documented.
  • Email-related DNS records will not be removed.
  • One primary frontend hostname has been selected.
  • The backend API hostname has been selected.
  • Staging and production use different hostnames.
  • The frontend domain has been added to the correct Render service.
  • The backend domain has been added to the correct Render service.
  • DNS records match the exact values shown by Render.
  • CNAME targets contain no https:// prefix.
  • The frontend DNS record points to the frontend service.
  • The API DNS record points to the backend service.
  • No conflicting record uses the same hostname.
  • Cloudflare settings follow Render’s current guidance where applicable.
  • Both domains have been verified in Render.
  • DNS resolution has been checked independently of the browser.
  • HTTPS works for the frontend.
  • HTTPS works for the backend.
  • HTTP redirects to HTTPS.
  • The certificate covers the exact hostname.
  • No redirect loop occurs.
  • The frontend build uses the custom API URL.
  • The frontend has been rebuilt after changing its API URL.
  • The backend allows only intended frontend origins.
  • The backend public base URL uses the custom domain.
  • Authentication cookies have been reviewed.
  • OAuth callback URLs have been updated.
  • Logout and password-reset URLs have been updated.
  • Webhook destinations have been reviewed.
  • Email links use the custom HTTPS domain.
  • Monitoring checks use the custom domain.
  • The repository has been searched for old hosting URLs.
  • A valid synthetic appointment can be created.
  • Duplicate-booking protection still works.
  • Authentication and authorization still work.
  • Staging configuration was not changed accidentally.
  • The old platform URL is not treated as secret.
  • The DNS rollback information is documented.
  • The final production URLs are recorded in deployment notes.