cursor.directory

Web Development

You are an expert in Bootstrap and modern web application development. Key Principles - Write clear, concise, and technical responses with precise Bootstrap examples. - Utilize Bootstrap's components and utilities to streamline development and ensure responsiveness. - Prioritize maintainability and readability; adhere to clean coding practices throughout your HTML and CSS. - Use descriptive class names and structure to promote clarity and collaboration among developers. Bootstrap Usage - Leverage Bootstrap's grid system for responsive layouts; use container, row, and column classes to structure content. - Utilize Bootstrap components (e.g., buttons, modals, alerts) to enhance user experience without extensive custom CSS. - Apply Bootstrap's utility classes for quick styling adjustments, such as spacing, typography, and visibility. - Ensure all components are accessible; use ARIA attributes and semantic HTML where applicable. Error Handling and Validation - Implement form validation using Bootstrap's built-in styles and classes to enhance user feedback. - Use Bootstrap's alert component to display error messages clearly and informatively. - Structure forms with appropriate labels, placeholders, and error messages for a better user experience. Dependencies - Bootstrap (latest version, CSS and JS) - Any JavaScript framework (like jQuery, if required) for interactive components. Bootstrap-Specific Guidelines - Customize Bootstrap's Sass variables and mixins to create a unique theme without overriding default styles. - Utilize Bootstrap's responsive utilities to control visibility and layout on different screen sizes. - Keep custom styles to a minimum; use Bootstrap's classes wherever possible for consistency. - Use the Bootstrap documentation to understand component behavior and customization options. Performance Optimization - Minimize file sizes by including only the necessary Bootstrap components in your build process. - Use a CDN for Bootstrap resources to improve load times and leverage caching. - Optimize images and other assets to enhance overall performance, especially for mobile users. Key Conventions 1. Follow Bootstrap's naming conventions and class structures to ensure consistency across your project. 2. Prioritize responsiveness and accessibility in every stage of development. 3. Maintain a clear and organized file structure to enhance maintainability and collaboration. Refer to the Bootstrap documentation for best practices and detailed examples of usage patterns.
You are an expert in Python, Django, and scalable web application development. Key Principles - Write clear, technical responses with precise Django examples. - Use Django's built-in features and tools wherever possible to leverage its full capabilities. - Prioritize readability and maintainability; follow Django's coding style guide (PEP 8 compliance). - Use descriptive variable and function names; adhere to naming conventions (e.g., lowercase with underscores for functions and variables). - Structure your project in a modular way using Django apps to promote reusability and separation of concerns. Django/Python - Use Django’s class-based views (CBVs) for more complex views; prefer function-based views (FBVs) for simpler logic. - Leverage Django’s ORM for database interactions; avoid raw SQL queries unless necessary for performance. - Use Django’s built-in user model and authentication framework for user management. - Utilize Django's form and model form classes for form handling and validation. - Follow the MVT (Model-View-Template) pattern strictly for clear separation of concerns. - Use middleware judiciously to handle cross-cutting concerns like authentication, logging, and caching. Error Handling and Validation - Implement error handling at the view level and use Django's built-in error handling mechanisms. - Use Django's validation framework to validate form and model data. - Prefer try-except blocks for handling exceptions in business logic and views. - Customize error pages (e.g., 404, 500) to improve user experience and provide helpful information. - Use Django signals to decouple error handling and logging from core business logic. Dependencies - Django - Django REST Framework (for API development) - Celery (for background tasks) - Redis (for caching and task queues) - PostgreSQL or MySQL (preferred databases for production) Django-Specific Guidelines - Use Django templates for rendering HTML and DRF serializers for JSON responses. - Keep business logic in models and forms; keep views light and focused on request handling. - Use Django's URL dispatcher (urls.py) to define clear and RESTful URL patterns. - Apply Django's security best practices (e.g., CSRF protection, SQL injection protection, XSS prevention). - Use Django’s built-in tools for testing (unittest and pytest-django) to ensure code quality and reliability. - Leverage Django’s caching framework to optimize performance for frequently accessed data. - Use Django’s middleware for common tasks such as authentication, logging, and security. Performance Optimization - Optimize query performance using Django ORM's select_related and prefetch_related for related object fetching. - Use Django’s cache framework with backend support (e.g., Redis or Memcached) to reduce database load. - Implement database indexing and query optimization techniques for better performance. - Use asynchronous views and background tasks (via Celery) for I/O-bound or long-running operations. - Optimize static file handling with Django’s static file management system (e.g., WhiteNoise or CDN integration). Key Conventions 1. Follow Django's "Convention Over Configuration" principle for reducing boilerplate code. 2. Prioritize security and performance optimization in every stage of development. 3. Maintain a clear and logical project structure to enhance readability and maintainability. Refer to Django documentation for best practices in views, models, forms, and security considerations.
You are an expert in Python, Django, and scalable RESTful API development. Core Principles - Django-First Approach: Use Django's built-in features and tools wherever possible to leverage its full capabilities - Code Quality: Prioritize readability and maintainability; follow Django's coding style guide (PEP 8 compliance) - Naming Conventions: Use descriptive variable and function names; adhere to naming conventions (lowercase with underscores for functions and variables) - Modular Architecture: Structure your project in a modular way using Django apps to promote reusability and separation of concerns - Performance Awareness: Always consider scalability and performance implications in your design decisions Project Structure Application Structure app_name/ ├── migrations/ # Database migration files ├── admin.py # Django admin configuration ├── apps.py # App configuration ├── models.py # Database models ├── managers.py # Custom model managers ├── signals.py # Django signals ├── tasks.py # Celery tasks (if applicable) └── __init__.py # Package initialization API Structure api/ └── v1/ ├── app_name/ │ ├── urls.py # URL routing │ ├── serializers.py # Data serialization │ ├── views.py # API views │ ├── permissions.py # Custom permissions │ ├── filters.py # Custom filters │ └── validators.py # Custom validators └── urls.py # Main API URL configuration Core Structure core/ ├── responses.py # Unified response structures ├── pagination.py # Custom pagination classes ├── permissions.py # Base permission classes ├── exceptions.py # Custom exception handlers ├── middleware.py # Custom middleware ├── logging.py # Structured logging utilities └── validators.py # Reusable validators Configuration Structure config/ ├── settings/ │ ├── base.py # Base settings │ ├── development.py # Development settings │ ├── staging.py # Staging settings │ └── production.py # Production settings ├── urls.py # Main URL configuration └── wsgi.py # WSGI configuration Django/Python Development Guidelines Views and API Design - Use Class-Based Views: Leverage Django's class-based views (CBVs) with DRF's APIViews - RESTful Design: Follow RESTful principles strictly with proper HTTP methods and status codes - Keep Views Light: Focus views on request handling; keep business logic in models, managers, and services - Consistent Response Format: Use unified response structure for both success and error cases Models and Database - ORM First: Leverage Django's ORM for database interactions; avoid raw SQL queries unless necessary for performance - Business Logic in Models: Keep business logic in models and custom managers - Query Optimization: Use select_related and prefetch_related for related object fetching - Database Indexing: Implement proper database indexing for frequently queried fields - Transactions: Use transaction.atomic() for data consistency in critical operations Serializers and Validation - DRF Serializers: Use Django REST Framework serializers for data validation and serialization - Custom Validation: Implement custom validators for complex business rules - Field-Level Validation: Use serializer field validation for input sanitization - Nested Serializers: Properly handle nested relationships with appropriate serializers Authentication and Permissions - JWT Authentication: Use djangorestframework_simplejwt for JWT token-based authentication - Custom Permissions: Implement granular permission classes for different user roles - Security Best Practices: Implement proper CSRF protection, CORS configuration, and input sanitization URL Configuration - URL Patterns: Use urlpatterns to define clean URL patterns with each path() mapping routes to views - Nested Routing: Use include() for modular URL organization - API Versioning: Implement proper API versioning strategy (URL-based versioning recommended) Performance and Scalability Query Optimization - N+1 Problem Prevention: Always use select_related and prefetch_related appropriately - Query Monitoring: Monitor query counts and execution time in development - Database Connection Pooling: Implement connection pooling for high-traffic applications - Caching Strategy: Use Django's cache framework with Redis/Memcached for frequently accessed data Response Optimization - Pagination: Standardize pagination across all list endpoints - Field Selection: Allow clients to specify required fields to reduce payload size - Compression: Enable response compression for large payloads Error Handling and Logging Unified Error Responses { "success": false, "message": "Error description", "errors": { "field_name": ["Specific error details"] }, "error_code": "SPECIFIC_ERROR_CODE" } Exception Handling - Custom Exception Handler: Implement global exception handling for consistent error responses - Django Signals: Use Django signals to decouple error handling and post-model activities - Proper HTTP Status Codes: Use appropriate HTTP status codes (400, 401, 403, 404, 422, 500, etc.) Logging Strategy - Structured Logging: Implement structured logging for API monitoring and debugging - Request/Response Logging: Log API calls with execution time, user info, and response status - Performance Monitoring: Log slow queries and performance bottlenecks
You are an expert in htmx and modern web application development. Key Principles - Write concise, clear, and technical responses with precise HTMX examples. - Utilize HTMX's capabilities to enhance the interactivity of web applications without heavy JavaScript. - Prioritize maintainability and readability; adhere to clean coding practices throughout your HTML and backend code. - Use descriptive attribute names in HTMX for better understanding and collaboration among developers. HTMX Usage - Use hx-get, hx-post, and other HTMX attributes to define server requests directly in HTML for cleaner separation of concerns. - Structure your responses from the server to return only the necessary HTML snippets for updates, improving efficiency and performance. - Favor declarative attributes over JavaScript event handlers to streamline interactivity and reduce the complexity of your code. - Leverage hx-trigger to customize event handling and control when requests are sent based on user interactions. - Utilize hx-target to specify where the response content should be injected in the DOM, promoting flexibility and reusability. Error Handling and Validation - Implement server-side validation to ensure data integrity before processing requests from HTMX. - Return appropriate HTTP status codes (e.g., 4xx for client errors, 5xx for server errors) and display user-friendly error messages using HTMX. - Use the hx-swap attribute to customize how responses are inserted into the DOM (e.g., innerHTML, outerHTML, etc.) for error messages or validation feedback. Dependencies - HTMX (latest version) - Any backend framework of choice (Django, Flask, Node.js, etc.) to handle server requests. HTMX-Specific Guidelines - Utilize HTMX's hx-confirm to prompt users for confirmation before performing critical actions (e.g., deletions). - Combine HTMX with other frontend libraries or frameworks (like Bootstrap or Tailwind CSS) for enhanced UI components without conflicting scripts. - Use hx-push-url to update the browser's URL without a full page refresh, preserving user context and improving navigation. - Organize your templates to serve HTMX fragments efficiently, ensuring they are reusable and easily modifiable. Performance Optimization - Minimize server response sizes by returning only essential HTML and avoiding unnecessary data (e.g., JSON). - Implement caching strategies on the server side to speed up responses for frequently requested HTMX endpoints. - Optimize HTML rendering by precompiling reusable fragments or components. Key Conventions 1. Follow a consistent naming convention for HTMX attributes to enhance clarity and maintainability. 2. Prioritize user experience by ensuring that HTMX interactions are fast and intuitive. 3. Maintain a clear and modular structure for your templates, separating concerns for better readability and manageability. Refer to the HTMX documentation for best practices and detailed examples of usage patterns.
--- description: Guidelines and best practices for building Netlify projects & sites, including serverless functions, edge functions, functions, storage, and real-world examples globs: **/*.{ts,tsx,js,jsx,toml} --- <ProviderContextOverrides> // Developers can override the content as needed, but it should all be placed in this section. </ProviderContextOverrides> ANY RULES IN THE ProviderContextOverrides SECTION CAN OVERRULE SPECIFIC RULES IN ProviderContext <ProviderContext version="1.0" provider="netlify"> ## General - the `.netlify` folder is not for user code. It should be added to the .gitignore list - avoid adding version numbers to imported code. (for example use `@netlify/functions` and never `@netlify/functions@VERSION`) - *NEVER* add CORS headers (such as Access-Control-Allow-Origin) unless user EXPLICITLY asks for them. - prefer using `netlify dev` to start dev server unless another dev command is requested by the user # Guidelines - There are 4 types of compute systems you can write code for: - Serverless functions - usually used for transactional server/api requests. - Edge functions - usually used for code that must modify requests before hitting the server or modifying responses before returning to users. - Background functions - longer running functions for asynchronous work. - Scheduled functions - schedule logic to run on a CRON-based interval. - Netlify Blobs is a general object storage that can be used to accomplish state storage, data storage, etc. - Netlify Image CDN enables on-demand image transformations without affecting build times or optimizing images upon upload. It optimizes images dynamically based on client capabilities and caches transformations for performance improvements. Use this when optimizing images dynamically. Don't use this when you need to modify an image during the development/build process. - Environment variables are available for storing secrets, API keys, and other values that you want to control external to the code or are too sensitive to put in the code. ## Netlify compute - NEVER put any type of serverless or edge function in the public or publish directory - DO NOT change the default functions or edge functions directory unless explicitly asked to. - ALWAYS verify the correct directory to place functions or edge functions into ### Context object for serverless functions and edge functions Below are the available fields/functions from the context argument to serverless and edge functions. ``` { account: { id: string, // Unique ID of the Netlify team account associated with the site and function. }, cookies: { get: (name: string) => string | undefined, // Reads a cookie from the incoming request. set: (options: { name: string; value: string; path?: string; domain?: string; secure?: boolean; httpOnly?: boolean; expires?: Date }) => void, // Sets a cookie on the outgoing response following the CookieStore.set web standard. delete: (nameOrOptions: string | { name: string; path?: string; domain?: string }) => void, // Deletes a cookie on the outgoing response, following the CookieStore.delete web standard. }, deploy: { context: string, // The deploy context (e.g., production, deploy-preview). id: string, // Unique ID of the deploy the function belongs to. published: boolean, // Indicates whether the function belongs to the currently published deploy. }, geo: { city: string, // City name of the client location. country: { code: string, // ISO 3166 country code. name: string, // Full country name. }, latitude: number, // Latitude coordinate of the client location. longitude: number, // Longitude coordinate of the client location. subdivision: { code: string, // ISO 3166 subdivision code (e.g., state or province). name: string, // Subdivision name. }, timezone: string, // Timezone of the location. postalCode: string, // Postal code of the location in its regional format. ip: string, // Client IP address. }, params: Record<string, string>, // Object containing route parameters from the function path configuration. requestId: string, // Unique Netlify request ID. server: { region: string, // The region code where the deployment is running (e.g., us-east-1). }, site: { id: string, // Unique ID for the Netlify site. name: string, // The site's Netlify subdomain name. url: string, // The main address of the site, which could be a Netlify subdomain or a custom domain. }, } ``` ### the `Netlify` global object - the `Netlify` object is available in global scope. - available on all serverless and edge function types It has the following fields/functions: ``` { context: object | null, // The Netlify-specific context object - same as function's second arg. Available only within function handlers or child scopes; otherwise, it returns null. env: { delete: (name: string) => void, // Deletes an environment variable within the context of the invocation. get: (name: string) => string | undefined, // Retrieves the string value of an environment variable; returns undefined if not defined. has: (name: string) => boolean, // Checks if an environment variable exists; returns true if it does, otherwise false. set: (name: string, value: string) => void, // Sets an environment variable within the invocation context. toObject: () => Record<string, string>, // Returns an object containing all environment variables and their values. }, }; ``` ### Serverless Functions (aka Functions, aka Synchronous functions) - Serverless functions use Node.js and should attempt to use built-in methods where possible - When adding new npm modules, ensure "node_modules" is in the .gitignore - ALWAYS use the latest format of a function structure. - if using typescript, ensure types are installed from `npm install @netlify/functions` - DO NOT put global logic outside of the exported function unless it is wrapped in a function definition - ONLY use vanilla javascript if there are other ".js" files in the functions directory. - ALWAYS use typescript if other functions are typescript or if there are no existing functions. - The first argument is a web platform Request object that represents the incoming HTTP request - The second argument is a custom Netlify context object. - Functions have a global `Netlify` object that is also accessible. - ONLY use `Netlify.env.*` for interacting with environment variables in code. - Place function files in `YOUR_BASE_DIRECTORY/netlify/functions` or a subdirectory. - The serverless functions directory can be changed via: - **Netlify UI**: *Site configuration > Build & deploy > Continuous deployment > Build settings* - **`netlify.toml`**: ```toml [functions] directory = "my_functions" ``` - `netlify.toml` settings override UI settings. - If using a subdirectory, name the entry file `index.mts` or match the subdirectory name. - Example valid function paths: - `netlify/functions/hello.mts` - `netlify/functions/hello/index.mts` - `netlify/functions/hello/hello.mts` - Naming files with `.mts` enables modern ES module syntax #### Examples of the latest Serverless Function or Function structures - ```typescript import type { Context, Config } from "@netlify/functions"; export default async (req: Request, context: Context) => { // user code return new Response("Hello, world!") } export const config: Config = { // use this path instead of /.netlify/functions/{fnName} path: "/hello-world" }; ``` - ```javascript export default async (req, context) => { // user code return new Response("Hello, world!") } export const config = { // use this path instead of /.netlify/functions/{fnName} path: "/hello-world" }; ``` #### In-code function config and routing for serverless functions - prefer to use in-code configuration via exporting a `config` object. This is the structure the config can have: - prefer to provide a friendly path using the config object. - ONLY serverless functions use `/.netlify/functions/{function_name}` path by default. - If you set a specific path via this config or the netlify.toml, it will only be available at that new path. - path and excluded path supports substring patterns or the URLPattern syntax from the web platform. ``` { path: string | string[], // Defines the URL path(s) that trigger the function. Can be a single string or an array of paths. excludedPath?: string | string[], // Optional. Defines paths that should be excluded from triggering the function. preferStatic?: boolean, // Optional. If true, prevents the function from overriding existing static assets on the CDN. } ``` ### Background Functions - Use background functions when you need to run long-running logic, and that logic does not need to compute a response immediately. - Any data that background functions need to serve to users should be calculated and stored in a place that a serverless function can read from later - such as Netlify Blobs or a preconfigured database. - Background functions operate the same as standard Serverless functions and are syntactically the same with the following exceptions - they have a 15-minute timeout measured by "wall clock" time - they immediately return an empty response with a 202 status code. Return values from these functions are ignored. - Background functions MUST have a "-background" suffix on the function file name or function directory (for example, netlify/functions/hello-background.mts or netlify/functions/hello-background/index.mts). #### Examples of the latest background function structures - ```typescript import { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { await someLongRunningTask(); console.log("Done"); }; ``` - ```javascript export default async (req, context) => { await someLongRunningTask(); console.log("Done"); }; ``` ### Scheduled Functions - Use scheduled functions when the logic needs to run on an interval or can be defined via CRON timing. - CRON expressions are executed against the UTC timezone - our CRON syntax supports extensions defined the RFC except for the @reboot and @annually. - The minimum interval is 1 minute - Scheduled functions have a 30-second execution limit - Scheduled functions do not return response bodies - the request body is a JSON-encoded object containing a `next_run` property. It represents the timestamp of the next scheduled invocation, as a string in the ISO-8601 format. - in addition to in-code config, schedules can be defined in the `netlify.toml`. ONLY do this for consistency or if explicitly asked to keep all schedules in one place. ```toml [functions."test-scheduled-function"] schedule = "@hourly" ``` - Scheduled functions ONLY run on published deploys. They don’t run on Deploy Previews or branch deploys. - For local tests, the Netlify CLI to run the site in dev mode and the `netlify functions:invoke` [command](mdc:https:/cli.netlify.com/commands/functions/#functionsinvoke) to trigger the scheduled function. example: ```bash netlify functions:invoke myfunction ``` #### Examples of the latest background function structures - ```typescript import type { Config } from "@netlify/functions" export default async (req: Request) => { const { next_run } = await req.json() console.log("Received event! Next invocation at:", next_run) } export const config: Config = { schedule: "@hourly" } ``` - ```javascript export default async (req) => { const { next_run } = await req.json() console.log("Received event! Next invocation at:", next_run) } export const config = { schedule: "@hourly" } ``` ### Edge Functions - ALWAYS use the latest format of an edge function structure. - **DO NOT** add CORS headers (such as Access-Control-Allow-Origin) unless explicitly asked for them. - if using typescript, ensure types are installed from `npm install @netlify/edge-functions` - DO NOT put global logic outside of the exported function unless it is wrapped in a function definition - ONLY use vanilla javascript if there are other ".js" files in the functions directory. - ALWAYS use typescript if other functions are typescript or if there are no existing functions. - The first argument is a web platform Request object that represents the incoming HTTP request - The second argument is a custom Netlify context object. - Edge functions have a global `Netlify` object that is also accessible. - ONLY use `Netlify.env.*` for interacting with environment variables in code. - Place function files in `YOUR_BASE_DIRECTORY/netlify/edge-functions` or a subdirectory. - The serverless functions director can be changed via`netlify.toml`: ```toml [build] edge_functions = "my-custom-directory" ``` - Edge functions use Deno as runtime and should attempt to use built-in methods where possible. See the list of available web APIs to know which built-ins to use. - **Module Support**: - Supports **Node.js built-in modules**, **Deno modules**, and **npm packages** (beta). - **Importing Modules**: - **Node.js built-in modules**: Use `node:` prefix (e.g., `import { randomBytes } from "node:crypto"`). - **Deno modules**: Use **URL imports** (e.g., `import React from "https://esm.sh/react"` or an **import map**). - **npm packages (beta)**: Install via `npm install` and import by package name (e.g., `import _ from "lodash"`). - Some npm packages with **native binaries** (e.g., Prisma) or **dynamic imports** (e.g., cowsay) may not work. - You may use an **import map** to reference third-party modules with shorthand names instead of full URLs. - **Import Map Usage**: - Define mappings in a separate **import map file** (not in `deno.json`). - The file can be placed anywhere in the project directory. - **Example Import Map (`import_map.json`)**: ```json { "imports": { "html-rewriter": "https://ghuc.cc/worker-tools/html-rewriter/index.ts" } } ``` - **Enabling Import Maps**: - Declare the import map in `netlify.toml`: ```toml [functions] deno_import_map = "./path/to/your/import_map.json" ``` - **Usage in Code**: - Modules can now be imported by name: ```javascript import { HTMLRewriter } from "html-rewriter"; ``` #### Examples of the latest Edge function structures - ```typescript import type { Context, Config } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { // user code return new Response("Hello, world!") } export const config: Config = { path: "/hello-world" }; ``` - ```javascript export default async (req, context) => { // user code return new Response("Hello, world!") } export const config = { path: "/hello-world" }; ``` #### Extra properties on context argument for Edge Functions - these are ONLY available in Edge Functions ``` { ...ALL OTHER Context fields/methods, next: (options?: { sendConditionalRequest?: boolean }) => Promise<Response>, // Invokes the next item in the request chain, optionally using conditional requests. nextRequest: (request: Request, options?: { sendConditionalRequest?: boolean }) => Promise<Response>, // Same as next(), but requires an explicit Request object. } ``` #### Web APIs available in Edge Functions ONLY - console.* - atob - btoa - Fetch API - fetch - Request - Response - URL - File - Blob - TextEncoder - TextDecoder - TextEncoderStream - TextDecoderStream - Performance - Web Crypto API - randomUUID() - getRandomValues() - SubtleCrypto - WebSocket API - Timers - setTimeout - clearTimeout - setInterval - Streams API - ReadableStream - WritableStream - TransformStream - URLPattern API #### In-code function config and routing for Edge functions - prefer to use in-code configuration via exporting a `config` object. This is the structure the config can have: - prefer to provide a friendly path using the config object. - Edge functions are configured with a path pattern and only paths matching those patterns will run the edge function - path and excludedPath supports substring patterns or the URLPattern syntax from the web platform. - unless explicitly asked to modify other properties, only set path, pattern, excludedPath when creating functions. ``` { path?: string | string[], // URLPattern expression defining paths where the edge function should run. Must start with '/'. excludedPath?: string | string[], // Optional. Defines paths to exclude from execution. Must start with '/'. pattern?: RegExp | RegExp[], // Alternative to `path`. Uses regex for path matching. excludedPattern?: RegExp | RegExp[], // Optional. Defines regex patterns to exclude certain routes. method?: string | string[], // Optional. Specifies HTTP methods that should trigger the function (e.g., "GET", ["POST", "PUT"]). onError?: "continue" | "fail" | "fallback", // Optional. Controls how the function handles errors. cache?: 'manual', // Optional. Enables response caching if set to 'manual'. } = { path: "", // Default value; should be set per function. }; ``` #### Configuring Edge Functions in netlify.toml - ONLY Use `netlify.toml` for precise function order control instead of inline declarations. - DO NOT use `netlify.toml` if there is not edge function ordering requirements. - When controlling order, it's important to include all edge functions for order control. - **Declare Edge Functions in `netlify.toml`**: - Allows multiple edge functions on the same path with explicit execution order. - Functions run **top-to-bottom**, except cached functions, which always run last. - **Edge Function Properties**: - `function`: Name of the edge function. - `path`: URL pattern to trigger the function (must start with `/`). - `excludedPath`: Excludes specific routes from `path` (supports string or array). - `pattern`: Regex-based path matching. - `excludedPattern`: Excludes specific regex patterns (single or array). - `cache`: Enables response caching (cached functions run after non-cached ones) set to 'manual' to opt in. - **Netlify.toml config examples** ```toml [[edge_functions]] path = "/admin" function = "auth" [[edge_functions]] path = "/admin" function = "injector" cache = "manual" [[edge_functions]] path = "/blog/*" function = "auth" [[edge_functions]] path = "/blog/*" function = "rewriter" [[edge_functions]] pattern = "/products/(.*)" excludedPattern = "/products/things/(.*)" function = "highlight" [[edge_functions]] path = "/*" excludedPath = "/img/*" function = "common" ``` - **Execution Order for Edge Functions**: 1. **Configuration-based** edge functions (`netlify.toml`) run first. 2. **Framework-generated** edge functions execute before user-defined functions. 3. **Non-cached** edge functions execute before cached functions. 4. **Inline-declared** edge functions override duplicate `netlify.toml` functions. 5. **Multiple inline edge functions** run alphabetically by filename. - **Caveats & Special Cases**: - If an edge function returns a response, redirects for that path DO NOT occur. - Edge functions DO NOT execute for rewritten static routing targets. - `fetch()` or `URL()` triggers a **new request chain**, re-running matching functions. - Use `context.next()` to continue processing instead of re-triggering functions. - Function failure behavior depends on its **error handling configuration**. #### Edge functions limitations - 20 MB (compressed) code size limit - 512 MB per deployment memory limit - 50ms per request CPU execution time (excludes waiting time) - 40 seconds Response header timeout - **Not compatible with these Netlify features**: - Netlify's split testing feature - Custom Headers (including basic authentication) from _headers or netlify.toml config - Netlify prerendering feature on paths served by edge functions - Be aware that multiple framework adapters may generate conflicting edge functions - **Restrictions**: - Can only rewrite requests to same-site URLs (use `fetch()` for external content) - Cached edge functions override existing static files - No local caching; HTTP cache headers are ignored in local testing - Not included in Netlify’s HIPAA-compliant hosting offering ## Netlify Blobs - Prefer using Netlify Blobs over creating a new database unless a flat file is not appropriate data layer, if explicitly asking to use a tool, or the dev needs to created relational structures or search that's more appropriate for databases - Blobs do not require configuration to use, everything is automatically provisions, and devs can simply start using them via any Netlify compute. The API will be the same across all compute types. - ensure `@netlify/blobs` NPM module is installed - Requirements and limits - Requires Fetch API support (Node.js 18+ recommended) - a fetch function can be provided to the store - Store names cannot exceed 64 bytes - Object keys cannot exceed 600 bytes - Maximum object size: 5GB - Local development uses a sandboxed store ### Netlify Blobs API ```typescript export interface BlobMetadata { [key: string]: any; } export interface BlobData<T = string> { data: T | null; etag: string; metadata: BlobMetadata; } export interface ListResult { blobs: { etag: string; key: string }[]; directories?: string[]; } interface GetKeyOptions { type?: 'arrayBuffer' | 'blob' | 'json' | 'stream' | 'text' } interface GetKeyAndMetadataOptions { type?: 'arrayBuffer' | 'blob' | 'json' | 'stream' | 'text', etag?: string; } // THESE ARE THE ONLY STORE METHODS. DO NOT MAKE UP NEW ONES interface Store { // Creates or overwrites a blob entry. // example: await store.set('key-name', 'contents-of key'); // - NEVER add metadata unless instructed to. set(key: string, value: ArrayBuffer | Blob | string, { metadata?: object }): Promise<void>; // Stores a JSON-serializable object. // example: await store.setJSON('key-name', {version: 'a', someBoolean: true}); // - NEVER add metadata unless instructed to. setJSON(key: string, value: any, { metadata?: object }): Promise<void>; // Retrieves a stored blob. // example: await store.get('key-name'); // - NEVER add the second arg unless you need an explicit type 'arrayBuffer' | 'blob' | 'json' | 'stream' | 'text'. // - Instead of using JSON.parse(blob), use store.get('key-name', {type: 'json'}) // - if the blob is missing, it will resolve the promise with a null value get(key: string, getOpt?: GetKeyOptions): Promise<any | null>; // Retrieves a blob along with metadata // example: await store.getWithMetadata('key-name'); // - NEVER add the second getOpts arg unless you need an explicit type or have an etag to check against. // - AVOID adding it unless it's reliably available but IF an etag is provided, it will only return the blob if the etag is different that what's stored. // - if the blob is missing, it will resolve the promise with a null value getWithMetadata(key: string, getOpts?: GetKeyAndMetadataOptions): Promise<{ data: any, etag: string, metadata: object } | null>; // Retrieves metadata of a blob WITHOUT downloading the data. // example: await store.getMetadata('key-name'); // - NEVER add the second getOpts arg unless you need an explicit type or have an etag to check against. // - AVOID adding it unless it's reliably available but IF an etag is provided, it will only return the blob if the etag is different that what's stored. // - if the blob is missing, it will resolve the promise with a null value getMetadata(key: string, getOpts?: GetKeyAndMetadataOptions): Promise<{ etag: string, metadata: object } | null>; // Lists blobs in the store with optional hierarchical browsing. // example: // const { blobs } = await store.list() // // blobs === [ { etag: 'etag1', key: 'some-key' }, { etag: 'etag2', key: 'another-key' } ] // // - NEVER add the options arg unless you need an explicit reduce the searched data. // -- ONLY if you have to reduce searched data, use `prefix: 'some-prefix'` to pull blobs that start with that prefix value. Use `directories: true` to include the full directory path on the `key` // - By default, the list() method retrieves all pages, meaning you'll always get the full list of results. This can be slow or memory intensive. To paginate, pass the `paginate: true` in the options to turn the response into an AsyncIterator that allows you to for-of loop through the blobs in the store. // - if store path is empty, the blobs will resolve the promise with an empty array list(options?: { directories?: boolean, paginate?: boolean. prefix?: string }): Promise<{ blobs: BlobResult[], directories: string[] }> | AsyncIterable<{ blobs: BlobResult[], directories: string[] }> // Deletes a blob. // example: await store.delete('key-name'); // - The return value is always resolves to `undefined`, regardless of whether or not there was an object to delete. delete(key: string): Promise<void>; } interface GetDeployStoreOptions extends Partial<ClientOptions> { deployID?: string; name?: string; region?: Region; } // Returns a store instance for managing blobs. This is global scoped data across all deploys. // example: const store = getStore('my-store'); // - ONLY add the options argument if the user needs strong consistency export function getStore(name: string, options?: { consistency?: 'strong' | 'eventual' }): Store; // Returns a deploy-specific store instance for managing blobs tied to a deploy. // example: const store = getDeployStore('my-store'); // - ONLY add the options argument if the user needs strong consistency declare const getDeployStore: (input?: GetDeployStoreOptions | string) => Store; interface GetStoreOptions extends Partial<ClientOptions> { deployID?: string; name?: string; } // Lists all stores available on a site. // example: // const { stores } = await listStores(); // // [ "beauty", "construction" ] // - By default, the listStores() method retrieves all pages, meaning you'll always get the full list of results. This can be slow or memory intensive. To paginate, pass the `paginate: true` in the options to turn the response into an AsyncIterator that allows you to for-of loop through the blobs in the store. // - DO NOT pass options unless paginating. declare function listStores(options?: { paginate?: boolean; }): Promise<ListStoresResponse> | AsyncIterable<ListStoresResponse>; interface ListStoresResponse { stores: string[]; next_cursor?: string; } ``` ## File-Based Uploads With file-based uploads, write blobs to deploy-specific stores after the site build completes. Useful for frameworks and other tools integrating with Netlify as it does not require a build plugin. Put files in `.netlify/blobs/deploy/*` for deploy specific ``` .netlify/ ├─ blobs/ | ├─ deploy/ │ | ├─ beauty/ │ │ | └─ nails.jpg ``` To attach metadata to a blob via file upload flows, include a JSON file that prefixes the corresponding blob filename with $ and has a .json extension. For example: ``` ├─ blobs/ | ├─ deploy/ │ | ├─ beauty/ │ │ | ├─ nails.jpg │ │ | └─ $nails.jpg.json ``` ## Blob consistency models - By default, blobs are "eventually consistent" - Fast reads, updates/deletions propagated within 60 seconds. - To have strong consistency that ensures updates are immediately visible at the cost of slower reads. set the `consistency` field to `'strong'` on the store instantiation. - There is no concurrency control built in, last write wins. Add object-locking mechanisms if you need concurrency guarantees. Example: ```javascript const store = getStore({ name: "animals", consistency: "strong" }); await store.set("dog", "🐶"); const dog = await store.get("dog"); ``` ## Storage scopes - blobs can be stored in a deploy-specific scope or at a global scope - deploy-specific blobs sync with deploys and are removed with deploy deletions. `getDeployStore()` is used to interact with deploy specific stores. - global scope blobs are not automatically cleaned up and are consistent across all branches. `getStore()` is used for global scope. - Build plugins and file-based uploads must write to deploy-specific stores. - ALWAYS When creating logic that saves to global scope, ensure that non-production data does not get stored in these global stores. This keeps production data isolated from test data. To do that, check for the environment and choose which store to use depending on the environment. #### Examples of blob usage ```javascript // basic writing to a deploy store import { getDeployStore } from "@netlify/blobs"; const store = getDeployStore("construction"); ``` ```javascript // basic writing to a global store import { getStore } from "@netlify/blobs"; const store = getStore("construction"); ``` ```javascript // using global store if in production, otherwise use deploy scope store import { getStore, getDeployStore } from "@netlify/blobs"; function getBlobStore(...storeOptions){ if((Netlify.context?.deploy.context === 'production'){ return getStore(...storeOptions); } return getDeployStore(...storeOptions) } const store = getBlobStore("construction"); ``` --- ## Netlify Image CDN - All Netlify sites have a `/.netlify/images` route supported by their site without any additional enablement. - Transform images via query parameters in requests to `/.netlify/images`. - NEVER introduce circular dependencies with urls redirecting to urls that redirect back to the same url in a loop - when using the ?url={URL} parameter, ensure the url is a URI encoded component. - Supported transformations: - **source**: Required, specifies image URL (relative or remote). - **size**: `w` (width) and `h` (height) in pixels. - **fit**: Determines how the image is resized (`contain`, `cover`, `fill`). - **position**: Cropping alignment (`top`, `bottom`, `left`, `right`, `center`). - **format**: Convert to `avif`, `jpg`, `png`, `webp`, `gif`, or `blurhash`. - **quality**: Controls lossy format quality (`q`, 1-100, default 75). ### Example transformations ```html <!-- get an image hosted on this site and change its size and format --> <img src="/.netlify/images?url=/image.jpg&w=100&h=100&fit=cover&fm=webp&q=80" /> <!-- get an image hosted externally and change its size and format --> <img src="/.netlify/images?url=https://example.com/path/to/image&w=40&h=10&fm=jpg&q=80" /> ``` ### Caching & deployment behavior - Transformed images are cached at the edge. - Source images are cached for future transformations. - After a new deploy cached images are invalidated and so images can be reprocessed in case of changes - Cache-busting via asset fingerprinting is recommended if you must finely control cache key. - In order to use externally hosted (aka remote) images the domain pattern must be allowlisted in the Netlify `netlify.toml`. - Allow remote sources using: ```toml [images] remote_images = ["https://externalexample.com/.*"] ``` - only absolute urls to external servers need to be in remote_images ### Redirects & Rewrites - If you do not want to use the default `/.netlify/images` path, a redirect or rewrite can be used to have a different url. - Define reusable transformation routes in `_redirects` or `netlify.toml` files. - When doing so, the parameters can remain parameters to pass in or can be statically defined. - Examples: - netlify.toml to use /transform-my-images/{imagePath} ```toml [[redirects]] from = "/transform-my-images/*" to = "/.netlify/images?url=/:splat&w=50&h=50" status = 200 ``` - _redirects to use /transform-all/{...imagePath} ``` /transform-all/* /.netlify/images?url=/:splat&w=50&h=50 200 ``` ### Custom headers - Custom headers can ONLY be applied to images hosted on the same domain. - ONLY do this when explicitly asked - Examples: - netlify.toml to use /transform-my-images/{imagePath} ```toml [[headers]] for = "/source-images/*" [headers.values] Cache-Control = "public, max-age=604800, must-revalidate" ``` - _headers to use /{...imagePath} ``` /source-images/* Cache-Control: public, max-age=604800, must-revalidate ``` ### Image CDN framework support Netlify Image CDN integrates with frameworks for automatic optimizations: - **Angular**: `NgOptimizedImage` component will use Image CDN automatically - **Astro**: `<Image />` component will use Image CDN automatically - **Gatsby**: set `NETLIFY_IMAGE_CDN=true` and use the Contentful, Drupal, or WordPress source plugins. - **Next.js**: set `remotePatterns` in `next.config.js` - **Nuxt**: `nuxt/image` module will use Image CDN automatically --- ## Environment Variables - securely create, manage, and use environment variables across sites. These variables can be set via the UI, CLI, API, or configuration files. - when setting environment variables, Netlify local environment and cloud environment will make these variables available. - **Precedence**: `netlify.toml` overrides UI/CLI/API variables, and site-specific variables take precedence over shared ones. ### Creating Environment Variables Variables can be created and managed using: - **Netlify UI**: Suggest using if they don't want to provide the values directly to this agent. They can navigate to it via the path "Site configuration > Environment variables". - **Netlify CLI**: Prefer using this if the agent can run commands. This requires the site to be linked. - **Netlify Configuration (`netlify.toml`)**: Defines variables at the repository level. ONLY use this for environment variables where the site is not linked yet and the values are not sensitive. ### Netlify CLI Command - The site must be linked first before the CLI will add variables. See the rules for initializing and linking sites for how to do this. - Use `env:set` for changes, `env:unset` to delete. `env:import` to import from a dotenv`.env` file. #### Example usage of env var CLI - Basic setting an environment variable for the site ```sh netlify env:set API_KEY "not-a-secret" ``` - Setting an environment variable that should be treated as a secret ```sh netlify env:set API_KEY "secret-value" --secret ``` ### Example `netlify.toml` Configuration - Using the netlify.toml the configuration can be specific to certain branches/deploy contexts. - examples ```toml # Production context: all deploys from the Production branch # set in your site’s Branches settings in the UI will inherit # these settings. You can define environment variables # here but we recommend using the Netlify UI for sensitive # values to keep them out of your source repository. [context.production] publish = "output/" command = "make publish" environment = { NODE_VERSION = "14.15.3" } # Here is an example of how to define context-specific # environment variables. Be mindful when using this # option and avoid committing sensitive values to public # source repositories. [context.deploy-preview.environment] NOT_PRIVATE_ITEM = "not so secret" # Branch Deploy context: all deploys that are not from # a pull/merge request or from the Production branch # will inherit these settings. [context.branch-deploy.environment] NODE_ENV = "development" # Dev context: environment variables set here # are available for local development environments # run using Netlify Dev. These values can be # overwritten on branches that have a more specific # branch context configured. [context.dev.environment] NODE_ENV = "development" # Specific branch context: all deploys from # this specific branch will inherit these settings. [context.staging.environment] # “staging” is a branch name NODE_ENV = "development" ``` ### `.env` File Handling - Netlify builds do not read `.env` files directly - Import `.env` variables into Netlify using the UI or CLI (`netlify env:import .env`). - Export Netlify variables to `.env` files via UI or CLI (`env:list`). ### Export `.env` Variables ```sh # list the production deploy context values in .env format netlify env:list --plain --context production # list the production deploy context values in .env format # and pipe results into a .env file netlify env:list --plain --context production > .env ``` --- # Creating new sites - do not add redirects to netlify.toml or _redirects unless requested - do not add custom headers to the netlify.toml or _headers unless requested # Initializing sites or linking them - determine if a site is linked by checking if `PROJECT_FOLDER/.netlify/state.json` file exists and it has a populated `siteId` value. - if the site is not linked, run `netlify init` to allow the user to set up the site with Netlify. If the user deploys manually, it will set up the site to use Netlify automatically. If the user decides to set up a repo, they might have to set up the repo first. If the site is already set up on netlify then run `netlify link` for the user to input the credentials to link. </ProviderContext>
You are a full-stack expert using remult with: - TypeScript Key Principles - Remult is the single source of truth for your application. ## Entities are the SSoT ```ts filename=src/shared/Task.ts import { Entity, Fields } from 'remult' @Entity('tasks', { allowApiCrud: true, }) export class Task { @Fields.cuid() id!: string @Fields.string() title: string = '' @Fields.boolean() completed: boolean = false @Fields.createdAt() createdAt?: Date } ``` ## In the backend and the frontend you can do Pagination, Sorting, Filtering and Aggregation ```ts filename=src/shared/Task.ts import { repo } from 'remult' repo(Task) .find({ limit: 20, orderBy: { createdAt: "asc" }, where: { completed: true } }) ``` ## All CRUD operations are available in frontend and backend ```ts filename=src/shared/Task.ts // create await repo(Task).insert({ title: newTaskTitle }); // update await repo(Task).update(taskId, { title: newTaskTitle }); // delete await repo(Task).delete(taskId); ``` ## Add validation to your entities ```ts filename=src/shared/Task.ts @Entity('tasks', { allowApiCrud: true, }) export class Task { import { Validators } from 'remult'; @Fields.string({ validate: Validators.required }) title: string = ''; } ``` ## Live Queries ```ts filename=src/shared/Task.ts repo(Task) .liveQuery({ where: { completed: true } }) .subscribe((info) => { tasks = info.applyChanges(tasks); }); ``` ## Database By default Remult use JSON database, but you can use any database listed here: https://remult.dev/docs/installation/database/ example for PostgreSQL: ```ts filename=remult.config.ts import { createPostgresDataProvider } from 'remult/postgres' // Server options { // ... entities: [Task], dataProvider: DATABASE_URL ? createPostgresDataProvider({ connectionString: DATABASE_URL }) : undefined, // ... } ``` Documentation - Remult Documentation: https://remult.dev/docs