### Install Dependencies for GitHub Releases Addon Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/changelog/README.md Installs required npm packages including Tailwind CSS typography plugin, markdown parser (marked), syntax highlighter (marked-highlight), and code highlighting library (highlight.js). These dependencies enable markdown processing and syntax highlighting for release notes. ```bash npm install @tailwindcss/typography marked marked-highlight highlight.js ``` -------------------------------- ### Configure GitHub Repository for Release Fetching Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/changelog/README.md Updates the repository configuration in the addon routes to specify the target GitHub organization and repository for fetching releases. Replace 'GITHUB_ORG/GITHUB_REPO' with the actual repository details. ```typescript let releaseKeys = await fetchReleases("GITHUB_ORG/GITHUB_REPO"); ``` -------------------------------- ### Create Cloudflare KV Queue for Changelog Storage Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/changelog/README.md Creates a Cloudflare KV (Key-Value) queue named 'KV_ADDON_CHANGELOG' for caching GitHub release data. This queue stores fetched release information to reduce API calls and improve performance. ```bash npx wrangler queues create KV_ADDON_CHANGELOG ``` -------------------------------- ### Configuring RedwoodSDK App with Headers and Routing Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/full-stack-payment-integration.md This code sets up the main application worker, applying common headers, initializing the database and session store, loading user sessions, and defining core routes including a prefix for subscribe functionality. It depends on RedwoodSDK, a database (db), and environment variables (env). Inputs include the context (ctx) and environment; outputs render the Document with specified routes like HomePage and subscribe routes. Limitations include requiring proper session management and database setup for user loading. ```typescript // worker.tsx export default defineApp([ setCommonHeaders(), async ({ ctx }) => { await setupDb(env); setupSessionStore(env); if (ctx.session?.userId) { ctx.user = await db.user.findUnique({ where: { id: ctx.session.userId }, }); } }, render(Document, [ route("/", [HomePage]), prefix("/subscribe", subscribeRoutes), ]), ]); ``` -------------------------------- ### Initialize Project with Bash Commands Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt These Bash commands initialize the RedwoodSDK Website project by cloning the repository, installing dependencies, and providing commands for development, building, and deployment. It assumes a Node.js environment with pnpm package manager. Inputs include the Git repository URL, and outputs are local development server, production build, or deployed application on Cloudflare Workers. Limitations include requiring pnpm and a compatible environment for Cloudflare tools. ```bash # Clone the repository git clone https://github.com/redwoodjs/rwsdk.com.git cd rwsdk.com # Install dependencies pnpm i # Start development server (runs on Miniflare) pnpm dev # Build for production pnpm build # Deploy to Cloudflare Workers pnpm release ``` -------------------------------- ### RedwoodSDK Custom API Route Examples Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/true-js-fullstack.md Shows how to define custom API routes in RedwoodSDK that can return various response types like JSON, XML, or plain text, utilizing the framework's Request/Response cycle. Includes examples for redirects, sitemaps, and robots.txt. ```javascript // worker.tsx export default defineApp([ setCommonHeaders(), render(Document, [ index([UsersPage]), route("/docs", async () => { return new Response(null, { status: 301, headers: { "Location": "https://docs.rwsdk.com", }, }); }), route("/sitemap.xml", async () => { return new Response(sitemap, { status: 200, headers: { "Content-Type": "application/xml", }, }); }), route("/robots.txt", async () => { const robotsTxt = `User-agent: * Allow: / Disallow: /search Sitemap: https://rwsdk.com/sitemap.xml`; return new Response(robotsTxt, { status: 200, headers: { "Content-Type": "text/plain", }, }); }), route("*", async () => { return notFound(); }), ]), ]); ``` -------------------------------- ### Next.js App Router Metadata Generation Example Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/your-react-meta-framework-feels-broken.md This example demonstrates how to generate metadata for a blog post in Next.js using the App Router. It shows the use of async functions like `generateMetadata` to fetch post data and return metadata objects for SEO and social sharing. This relies on Next.js's specific file conventions and magic exports. ```tsx import { getPost } from "./actions"; // Assuming getPost is defined elsewhere export async function generateMetadata({ params }) { const post = await getPost(params.slug); return { title: post.title, description: post.summary, openGraph: { title: post.title, description: post.summary, images: [`https://example.com/og/${post.slug}.png`] } }; } export default async function BlogPost({ params }) { const post = await getPost(params.slug); return
{post.content}
; } ``` -------------------------------- ### Root Document Setup with SEO and Security Headers in TypeScript Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt Configures the root HTML document for a RedwoodJS application using React and TypeScript. It includes meta tags for SEO, Open Graph, Twitter cards, and crucially, a Content Security Policy (CSP) to enhance security by controlling resource loading. The component imports necessary scripts like TurnstileScript and links to external stylesheets. ```typescript // src/app/Document.tsx import { TurnstileScript } from "rwsdk/turnstile"; import stylesUrl from "./styles.css?url"; // Content Security Policy configuration const cspDirectives = { "script-src": "'self' 'unsafe-inline' https://challenges.cloudflare.com https://static.cloudflareinsights.com https://kwesforms.com https://scripts.simpleanalyticscdn.com", "style-src": "'self' 'unsafe-inline' https://fonts.googleapis.com", "font-src": "'self' https://fonts.gstatic.com", "connect-src": "'self' https://api.github.com https://kwesforms.com https://kwesforms.com/api/foreign/forms/* https://simpleanalyticscdn.com https://queue.simpleanalyticscdn.com", "frame-src": "https://ghbtns.com https://www.youtube.com https://youtube.com https://www.youtube.com/", "object-src": "'none'", "img-src": "'self' data: https: https://queue.simpleanalyticscdn.com", }; const cspContent = Object.entries(cspDirectives) .map(([key, value]) => `${key} ${value}`) .join("; "); const canonicalUrl = "https://rwsdk.com"; export const Document: React.FC<{ children: React.ReactNode; nonce?: string; }> = ({ children, nonce }) => { return ( RedwoodSDK is a React framework for Cloudflare {/* Icons */} {/* Open Graph Tags */} {/* SEO */} {/* Security */} {/* Styles and Scripts */}
{children}
); }; ``` -------------------------------- ### Integrate Changelog Routes in RedwoodJS Application Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/changelog/README.md Imports and integrates the changelog routes into the RedwoodJS application router. The prefix '/changelog' is configured to handle all changelog-related routes, enabling the GitHub releases display functionality. ```typescript import { changelogRoutes } from '@/addons/changelog/routes.tsx' defineApp([ prefix('/changelog', changelogRoutes), ]) ``` -------------------------------- ### Server Actions for Paystack Payment Initiation and Verification (TypeScript) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/full-stack-payment-integration.md These server actions handle the backend logic for integrating with the Paystack API. The `initiatePayment` function sends payment details to Paystack to get an authorization URL, while `verifyPayment` checks the transaction status using a reference. They utilize environment variables for API keys and can interact with databases and other server-side functionalities within RedwoodSDK. Dependencies include 'cloudflare:workers' for environment variables and the 'db' for potential database operations. ```typescript // payment.ts "use server"; import { db } from "@/db"; import { AppContext } from "@/worker"; import { env } from "cloudflare:workers"; const INITIATE_PAYMENT_LINK = "https://api.paystack.co/transaction/initialize"; const VERIFY_PAYMENT_LINK = "https://api.paystack.co/transaction/verify/"; const CALLBACK_URL = "http://localhost:5173/subscribe/callback"; // Testing locally export async function initiatePayment(email: string, plan: string) { const response = await fetch(INITIATE_PAYMENT_LINK, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${env.PAYSTACK_SECRET_KEY}`, }, body: JSON.stringify({ email, plan, callback_url: CALLBACK_URL }), }); const data = await response.json(); return data; } export async function verifyPayment(reference: string) { const response = await fetch(`${VERIFY_PAYMENT_LINK}${reference}`, { headers: { Authorization: `Bearer ${env.PAYSTACK_SECRET_KEY}`, }, }); const data = await response.json(); return data; } ``` -------------------------------- ### Configure Tailwind CSS Typography Plugin Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/changelog/README.md Adds the Tailwind CSS typography plugin to the application's styles configuration. This plugin provides typographic defaults and utilities for enhanced readability of markdown content. ```css @import "tailwindcss"; @plugin "@tailwindcss/typography"; ``` -------------------------------- ### Client Component for Paystack Payment Subscription Form (React/TypeScript) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/full-stack-payment-integration.md This client component provides the user interface for subscribing to a plan using Paystack. It allows users to select a package, enter their email, and initiate the payment process by calling the `initiatePayment` server action. Upon successful initiation, the user is redirected to Paystack's authorization URL. Dependencies include React's 'useState' hook and imported constants like 'packages'. ```typescript "use client"; import { initiatePayment } from "@/app/actions/payment"; import { packages } from "@/app/Constants"; import { useState } from "react"; export default function Subscribe() { const [selectedPackage, setSelectedPackage] = useState("Starter"); const [email, setEmail] = useState(""); const pkg = packages.find((pkg) => pkg.title === selectedPackage); const handleSelectPackage = (packageName: string) => { setSelectedPackage(packageName); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!pkg) return; const response = await initiatePayment(email, pkg.planCode); if (response.status) { window.location.href = response.data.authorization_url; } }; return (
{/* form fields */}
); } ``` -------------------------------- ### RedwoodSDK Server Component: Direct Database Access Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/true-js-fullstack.md Illustrates how RedwoodSDK allows direct database access within server components, eliminating the need for separate API endpoints. This example shows a server function (`getUsers`) to fetch data and a server component (`UsersPage`) to render it. ```javascript // users.ts (server function) "use server" import { db } from "@/db"; export async function getUsers() { const users = await db.users.findAll(); return users; } // UserList.tsx (server component) import { getUsers } from "./users"; export default async function UsersPage() { const users = await getUsers(); return (
) } ``` -------------------------------- ### Initialize RedwoodSDK Database Connection (TypeScript) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/do-db-exporer.md Defines the application's database type and creates a database instance using RedwoodSDK. It connects to a Durable Object named 'APP_DURABLE_OBJECT' and uses 'main-database' as the database key. This setup requires the `env` object from 'cloudflare:workers' and migration types defined in '@/db/migrations'. ```typescript // src/db/db.ts import { env } from "cloudflare:workers"; import { type Database, createDb } from "rwsdk/db"; import { type migrations } from "@/db/migrations"; export type AppDatabase = Database; export const db = createDb(env.APP_DURABLE_OBJECT, "main-database"); ``` -------------------------------- ### Defining Subscribe Routes with Payment Callback Handler Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/full-stack-payment-integration.md This defines routes for subscription handling, including an index for Subscribe page, a callback route for payment verification, and success/error pages. It uses RedwoodSDK router, verifies payments via a payment action, queries the database for user and subscription data, and redirects based on payment status. Dependencies include rwsdk/router, db, and verifyPayment function; inputs are request URL and context; outputs are redirects or page renders. Limitations: Assumes user is authenticated in context and handles only success/failure statuses without error details. ```typescript // subscribeRoutes.ts import { route, index } from "rwsdk/router"; import { verifyPayment } from "@/app/actions/payment"; import Subscribe from "./Subscribe"; import PaymentSuccess from "./PaymentSuccess"; import PaymentError from "./PaymentError"; const subscribeRoutes = [ index(Subscribe), route("/callback", async (ctx, request) => { const url = new URL(request.url); const reference = url.searchParams.get("reference") || ""; const payment = await verifyPayment(reference); if (payment.data.status === "success") { const user = await db.user.findUnique({ where: { id: ctx.user?.id }, }); if (user) { const subscription = await db.subscription.findUnique({ where: { userId: user.id }, }); // Additional logic... } return Response.redirect( new URL("/subscribe/payment-success", request.url) ); } return Response.redirect(new URL("/subscribe/payment-failed", request.url)); }), route("/payment-success", PaymentSuccess), route("/payment-failed", PaymentError), ]; export default subscribeRoutes; ``` -------------------------------- ### Configure Cloudflare Workers Settings Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt This JSONC configuration file defines the Cloudflare Workers setup for the RedwoodSDK project, including assets, KV namespaces, R2 buckets, and environment-specific variables. It relies on Wrangler tool and Cloudflare account for deployment. Inputs are binding names and IDs, producing a configured worker with observability. Limited by requiring Cloudflare CLI tools and account for full functionality in production. ```jsonc // wrangler.jsonc { "$schema": "node_modules/wrangler/config-schema.json", "name": "redwoodsdk", "main": "src/worker.tsx", "compatibility_date": "2024-09-23", "compatibility_flags": ["nodejs_compat"], "assets": { "binding": "ASSETS" }, "env": { "production": { "vars": { "APP_NAME": "redwoodsdk-production" }, "routes": [ { "pattern": "rwsdk.com", "custom_domain": true }, { "pattern": "www.rwsdk.com", "custom_domain": true } ], "kv_namespaces": [ { "binding": "KV_ADDON_CHANGELOG", "id": "c934e8cdc828424f8ccfbdd002fb9a7e" } ] } }, "r2_buckets": [ { "bucket_name": "rwsdk-blog", "binding": "R2" } ], "kv_namespaces": [ { "binding": "KV_ADDON_CHANGELOG", "id": "c934e8cdc828424f8ccfbdd002fb9a7e" } ], "observability": { "enabled": true } } ``` -------------------------------- ### Deploy RedwoodSDK application to production (bash) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/redwoodsdk-and-cloudflare-environments.md Runs the standard release command to deploy the RedwoodSDK app to the production environment defined in wrangler.jsonc. Assumes Cloudflare credentials are configured and the default environment is production. No additional flags are required. ```bash pnpm release ``` -------------------------------- ### Initialize RWSdk Worker and Client in TypeScript Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt Defines the main worker with a Document wrapper and a set of routes including redirects, sitemap/robots generation, and a 404 fallback. The client snippet initializes the RWSdk client for hydration. Dependencies: rwsdk/worker, rwsdk/router, and project pages/components. Inputs: route handlers and middleware; Outputs: HTTP responses for the configured routes and hydrated client. ```typescript // src/worker.tsx import { defineApp } from "rwsdk/worker"; import { index, render, route, prefix } from "rwsdk/router"; import { Document } from "src/Document"; import Home from "src/pages/Home"; import { setCommonHeaders } from "src/headers"; import sitemap from "./sitemap"; import PersonalSoftware from "src/pages/readme/PersonalSoftware"; import { notFound } from "src/utils/notFound"; import { changelogRoutes } from "src/addons/changelog/routes"; import { blogRoutes } from "./app/addons/blog"; import StartPage from "./app/pages/Start"; export type AppContext = {}; export default defineApp([ // Apply headers middleware to all routes setCommonHeaders(), // Wrap routes with Document component for HTML shell render(Document, [ route("/", Home), route("/personal-software", PersonalSoftware), // Blog routes with prefix prefix("/blog", blogRoutes), route('/start', StartPage), // Redirect to external docs route("/docs", async () => { return new Response(null, { status: 301, headers: { Location: "https://docs.rwsdk.com" }, }); }), route("/docs/getting-started/quick-start/", async () => { return new Response(null, { status: 301, headers: { Location: "https://docs.rwsdk.com/getting-started/quick-start/" }, }); }), // Sitemap generation route("/sitemap.xml", async () => { return new Response(sitemap, { status: 200, headers: { "Content-Type": "application/xml" }, }); }), // Robots.txt route("/robots.txt", async () => { const robotsTxt = `User-agent: * Allow: / Disallow: /start Sitemap: https://rwsdk.com/sitemap.xml`; return new Response(robotsTxt, { status: 200, headers: { "Content-Type": "text/plain" }, }); }), // Changelog routes prefix("/changelog", changelogRoutes), // 404 fallback route("*", async () => { return notFound(); }), ]), ]); ``` ```typescript // src/client.tsx import { initClient } from "rwsdk/client"; // Initialize RedwoodSDK client for hydration initClient(); ``` -------------------------------- ### Fetch GitHub Releases with KV Caching (TypeScript) Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt Fetches releases from the GitHub API, caches them in Cloudflare KV with a 60-minute TTL, and parses markdown bodies to HTML. Includes a function to purge the entire cache. Dependencies: Cloudflare Workers `env`, `marked` for markdown parsing, and `highlight.js` for syntax highlighting. ```typescript // src/app/addons/changelog/githubApi.ts import { env } from "cloudflare:workers"; import type { GitHubRelease } from "./types"; import { marked } from "marked"; import { markedHighlight } from "marked-highlight"; import hljs from "highlight.js"; // Configure marked with syntax highlighting marked.use( markedHighlight({ langPrefix: "hljs language-", highlight(code, lang) { const language = hljs.getLanguage(lang) ? lang : "plaintext"; return hljs.highlight(code, { language }).value; }, }) ); marked.setOptions({ gfm: true, breaks: true, pedantic: false, }); export async function purgeCache() { const { keys } = await env.KV_ADDON_CHANGELOG.list(); for (const key of keys) { await env.KV_ADDON_CHANGELOG.delete(key.name); } } export async function fetchReleases(repo: string, perPage: number = 10) { // Check if cache is valid (60 minutes TTL) const lastUpdate = await env.KV_ADDON_CHANGELOG.get("lastUpdate"); if (lastUpdate) { const { keys } = await env.KV_ADDON_CHANGELOG.list(); return keys .filter((key) => key.name.startsWith("release-")) .map((key) => key.name) .sort((a, b) => a > b ? -1 : 0); } // Fetch from GitHub API const response = await fetch( `https://api.github.com/repos/redwoodjs/sdk/releases?per_page=${perPage}`, { headers: { "User-Agent": "RedwoodSDK", Accept: "application/vnd.github.v3+json", "Content-Type": "application/json", }, } ); await purgeCache(); const data = await response.json(); // Store each release in KV with markdown parsed to HTML for (const release of data) { const key = `release-${release.published_at.toString()}-${release.id}`; release.body = await marked(release.body); await env.KV_ADDON_CHANGELOG.put(key, JSON.stringify(release)); } // Set cache timestamp with 60 minute expiration await env.KV_ADDON_CHANGELOG.put("lastUpdate", new Date().toISOString(), { expirationTtl: 60_000, // 60 minutes }); return data.map((release) => `release-${release.id}`); } ``` -------------------------------- ### Configure staging and production environments in Wrangler (jsonc) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/redwoodsdk-and-cloudflare-environments.md Defines environment-specific variables and routes in the wrangler.jsonc file to differentiate staging and production deployments. Requires Cloudflare Wrangler and a RedwoodSDK project. Outputs a configuration object that Cloudflare uses during deployment. ```jsonc { "env": { "staging": { "vars": { "APP_NAME": "redwoodsdk-staging" } }, "production": { "vars": { "APP_NAME": "redwoodsdk-production" }, "routes": [ { "pattern": "rwsdk.com", "custom_domain": true }, { "pattern": "www.rwsdk.com", "custom_domain": true } ] } } } ``` -------------------------------- ### Integrate Blog Addon into Worker Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/full-stack-colocation.md This TypeScript code shows how to integrate the previously defined 'blogAddon' into the main application's worker file using RedwoodSDK. It uses 'defineApp' to register the addon, prefixed under the '/blog' path, making the blog accessible at '/blog' and '/blog/:slug'. ```tsx // src/worker.tsx import { defineApp } from "rwsdk/worker"; import { blogAddon } from "./addons/blog/routes.tsx"; export default defineApp([ // existing routes... prefix("/blog", blogAddon), ]); ``` -------------------------------- ### Configure Blog Routes with MDX Support in RedwoodJS RWSdk Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt This configuration defines routes for a blog system, including an index route for the blog listing page and dynamic routes for individual posts validated by slug existence. It relies on 'rwsdk/router' for route and index functions, along with custom components like BlogList and BlogPage, and a data module for post slugs. Inputs include route parameters like slug, with outputs being the rendered pages or a not-found response if the slug is invalid; it supports MDX for blog content rendering. ```typescript // src/app/addons/blog/routes.ts import { route, index } from "rwsdk/router"; import BlogList from "./pages/BlogList"; import BlogPage from "./pages/BlogPage"; import { notFound } from "src/utils/notFound"; import { blogPostSlugs } from "./data/posts"; export const blogRoutes = [ // Blog listing page at /blog index(BlogList), // Individual blog posts at /blog/:slug route("/:slug", [ // Middleware: validate slug exists async ({ params }) => { const slug = params.slug; if (!blogPostSlugs.includes(slug)) { return notFound(); } }, BlogPage, ]), ]; ``` -------------------------------- ### Define Blog Addon Routes and RSS Feed Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/full-stack-colocation.md This TypeScript code defines the routes for a blog addon using RedwoodSDK's router. It includes routes for the home page, individual posts by slug, and an RSS feed. It utilizes the 'rss' library to generate the XML feed, demonstrating how server logic can be co-located within an addon. ```tsx // src/addons/blog/routes.tsx import { render, route } from "rwsdk/router"; import { Document } from "./Document"; import { BlogHomePage } from "./pages/HomePage"; import { BlogPostPage } from "./pages/PostPage"; import RSS from "rss"; export const blogAddon = render(Document, [ route("/", BlogHomePage), route("/:slug", BlogPostPage), route("/blog.rss", async function () { const feed = new RSS({}); /* [snip] */ return new Response(feed.xml(), { headers: { "content-type": "application/xml" }, }); }), ]); ``` -------------------------------- ### Classic React Frontend: Fetching Data via API Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/true-js-fullstack.md Demonstrates a traditional React component fetching user data from a separate backend API. This involves setting up a React component with `useState` and `useEffect` hooks, and a backend server (Node.js/Python) to handle the API endpoint for database queries. ```javascript // React component export default function UsersPage() { const [users, setUsers] = useState([]) useEffect(() => { fetch('/api/users') .then((res) => res.json()) .then((data) => setUsers(data)); }, []); return ... } // Node / Python etc server, on a seperate server somewhere app.get('/api/users', async (req, res) => { const users = await db.query('SELECT * FROM users'); res.json(users); }); ``` -------------------------------- ### Initialize client-side navigation in RedwoodSDK Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/spa-is-dead.md This code snippet demonstrates how to set up client-side navigation in a RedwoodSDK application. It imports and initializes client navigation features that intercept link clicks and handle page transitions using React Server Components streaming. The implementation provides SPA-like navigation while preserving HTTP semantics like cookies and redirects. ```javascript // src/client.tsx import { initClient, initClientNavigation } from "rwsdk/client"; initClientNavigation(); initClient() ``` -------------------------------- ### Deploy RedwoodSDK application to staging (bash) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/redwoodsdk-and-cloudflare-environments.md Sets the CLOUDFLARE_ENV variable to 'staging' before executing the release command, directing the deployment to the staging environment defined in wrangler.jsonc. Useful for testing changes before production release. ```bash CLOUDFLARE_ENV=staging pnpm release ``` -------------------------------- ### Configure Vite with RedwoodSDK Plugin Source: https://context7.com/redwoodjs/rwsdk.com/llms.txt This TypeScript configuration file sets up Vite for the RedwoodSDK project, enabling server-side rendering, React Server Components, and MDX support. It depends on Vite, RedwoodSDK, TailwindCSS, and MDX plugins. The config defines plugin arrays and environments, outputting a configured build system. It requires Node.js and may have compatibility workarounds for TailwindCSS in SSR environments. ```typescript // vite.config.mts import { defineConfig } from "vite"; import tailwindcss from "@tailwindcss/vite"; import { redwood } from "rwsdk/vite"; import mdx from "@mdx-js/rollup"; import remarkFrontmatter from "remark-frontmatter"; import remarkMdxFrontmatter from "remark-mdx-frontmatter"; export default defineConfig({ environments: { // Workaround for tailwindcss compatibility ssr: {}, }, plugins: [ tailwindcss(), redwood(), // RedwoodSDK plugin enables SSR, RSC, and server functions mdx({ remarkPlugins: [remarkFrontmatter, remarkMdxFrontmatter], }), ], }); ``` -------------------------------- ### Define RedwoodJS App Routes and Middleware (TypeScript) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/do-db-exporer.md Sets up the main application routes and middleware for a RedwoodJS application. Includes a middleware to restrict access to localhost environments, ensuring the explorer is not exposed publicly. It renders the `Document` component with defined routes for the home page and dynamic table views. ```typescript import { defineApp, render, route, setCommonHeaders, } from "@redwoodjs/rws-runtime"; import { isLocalhost, } from "@redwoodjs/rws-runtime/middleware"; import Document from "./Document"; import Home from "./app/pages/Home"; export default defineApp([ setCommonHeaders(), ({ ctx }) => { // middleware interruptor to stop the request if not localhost isLocalhost(); ctx; }, render(Document, [ route("/", Home), route("/:table", Home), ]), ]); ``` -------------------------------- ### Configure Per-Route Document Rendering in RedwoodSDK Worker (TS) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/redwoodsdk-multiple-documents.md This RedwoodSDK worker configuration defines how different document types are rendered for various routes. It uses `defineApp`, `render`, `route`, and `prefix` from `rwsdk/worker` and `rwsdk/router`. It allows specifying `StaticDocument`, `StandardDocument`, and `RealtimeDocument` for different route groups, demonstrating flexible rendering strategies. ```ts // src/worker.tsx import { defineApp } from 'rwsdk/worker' import { render, route, prefix } from 'rwsdk/router' import { StaticDocument } from '@/app/StaticDocument.tsx' import { StandardDocument } from '@/app/StandardDocument.tsx' import { RealtimeDocument } from '@/app/RealtimeDocument.tsx' export default defineApp([ render(StaticDocument, [ route('/', HomePage), prefix('/blog', blogRoutes), ]), render(StandardDocument, [ prefix('/app/user', userRoutes), ]) render(RealtimeDocument, [ prefix('/app/dashboard', dashboardRoutes), ]) ]) ``` -------------------------------- ### Server Action (`getUsers`) in TypeScript Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/react-rsc-redwoodsdk.md This server function runs on the server and fetches data from a D1 Prisma-powered database. It is marked with 'use server' to indicate it's a server action. ```TypeScript // src/app/functions.ts "use server"; import { db } from "@/db"; export async function getUsers() { const users = await db.user.findMany(); return users; } ``` -------------------------------- ### Configure Durable Objects and AI Binding in Wrangler (JSON) Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/do-db-exporer.md Configures the `wrangler.jsonc` file for a Cloudflare Worker project. It defines Durable Object bindings, including the `APP_DURABLE_OBJECT` class `AppDurableObject`, and an AI binding named 'AI'. It also specifies migration tags and new SQLite classes required for deployment. ```json { "durable_objects": { "bindings": [ { "name": "APP_DURABLE_OBJECT", "class_name": "AppDurableObject" } ] }, "ai": { "binding": "AI" }, "migrations": [ { "tag": "v1", "new_sqlite_classes": ["AppDurableObject"] } ] } ``` -------------------------------- ### RedwoodSDK Route Definition with JSX Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/your-react-meta-framework-feels-broken.md Demonstrates defining a blog post route in RedwoodSDK, where the route handler directly returns a JSX element, which can be a client or server component. It utilizes RedwoodSDK's `defineApp` and `route` functions for configuration. ```tsx // worker.tsx import { defineApp } from "rwsdk/worker"; import { route } from "rwsdk/router"; export default defineApp([ route("/blog/:slug", ({ params }) => { const post = await getPost(params.slug); return
{post}
; }), ]); ``` -------------------------------- ### RedwoodSDK Markdown Renderer with Highlight.js Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/web-components.md This TypeScript component renders Markdown content and highlights code blocks using the highlight.js library. It uses dangerouslySetInnerHTML to render the HTML and useEffect to apply the highlighting after the component mounts. ```tsx use client; import { useEffect, useRef } from "react"; import hljs from "highlight.js"; export default function Content({ content }: { content: string }) { const ref = useRef(null); useEffect(() => { if (!ref.current) return; ref.current.querySelectorAll("pre code").forEach((block) => { hljs.highlightElement(block as HTMLElement); }); }, [content]); return (
); } ``` -------------------------------- ### Configure AI binding in wrangler.json Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/redwoodsdk-streaming-guide.md Sets up the AI binding in the Cloudflare Workers configuration file to enable AI model access. ```json { "ai": { "binding": "AI" } } ``` -------------------------------- ### Implement Quick CRUD Helper in TypeScript Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/do-db-exporer.md This TypeScript function provides a basic 'insert' capability for database tables using server actions. It includes a check to ensure the target table exists before attempting the insertion. It relies on an existing database connection (db) and expects table name and row data as input. ```typescript export async function insertRow(tableName: string, row: Record) { const adb: any = db; const masterRows = await adb.selectFrom("sqlite_master").selectAll().execute(); const table = masterRows.find((r: any) => r.name === tableName); if (!table) throw new Error(`Table ${tableName} not found`); await adb.insertInto(tableName as any).values(row).execute(); } ``` -------------------------------- ### Seed Data with Workers AI in TypeScript Source: https://github.com/redwoodjs/rwsdk.com/blob/main/src/app/addons/blog/data/posts/do-db-exporer.md This TypeScript snippet demonstrates seeding a table with AI-generated data using Workers AI. It includes steps for calling the AI model with a prompt, coercing the returned data to match the SQLite schema (handling string types and NOT NULL constraints), and then inserting the data after clearing the existing table. It requires access to `env.AI` and assumes `coercedData` is prepared. ```typescript // @ts-ignore const ai = env.AI; const response = await ai.run("@cf/meta/llama-3.1-8b-instruct", { prompt: `Generate 10 rows for table ...`, max_tokens: 4000, temperature: 0.2, }); // Coerce text columns to strings, validate NOT NULLs, then insert await adb.deleteFrom(tableName as any).execute(); await adb.insertInto(tableName as any).values(coercedData).execute(); ```