apps/docs/content/guides/functions/quickstart.mdx
Before getting started, make sure you have the Supabase CLI installed. Check out the CLI installation guide for installation methods and troubleshooting.
<Admonition type="tip" label="Prefer using the Supabase Dashboard?">You can also create and deploy functions directly from the Supabase Dashboard. Check out our Dashboard Quickstart guide.
</Admonition>If you don't have a project yet, initialize a new Supabase project in your current directory.
supabase init my-edge-functions-project
cd my-edge-functions-project
Or, if you already have a project locally, navigate to your project directory. If your project hasn't been configured for Supabase yet, make sure to run the supabase init command.
cd your-existing-project
supabase init # Initialize Supabase, if you haven't already
After this step, you should have a project directory with a supabase folder containing config.toml and an empty functions directory.
Within your project, generate a new Edge Function with a basic template:
supabase functions new hello-world
This creates a new function at supabase/functions/hello-world/index.ts with this starter code:
Deno.serve(async (req) => {
const { name } = await req.json()
const data = {
message: `Hello ${name}!`,
}
return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } })
})
This function accepts a JSON payload with a name field and returns a greeting message.
After this step, you should have a new file at supabase/functions/hello-world/index.ts containing the starter Edge Function code.
Start the local development server to test your function:
supabase start # Start all Supabase services
supabase functions serve hello-world
The supabase start command downloads Docker images, which can take a few minutes initially.
Function not starting locally?
supabase stop then supabase start to restart servicesPort already in use?
supabase statussupabase stopYour function is now running at http://localhost:54321/functions/v1/hello-world. Hot reloading is enabled, which means that the server will automatically reload when you save changes to your function code.
After this step, you should have all Supabase services running locally, and your Edge Function serving at the local URL. Keep these terminal windows open.
</Admonition>Open a new terminal and test your function with curl:
<Admonition type="tip">Need your SUPABASE_PUBLISHABLE_KEY?
Run supabase status to see your local anon key and other credentials.
curl -i --location --request POST 'http://localhost:54321/functions/v1/hello-world' \
--header 'Authorization: Bearer SUPABASE_PUBLISHABLE_KEY' \
--header 'Content-Type: application/json' \
--data '{"name":"Functions"}'
After running this curl command, you should see:
{ "message": "Hello Functions!" }
You can also try different inputs. Change "Functions" to "World" in the curl command and run it again to see the response change.
After this step, you should have successfully tested your Edge Function locally and received a JSON response with your greeting message.
</Admonition>To deploy your function globally, you need to connect your local project to a Supabase project.
<Admonition type="tip" label="Need to create new Supabase project?">Create one at database.new.
</Admonition>First, login to the CLI if you haven't already, and authenticate with Supabase. This opens your browser to authenticate with Supabase; complete the login process in your browser.
supabase login
Next, list your Supabase projects to find your project ID:
supabase projects list
Next, copy your project ID from the output, then connect your local project to your remote Supabase project. Replace YOUR_PROJECT_ID with the ID from the previous step.
supabase link --project-ref [YOUR_PROJECT_ID]
After this step, you should have your local project authenticated and linked to your remote Supabase project. You can verify this by running supabase status.
Deploy your function to Supabase's global edge network:
supabase functions deploy hello-world
# If you want to deploy all functions, run the `deploy` command without specifying a function name:
supabase functions deploy
The CLI automatically falls back to API-based deployment if Docker isn't available. You can also explicitly use API deployment with the --use-api flag:
supabase functions deploy hello-world --use-api
If you want to skip JWT verification, you can add the --no-verify-jwt flag for webhooks that don't need authentication:
supabase functions deploy hello-world --no-verify-jwt
Use --no-verify-jwt carefully. It allows anyone to invoke your function without authentication!
When the deployment is successful, your function is automatically distributed to edge locations worldwide.
<Admonition type="note">Now, you should have your Edge Function deployed and running globally at https://[YOUR_PROJECT_ID].supabase.co/functions/v1/hello-world.
š Your function is now live! Test it with your project's anon key:
curl --request POST 'https://[YOUR_PROJECT_ID].supabase.co/functions/v1/hello-world' \
--header 'Authorization: Bearer SUPABASE_PUBLISHABLE_KEY' \
--header 'Content-Type: application/json' \
--data '{"name":"Production"}'
Expected response:
{ "message": "Hello Production!" }
The SUPABASE_PUBLISHABLE_KEY is different in development and production. To get your production anon key, you can find it in your Supabase dashboard under Settings > API.
Finally, you should have a fully deployed Edge Function that you can call from anywhere in the world.
Now that your function is deployed, you can invoke it from within your app:
<Tabs scrollable size="small" type="underlined" defaultActiveId="supabase-js"
<TabPanel id="supabase-js" label="Supabase Client">
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('https://[YOUR_PROJECT_ID].supabase.co', 'YOUR_ANON_KEY')
const { data, error } = await supabase.functions.invoke('hello-world', {
body: { name: 'JavaScript' },
})
console.log(data) // { message: "Hello JavaScript!" }
const response = await fetch('https://[YOUR_PROJECT_ID].supabase.co/functions/v1/hello-world', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_ANON_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Fetch' }),
})
const data = await response.json()
console.log(data)