In this workshop, you will learn how to create your first composable website with Netlify. You'll learn features of the Netlify platform, and will deep dive into core primitives.
The site showcasing all workshop examples is available here: https://netlify-core-workshop.netlify.app
In this workshop, you will learn how to:
- Create your first site on Netlify
- Trigger builds with Git and embrace a CI/CD workflow
- Create Deploy Previews and collaborate using the Netlify Drawer
- Securely manage environment variables in the Netlify CLI and UI
- Learn about different caching and page rendering strategies
- Personalize user experiences with Netlify Edge Functions
- Read and write to a globally-distributed data store using Netlify Blobs
- Optimize images on the fly with Netlify Image CDN
Part 1: Initial setup
i. Log in to Netlify. If you haven't made an account yet, then sign up.
ii. Install the Netlify GitHub app on your org or personal GitHub account if you have not done so already.
iii. Deploy this repo to Netlify! Clicking the button below will copy the contents of this repo into a repo that you control, and create a new site that is linked to your new repo.
iv. Clone your new repo, and install dependencies locally.
git clone <new_repo_url>
cd netlify-workshop
npm i
v. Ensure you have the latest version of netlify-cli
installed globally. Then log in to the CLI, link your repo to your site, and start local dev server
npm i netlify-cli -g
netlify login
netlify link
netlify dev
💡 Learn more about getting started in our docs.
Part 2: Understanding deploy contexts and CI/CD
Create a new branch, commit changes, push the branch, and open a pull request.
git checkout -b testing
git commit -m "Changing some headings to red"
git push origin testing
You should see a link to the Deploy Preview as a comment by the Netlify bot on the pull request. Pushing to an open pull request will kick off a new build in the Continuous Integration pipeline, and you can inspect the deploy logs as the build is building and deploying.
In the Deploy Preview itself, you'll notice a floating toolbar anchored to the bottom of your screen. This is the Netlify Drawer. You and your teammates can use this to leave feedback to each other about the Deploy Preview. Any comments you make will sync back to the pull request on GitHub (or any Git service that you may use).
Back in the pull request, merge to main. This will kick off a production build. Every deploy is atomic and immutable, which makes instant rollbacks a breeze.
In your local repo, sync up with the changes from main
again:
git checkout main
git pull origin main
💡 Learn more about Git workflows and site deploys in our docs.
Part 3: Share environment variables with your team
You can securely manage and share environment variables with your teammates in both the Netlify CLI and UI. Let's start with the CLI.
It's common practice for projects to have a gitignored .env
file in the root of the repo. This one doesn't, so let's add a dummy one now:
echo "MY_API_TOKEN=asdf123456789" > .env
To share this hypothetically-sensitive value with your team, simply use the env:import
command:
netlify env:import .env
Now, when you go to Site configuration > Environment variables in the Netlify UI, you should see your environment variable that you had saved in your .env
file.
You can adjust deploy contexts and scopes in the UI, and in the CLI too.
💡 Learn more about environment variables in our docs.
Part 1: Getting acquainted with the Netlify UI
Here, we'll take a quick segue from our CLI and dev environment to showcase more features from the Netlify UI.
Part 2: High-level overview of platform primitives
These are the primitives that we'll be talking more about in Day 2 of this workshop. It's useful to understand their benefits and how they compare to one another.
- Functions
- Built on AWS Lambda
- Runs in a single region (this is configurable)
- 10s execution time (can be extended up to 26s)
- 50MB bundle size max, 6MB payload size max
- Supports streaming
- Edge Functions
- Built on Deno Deploy
- Runs on the edge, geographically close to user
- Must respond with headers within 40s
- 20MB bundle size max
- Supports streaming
- Blobs
- Built on AWS S3
- Ubiquitously available in build, functions, edge functions
- Optimized for frequent reads / infrequent writes
- Supports CRUD operations
- Deploy-specific stores
- Image CDN
- Built on Imgix
- Dynamically optimize and cache images at request-time
Netlify offers more primitives than this -- for example, you can create serverless cron jobs with Scheduled Functions, and run long-running tasks with Background Functions! But we won't dive into those topics during this workshop.
Part 1: Configuring headers, proxies, and redirects
You can configure many aspects of your site in code with the netlify.toml file.
Similar to the _redirects
file is the _headers
file. Here you can set custom headers for routes of your choosing. Inside the /public/_headers
file, and save the following:
/*
X-Frame-Options: deny
This will prevent your site from being loaded in an iframe, a technique that help your site prevent clickjacking attacks.
You can also configure both redirects and headers inside the /netlify.toml
file. Here is the netlify.toml
equivalents of the above:
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "deny"
💡 Learn more about redirects and rewrites and custom headers in our docs.
Part 2: Rendering techniques and caching strategies
🧑💻 Relevant demo and code:
- Static site generation (SSG) (src/pages/rendering-strategies/ssg.tsx)
- Server-side rendering (SSR) (src/pages/rendering-strategies/ssr.tsx)
- Stale-while-revalidate (SWR) (src/pages/rendering-strategies/swr.tsx)
- On-demand revalidation (ODR) (src/pages/rendering-strategies/odr.tsx)
💡 Learn more about caching in our docs.
Part 3: Going serverless with Functions
🧑💻 Relevant demo and code:
- Proxy to APIs (netlify/functions/dad-joke.ts)
- Combine and filter APIs (netlify/functions/platform-specific.ts)
- Streaming APIs (netlify/functions/stream.ts)
Serverless functions open a world of possibilities for running on-demand, server-side code without having to run a dedicated server.
With Netlify Functions, your serverless functions are version-controlled, built, and deployed along with the rest of your Netlify site, and we will automatically handle service discovery through our built-in API gateway. This eliminates overhead and brings the power of Deploy Previews and rollbacks to your functions.
By default, any JavaScript/TypeScript file in a site's netlify/functions
directory will become a Function available at the /.netlify/functions/{filename}
route. A simple Hello World would look like this:
// netlify/functions/hello-world.js
export default async () => {
return new Response("Hello world!");
};
Once deployed, you can visit /.netlify/functions/hello-world
to invoke your Function in production.
💡 Learn more about Functions in our docs.
Part 4: Run middleware and personalize with Edge Functions
🧑💻 Relevant demo and code:
Edge functions are like Functions, but they execute closer to where your users are. While you can reach them as you would an endpoint, they can also chain in front of any route on your site. Think of them like middleware for the CDN: they can add HTTP headers and transform responses, passing along the next request, before ultimately reaching your users.
All this dynamic processing happens in a secure runtime based on Deno directly from the worldwide network edge location closest to each user for fast response times. Plus, you have the option to cache edge function responses for even faster response times. Edge functions are version-controlled, built, and deployed along with the rest of your site. This eliminates overhead and brings the power of Deploy Previews and rollbacks to your edge functions.
💡 Learn more about Edge Functions in our docs.
Part 5: Globally persist data with Blobs
🧑💻 Relevant demo and code:
Netlify Blobs is a highly-available S3-like data store optimized for frequent reads and infrequent writes. Provisioning, configuration, and access control is handled automatically. This integrated zero-configuration solution helps you focus on building business value in your project rather than toil on setting up and scaling a separate blob storage solution.
With Blobs, you can store and retrieve unstructured data extremely easily. Blobs are ubiquitous: you can access them in the build, in functions, and in edge functions.
import { getStore } from "@netlify/blobs";
export default async (req: Request) => {
const store = getStore("ntl-workshop-todos");
if (req.method === "GET") {
const todos = await store.get("todos", { type: "json" });
return Response.json(todos || JSON.stringify([]), { status: 200 });
}
if (req.method === "PUT") {
const body = await req.json();
await store.setJSON("todos", body);
return new Response("Todos updated", { status: 200 });
}
};
💡 Learn more about Netlify Blobs in our docs.
Part 6: Optimize images at runtime with Image CDN
🧑💻 Relevant demo and code:
- Same-origin images (src/pages/primitives/image-cdn/same-origin.tsx)
- Remote images (src/pages/primitives/image-cdn/remote.tsx)
You may have experienced pain points in the past dealing with image optimizations for the web. Do you keep raw source images in a repo, and run them through sharp
or image-magick
at during the build? That would increase build time and costs significantly. Either way, you'd still need to deal with various image formats, sizing, pixel density, srcset
attributes, etc.
With Netlify Image CDN, you can transform images on demand without impacting build times. Image CDN also handles content negotiation to use the most efficient image format for the requesting client. Optimizing the size and format of your images improves both the runtime performance and reliability of your site. Transformations are integrated natively into the CDN so that repeated requests leverage layers of caching for improved performance.
To use Netlify Image CDN, simply prefix your image URLs with /.netlify/images?url=
:
- <img src="/owl.jpeg" />
+ <img src="/.netlify/images?url=/owl.jpeg" />
The next time you request that image, you'll see the format be converted on-the-fly to a more optimal compression format that your browser supports. There's no need to pre-generate images of different formats, or stuff multiple URLs in a srcset
attribute -- it's all handled at request-time, and cached on Netlify's CDN.
You can configure many other aspects of the image, such as size, fit, position, format, and quality, by passing in additional query parameters.
💡 Learn more about Image CDN in our docs.
Read these recent blog posts focused on Enterprise releases, features, and use cases.
- Netlify + AI: Why’d my deploy fail?
- Full control over caching with cache ID
- Introducing Netlify Image CDN Beta
- Introducing Netlify Blobs Beta
- Cache-tags & Purge API
- Introducing Netlify Functions 2.0
- Stale-while-revalidate & fine-grained cache control
- Elevating enterprise deployment with enhanced monorepo experience
- How I learned to stop worrying and love the Content Security Policy
- IP and Geo Restrictions for WAF Security
- Secrets Controller: Proactive security for secret keys