DevOps & Cloud

Netlify: Deploy & Host Modern Web

TOKEN

Panduan lengkap Netlify β€” deploy website modern dengan Git integration, serverless functions, form handling, identity authentication, edge functions, dan best practices

1. Pengenalan Netlify

Netlify adalah platform hosting dan deployment modern yang dirancang untuk web developer. Dengan Netlify, Anda bisa meng-deploy website dan web applications dari Git repository dalam hitungan detik, mendapatkan CDN global otomatis, SSL/HTTPS, serverless functions, form handling, dan fitur-fitur lain yang biasanya memerlukan konfigurasi server yang rumit.

Netlify mempopulerkan konsep JAMstack (JavaScript, APIs, Markup) β€” arsitektur web yang mengandalkan prerendering dan menyajikan konten statis dari CDN, dengan dynamic functionality ditangani oleh serverless functions atau APIs. Pendekatan ini menghasilkan website yang sangat cepat, aman, dan mudah di-scale.

Mengapa Netlify?

Keunggulan Penjelasan
Git-based DeployDeploy otomatis setiap kali push ke Git β€” zero configuration
Global CDNContent didistribusikan ke edge nodes di seluruh dunia
Free SSLHTTPS otomatis dengan Let's Encrypt untuk semua domain
Serverless FunctionsBackend logic tanpa server β€” support Node.js, Go, Rust
Form HandlingTerima form submissions tanpa backend β€” langsung di Netlify
IdentityAuthentication built-in β€” sign up, login, roles, JWT
Edge FunctionsCustom logic di edge nodes β€” ultra-low latency
Branch DeploysDeploy setiap branch ke URL terpisah untuk testing
Deploy PreviewsPreview deploy untuk setiap Pull Request
Split TestingA/B testing dengan traffic splitting antar branches
Diagram: Netlify Platform Architecture
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    NETLIFY PLATFORM                         β”‚
β”‚                                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Git Repo │────────►│  Build Pipeline              β”‚    β”‚
β”‚  β”‚ (GitHub,  β”‚         β”‚  - Install dependencies      β”‚    β”‚
β”‚  β”‚  GitLab,  β”‚         β”‚  - Run build command          β”‚    β”‚
β”‚  β”‚  Bitbucket)         β”‚  - Generate static files      β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                      β”‚                     β”‚
β”‚                                      β–Ό                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚              GLOBAL CDN                               β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚  β”‚
β”‚  β”‚  β”‚  US Edge β”‚  β”‚ EU Edge  β”‚  β”‚ Asia Edgeβ”‚           β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                            β”‚
β”‚  Features:                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Serverless  β”‚ β”‚   Forms      β”‚ β”‚   Identity       β”‚  β”‚
β”‚  β”‚  Functions   β”‚ β”‚   (built-in) β”‚ β”‚   (auth)         β”‚  β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚  Edge        β”‚ β”‚   Redirects  β”‚ β”‚   Split          β”‚  β”‚
β”‚  β”‚  Functions   β”‚ β”‚   & Headers  β”‚ β”‚   Testing        β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Perbandingan dengan Platform Lain

Fitur Netlify Vercel Cloudflare Pages
Free Tier100 GB bandwidth/bln100 GB bandwidth/blnUnlimited bandwidth
Build Minutes300 min/bln6000 min/bln500 min/bln
FunctionsServerless + EdgeServerless + EdgeWorkers
Formsβœ… Built-in❌ Tidak❌ Tidak
Identityβœ… Built-in❌ Tidak❌ Tidak
FrameworksSemua (React, Vue, dll)Next.js focusedSemua

2. Memulai dengan Netlify

Prerequisites

Bash
# Install Netlify CLI
npm install -g netlify-cli

# Atau gunakan npx (tanpa install global)
npx netlify-cli --version

# Login ke Netlify
netlify login

# Inisialisasi project baru (di dalam project directory)
netlify init

# Atau clone starter template
git clone https://github.com/netlify-templates/eleventy-base-blog my-blog
cd my-blog
npm install

Inisialisasi Project

Bash
# Inisialisasi Netlify di project yang sudah ada
cd my-project
netlify init

# Pilihan:
# βœ“ Create & configure a new site
# βœ“ Link to an existing site
# Pilih team, masukkan site name

# Atau manual: buat file netlify.toml
cat > netlify.toml << 'EOF'
[build]
  command = "npm run build"
  publish = "dist"
  functions = "netlify/functions"

[build.environment]
  NODE_VERSION = "20"

[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
EOF

3. Deploy Website

Manual Deploy

Bash
# Deploy directory langsung
netlify deploy --prod --dir=./dist

# Deploy dengan draft (preview URL)
netlify deploy --dir=./build
# Output: Deploy draft URL: https://6654abc123--my-site.netlify.app

# Setelah puas dengan preview, promote ke production
netlify deploy --prod --dir=./build

# Deploy single page app (SPA)
netlify deploy --prod --dir=./build --functions=./netlify/functions

# Lihat deploy history
netlify api listSiteDeploys --data '{ "site_id": "my-site-id" }'

netlify.toml Lengkap

TOML
# netlify.toml β€” Konfigurasi lengkap Netlify

# ====================================
# BUILD SETTINGS
# ====================================
[build]
  command = "npm run build"
  publish = "dist"
  functions = "netlify/functions"

[build.environment]
  NODE_VERSION = "20"
  NODE_ENV = "production"
  # Variabel dari Netlify UI akan di-merge otomatis

# ====================================
# CONTEXT-SPECIFIC BUILDS
# ====================================
[context.production]
  command = "npm run build:prod"

[context.deploy-preview]
  command = "npm run build:staging"

[context.branch-deploy]
  command = "npm run build:dev"

# ====================================
# REDIRECTS
# ====================================
# SPA fallback
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

# API proxy ke functions
[[redirects]]
  from = "/api/users"
  to = "/.netlify/functions/users"
  status = 200

# Wildcard API proxy
[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

# Redirect www ke non-www
[[redirects]]
  from = "https://www.mydomain.com/*"
  to = "https://mydomain.com/:splat"
  status = 301
  force = true

# Redirect old pages
[[redirects]]
  from = "/old-page"
  to = "/new-page"
  status = 301

# ====================================
# HEADERS
# ====================================
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    X-XSS-Protection = "1; mode=block"
    Referrer-Policy = "strict-origin-when-cross-origin"
    Permissions-Policy = "camera=(), microphone=(), geolocation=()"
    Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"

# Cache static assets
[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

# Cache images
[[headers]]
  for = "/images/*"
  [headers.values]
    Cache-Control = "public, max-age=86400"

# ====================================
# PLUGINS
# ====================================
[[plugins]]
  package = "@netlify/plugin-lighthouse"

[[plugins]]
  package = "netlify-plugin-submit-sitemap"
  [plugins.inputs]
    baseUrl = "https://mydomain.com"
    sitemapPath = "/sitemap.xml"

4. Git-based Deployment

Continuous Deployment

Fitur paling powerful dari Netlify adalah Git-based continuous deployment. Setiap kali Anda push ke Git repository, Netlify otomatis build dan deploy. Untuk setiap Pull Request, Netlify membuat Deploy Preview dengan URL unik yang bisa Anda review sebelum merge.

Diagram: Git-based Deployment Flow
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              GIT-BASED DEPLOYMENT FLOW                    β”‚
β”‚                                                           β”‚
β”‚  Developer                                                β”‚
β”‚  ────────                                                 β”‚
β”‚  git push main ─────────────────────────────┐             β”‚
β”‚  git push feature/a ──────────────────┐     β”‚             β”‚
β”‚  PR: feature/a ──────────────┐        β”‚     β”‚             β”‚
β”‚                              β”‚        β”‚     β”‚             β”‚
β”‚                              β–Ό        β–Ό     β–Ό             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚              NETLIFY BUILD PIPELINE                β”‚    β”‚
β”‚  β”‚                                                    β”‚    β”‚
β”‚  β”‚  Trigger: Branch push / PR                        β”‚    β”‚
β”‚  β”‚  1. Clone repo                                    β”‚    β”‚
β”‚  β”‚  2. Install dependencies (npm install)             β”‚    β”‚
β”‚  β”‚  3. Run build (npm run build)                     β”‚    β”‚
β”‚  β”‚  4. Process redirects & headers                   β”‚    β”‚
β”‚  β”‚  5. Deploy to CDN                                 β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                              β”‚                             β”‚
β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚            β–Ό                 β–Ό                 β–Ό          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ Deploy Previewβ”‚  β”‚ Branch Deployβ”‚  β”‚  Production  β”‚   β”‚
β”‚  β”‚               β”‚  β”‚              β”‚  β”‚              β”‚   β”‚
β”‚  β”‚ PR#42-preview β”‚  β”‚ feature/a    β”‚  β”‚ main         β”‚   β”‚
β”‚  β”‚ .netlify.app  β”‚  β”‚ .netlify.app β”‚  β”‚ .netlify.app β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚   Review dulu!      Testing staging     Live production   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Branch Deploy & Deploy Previews

Text
Branch Deploy URLs:
  main          β†’ my-site.netlify.app           (production)
  staging       β†’ staging--my-site.netlify.app   (branch deploy)
  dev           β†’ dev--my-site.netlify.app       (branch deploy)
  feature/blog  β†’ feature-blog--my-site.netlify.app (branch deploy)

Deploy Preview URLs (dari Pull Request):
  PR #1  β†’ deploy-preview-1--my-site.netlify.app
  PR #2  β†’ deploy-preview-2--my-site.netlify.app
  PR #3  β†’ deploy-preview-3--my-site.netlify.app

Split Testing:
  main (50%) + redesign (50%)
  Netlify CDN otomatis split traffic antar branches
  Berguna untuk A/B testing di production
πŸ’‘ Tips

Gunakan Deploy Preview untuk testing sebelum merge ke main. Anda bisa share URL preview ke team untuk review. Branch deploy juga berguna untuk environment staging β€” deploy branch staging ke URL terpisah sebelum promote ke production.

5. Serverless Functions

Netlify Functions memungkinkan Anda menjalankan backend code tanpa server. Functions berjalan di AWS Lambda di bawah permukaan, tetapi Netlify menyederhanakan deployment dan integrasi.

Membuat Function

JavaScript
// netlify/functions/hello.js
// Function sederhana β€” dipanggil via /.netlify/functions/hello

export default async (request, context) => {
  const { name = 'World' } = await request.json().catch(() => ({}));

  return new Response(
    JSON.stringify({
      message: `Hello, ${name}!`,
      timestamp: new Date().toISOString(),
      method: request.method,
      url: request.url,
      headers: Object.fromEntries(request.headers),
    }),
    {
      status: 200,
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
      },
    }
  );
};

export const config = {
  path: '/api/hello',  // Custom URL path
};

Function dengan Database

JavaScript
// netlify/functions/users.js
// CRUD API untuk users dengan PostgreSQL

import { neon } from '@neondatabase/serverless';

const sql = neon(process.env.DATABASE_URL);

export default async (request, context) => {
  try {
    switch (request.method) {
      case 'GET': {
        const users = await sql`SELECT * FROM users ORDER BY created_at DESC`;
        return Response.json({ users });
      }

      case 'POST': {
        const { name, email } = await request.json();
        const [user] = await sql`
          INSERT INTO users (name, email) VALUES (${name}, ${email})
          RETURNING *
        `;
        return Response.json({ user }, { status: 201 });
      }

      case 'PUT': {
        const { id, name, email } = await request.json();
        const [updated] = await sql`
          UPDATE users SET name = ${name}, email = ${email}
          WHERE id = ${id} RETURNING *
        `;
        return Response.json({ user: updated });
      }

      case 'DELETE': {
        const { searchParams } = new URL(request.url);
        const id = searchParams.get('id');
        await sql`DELETE FROM users WHERE id = ${id}`;
        return Response.json({ deleted: true });
      }

      default:
        return Response.json({ error: 'Method not allowed' }, { status: 405 });
    }
  } catch (error) {
    return Response.json({ error: error.message }, { status: 500 });
  }
};

export const config = {
  path: '/api/users',
};

Scheduled Functions

JavaScript
// netlify/functions/cleanup.js
// Scheduled function β€” berjalan otomatis berdasarkan cron

export default async (request, context) => {
  console.log('Running scheduled cleanup...');

  // Cleanup old data
  const result = await cleanupOldRecords();

  return new Response(
    JSON.stringify({
      message: 'Cleanup completed',
      deletedRecords: result.count,
    })
  );
};

export const config = {
  schedule: '@daily',  // Berjalan setiap hari
  // Atau: '0 */6 * * *' (setiap 6 jam)
  // Atau: '@hourly' (setiap jam)
};

Trigger Functions

JavaScript
// netlify/functions/deploy-notification.js
// Triggered setelah deploy selesai

export default async (request, context) => {
  const { site_id, deploy_id, state } = await request.json();

  if (state === 'ready') {
    console.log(`Deploy ${deploy_id} is ready!`);
    // Kirim notifikasi, update database, dll.
  }

  return new Response('OK');
};

export const config = {
  path: '/.netlify/functions/deploy-notification',
};

Memanggil Functions dari Client

JavaScript
// Dari frontend (React, Vue, vanilla JS, dll.)

// Simple GET request
const response = await fetch('/.netlify/functions/hello');
const data = await response.json();
console.log(data.message); // "Hello, World!"

// POST request dengan body
const result = await fetch('/.netlify/functions/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Budi', email: 'budi@email.com' }),
});
const newUser = await result.json();

// Dengan custom path (jika config.path diset)
const res = await fetch('/api/users');
const users = await res.json();

// Error handling
try {
  const res = await fetch('/.netlify/functions/hello', {
    method: 'POST',
    body: JSON.stringify({ name: 'Netlify' }),
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  const data = await res.json();
} catch (err) {
  console.error('Function call failed:', err);
}

6. Form Handling

Netlify Forms memungkinkan Anda menerima form submissions tanpa backend. Cukup tambahkan atribut data-netlify="true" pada HTML form, dan Netlify akan otomatis menangkap submissions. Data bisa dilihat di Netlify dashboard dan dikirim ke email/Webhook.

HTML Form dengan Netlify

HTML
<!-- Form kontak sederhana -->
<form name="contact" method="POST" data-netlify="true" netlify-honeypot="bot-field">
  <!-- Honeypot field untuk spam protection (hidden) -->
  <p class="hidden" style="display:none">
    <label>Jangan isi ini: <input name="bot-field"></label>
  </p>

  <!-- Fields -->
  <label for="name">Nama:</label>
  <input type="text" id="name" name="name" required>

  <label for="email">Email:</label>
  <input type="email" id="email" name="email" required>

  <label for="subject">Subjek:</label>
  <select id="subject" name="subject">
    <option value="general">Pertanyaan Umum</option>
    <option value="support">Dukungan Teknis</option>
    <option value="feedback">Feedback</option>
  </select>

  <label for="message">Pesan:</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <!-- File upload (optional, max 1 file per submission) -->
  <label for="attachment">Lampiran (opsional):</label>
  <input type="file" id="attachment" name="attachment" accept=".pdf,.png,.jpg">

  <button type="submit">Kirim Pesan</button>
</form>

<!-- Redirect ke halaman thank-you setelah submit -->
<!-- Bisa juga via netlify.toml: -->
<!--
  [[redirects]]
    from = "/contact"
    to = "/thank-you"
    status = 302
-->

JavaScript Form Submission (AJAX)

JavaScript
// Submit form via JavaScript (tanpa redirect)
const form = document.getElementById('contactForm');

form.addEventListener('submit', async (e) => {
  e.preventDefault();

  const formData = new FormData(form);

  try {
    const response = await fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams(formData).toString(),
    });

    if (response.ok) {
      alert('Pesan berhasil dikirim!');
      form.reset();
    } else {
      throw new Error('Gagal mengirim pesan');
    }
  } catch (error) {
    alert('Error: ' + error.message);
  }
});

7. Identity & Authentication

Netlify Identity menyediakan authentication yang terintegrasi langsung dengan site Anda. Support email/password signup, login via provider (Google, GitHub, GitLab, Bitbucket), JWT tokens, dan role-based access control.

Mengaktifkan Identity

Bash
# Aktifkan Identity via CLI
netlify sites:update --site-id my-site-id --with-identity

# Atau aktifkan via Netlify Dashboard:
# Site Settings β†’ Identity β†’ Enable Identity

# Set registration:
# - Open: Anyone can sign up
# - Invite only: Admin harus mengundang user

Menggunakan Identity di Frontend

HTML
<!-- Tambahkan Netlify Identity Widget -->
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>

<!-- Tombol login/logout (Netlify auto-inject jika diperlukan) -->
<div data-netlify-identity-button>
  Login with Netlify Identity
</div>

<script>
  // Initialize Identity
  netlifyIdentity.init({
    APIUrl: 'https://my-site.netlify.app/.netlify/identity',
    locale: 'en',
  });

  // Event listeners
  netlifyIdentity.on('init', (user) => {
    console.log('User init:', user);
  });

  netlifyIdentity.on('login', (user) => {
    console.log('User logged in:', user);
    console.log('JWT Token:', user.token.access_token);
    netlifyIdentity.close();
  });

  netlifyIdentity.on('logout', () => {
    console.log('User logged out');
    window.location.href = '/';
  });

  netlifyIdentity.on('error', (err) => {
    console.error('Identity error:', err);
  });

  // Programmatic login
  function login(email, password) {
    return netlifyIdentity.login(email, password);
  }

  // Get current user
  const currentUser = netlifyIdentity.currentUser();
  if (currentUser) {
    console.log('Logged in as:', currentUser.email);
    console.log('Roles:', currentUser.app_metadata.roles);
  }
</script>

Protecting Pages & Functions

Text
# Protect pages dengan JWT Gatekeeper
# Tambahkan di netlify.toml:

# Protect /admin pages
[[redirects]]
  from = "/admin/*"
  to = "/.netlify/functions/auth-check"
  status = 200

# Protect /dashboard pages
[[redirects]]
  from = "/dashboard/*"
  to = "/.netlify/functions/auth-check"
  status = 200

8. Edge Functions

Netlify Edge Functions berjalan di edge nodes (dekat dengan user), menggunakan Deno runtime. Edge Functions cocok untuk: A/B testing, personalization, geolocation-based content, authentication middleware, dan rewrites/redirects yang kompleks.

Membuat Edge Function

JavaScript
// netlify/edge-functions/geo-redirect.js
// Redirect user berdasarkan lokasi geografis

export default async (request, context) => {
  const country = context.geo.country?.code || 'US';
  const city = context.geo.city || 'Unknown';

  console.log(`Visitor from: ${city}, ${country}`);

  // Redirect ke halaman bahasa yang sesuai
  const localeMap = {
    ID: '/id',
    JP: '/ja',
    KR: '/ko',
    DE: '/de',
    FR: '/fr',
  };

  const locale = localeMap[country] || '/en';

  // Hanya redirect jika di halaman utama
  const url = new URL(request.url);
  if (url.pathname === '/') {
    return new Response(null, {
      status: 302,
      headers: { Location: locale },
    });
  }

  // Tambahkan header geo info
  const response = await context.next();
  response.headers.set('X-Country', country);
  response.headers.set('X-City', city);

  return response;
};

export const config = {
  path: '/*',
};

Edge Function: A/B Testing

JavaScript
// netlify/edge-functions/ab-test.js
// A/B testing di edge β€” ultra fast, zero flicker

const COOKIE_NAME = 'ab-test-variant';

export default async (request, context) => {
  // Cek apakah user sudah punya variant
  const existingVariant = context.cookies.get(COOKIE_NAME);

  if (existingVariant) {
    // User sudah di-assign variant
    return context.next();
  }

  // Assign variant baru (50:50 split)
  const variant = Math.random() < 0.5 ? 'A' : 'B';

  // Set cookie agar konsisten
  context.cookies.set({
    name: COOKIE_NAME,
    value: variant,
    httpOnly: true,
    secure: true,
    sameSite: 'Lax',
    path: '/',
    maxAge: 60 * 60 * 24 * 30, // 30 hari
  });

  // Tambahkan header untuk analytics
  const response = await context.next();
  response.headers.set('X-AB-Test', variant);

  return response;
};

export const config = {
  path: '/',
};

Edge Function: Response Transform

JavaScript
// netlify/edge-functions/personalize.js
// Inject personalized content ke halaman

export default async (request, context) => {
  const response = await context.next();
  const contentType = response.headers.get('content-type');

  // Hanya proses HTML pages
  if (!contentType?.includes('text/html')) {
    return response;
  }

  // Transform HTML response
  return new HTMLRewriter()
    .on('[data-personalize]', {
      element(element) {
        const key = element.getAttribute('data-personalize');
        if (key === 'greeting') {
          const country = context.geo.country?.name || 'World';
          element.setInnerContent(`Welcome, visitor from ${country}!`);
        }
      },
    })
    .transform(response);
};

export const config = {
  path: '/',
};

9. Custom Domains & HTTPS

Bash
# Tambah custom domain via CLI
netlify domains:add mydomain.com

# DNS Configuration:
# Type  | Name | Value
# A     | @    | 75.2.60.5
# CNAME | www  | my-site.netlify.app

# Tambah subdomain
netlify domains:add app.mydomain.com

# Cek DNS status
netlify domains:list

# HTTPS akan otomatis dikonfigurasi oleh Netlify
# Let's Encrypt certificate di-provision otomatis

# Force HTTPS (redirect HTTP ke HTTPS)
# Di Netlify Dashboard: Site Settings β†’ HTTPS β†’ Force HTTPS

# DNSSEC juga didukung
# Di Netlify Dashboard: Domain Settings β†’ Enable DNSSEC

10. Environment Variables

Bash
# Set environment variable
netlify env:set DATABASE_URL "postgres://user:pass@host/db"

# Set untuk context tertentu
netlify env:set API_KEY "prod-key-123" --context production
netlify env:set API_KEY "dev-key-456" --context dev

# Set untuk branch tertentu
netlify env:set FEATURE_FLAG "true" --scope functions --context branch:staging

# List semua environment variables
netlify env:list

# Import dari .env file
netlify env:import .env.production

# Delete environment variable
netlify env:unset DATABASE_URL

# Akses di functions
# process.env.DATABASE_URL tersedia secara otomatis

# Akses di build
# Tersedia sebagai environment variable saat build

# Scopes:
# - builds: Tersedia saat build
# - functions: Tersedia di serverless functions
# - runtime: Tersedia di edge functions
# - post_processing: Tersedia saat post-processing

11. Best Practices

Best Practice Detail
Gunakan netlify.tomlSimpan semua konfigurasi dalam version control β€” redirects, headers, build settings
Deploy PreviewReview setiap PR dengan preview sebelum merge ke main
Cache headersSet cache headers yang tepat untuk static assets (immutable) dan HTML (no-cache)
SPA redirectsSelalu tambahkan SPA fallback redirect (/* β†’ /index.html)
Honeypot formsGunakan netlify-honeypot untuk mencegah spam pada forms
Secrets di env varsJangan commit secrets β€” simpan di Netlify environment variables
Functions timeoutDefault timeout 10 detik. Untuk long-running tasks, pertimbangkan Background Functions
Image optimizationGunakan Netlify Image CDN untuk optimasi gambar otomatis
Force HTTPSSelalu aktifkan force HTTPS di production
Monitor buildsPantau build minutes dan bandwidth usage di dashboard
πŸ’‘ Tips

Netlify menyediakan free tier yang sangat generous β€” 100 GB bandwidth, 300 build menit, dan 125K serverless function calls per bulan. Ini lebih dari cukup untuk kebanyakan project personal dan startup. Upgrade ke Pro plan ($19/bln) untuk fitur lebih lanjut seperti role-based access dan priority support.

12. Quiz Pemahaman

πŸ“ Quiz: Pemahaman Netlify

1. Bagaimana cara Netlify melakukan deploy otomatis?

2. Apa fungsi atribut data-netlify="true" pada HTML form?

3. Dimana Netlify Functions berjalan?

4. Apa perbedaan antara Edge Functions dan Serverless Functions?

5. Apa itu Deploy Preview di Netlify?

πŸ” Zoom
100%
🎨 Tema