### Install Datastar Starter Kit Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/datastar/README.md Installs the Datastar starter kit using npx, navigates into the directory, installs dependencies, and starts the PocketBase server. ```bash npx tiged benallfree/pocketpages/packages/starters/datastar . cd datastar npm i pocketbase serve --dir=pb_data --dev ``` -------------------------------- ### Install and Run DaisyUI Docs Starter Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/daisyui-docs/README.md Installs the starter kit, navigates into the directory, installs dependencies, starts the development server, and runs the PocketBase server. ```bash npx tiged benallfree/pocketpages/starters/daisyui-docs . cd daisyui-docs npm i npm run dev pocketbase serve --dir=pb_data --dev ``` -------------------------------- ### Install MPA Auth Demo Starter Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/auth/README.md Installs the starter kit, navigates into the directory, installs dependencies, and starts the PocketBase development server and Maildev. ```bash npx tiged benallfree/pocketpages/packages/starters/auth . cd auth npm i pocketbase --dir=pb_data --dev serve bunx maildev ``` -------------------------------- ### Install and Run MVP Starter Kit Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/mvp/README.md Installs the MVP starter kit using npx and starts a local PocketBase development server. ```bash npx tiged benallfree/pocketpages/starters/mvp . cd mvp pocketbase --dir=pb_data --dev serve ``` -------------------------------- ### Install HTMX Starter Kit Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/htmx/README.md Installs the HTMX starter kit using npx, navigates into the directory, installs npm dependencies, and starts the PocketBase development server. ```bash npx tiged benallfree/pocketpages/packages/starters/htmx . cd htmx npm i pocketbase serve --dir=pb_data --dev ``` -------------------------------- ### Install and Run Minimal PocketPages Starter Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/minimal/README.md Use these commands to install the starter kit, navigate to its directory, and start the PocketBase development server. ```bash npx tiged benallfree/pocketpages/starters/minimal . cd minimal pocketbase --dir=pb_data --dev serve ``` -------------------------------- ### Install PocketPages Auth Starter Kit Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/authentication/oauth2.md Use npx to install the authentication starter kit for PocketPages. Navigate into the created directory and install dependencies. ```bash npx tiged benallfree/pocketpages/starters/auth my-auth-app cd my-auth-app npm i ``` -------------------------------- ### Example File Resolution with include() and resolve() Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/private-files.md Shows how `include()` and `resolve()` functions search for files within `_private` directories, starting from the current directory and moving up the tree. ```ejs <%% // In /products/categories/index.ejs: // Looks for category-nav first in local _private, then up the tree include('category-nav.ejs') // Uses /products/categories/_private/category-nav.ejs // Product card isn't in local _private, so checks parent directories include('product-card.ejs') // Uses /products/_private/product-card.ejs // Global layout is found in the root _private include('layout.ejs') // Uses /_private/layout.ejs // Same pattern works for resolve const helpers = resolve('helpers') // Uses local /categories/_private/helpers.js const queries = resolve('queries') // Uses parent /products/_private/queries.js const config = resolve('config') // Uses root /_private/config.js %> ``` -------------------------------- ### Install and Run DaisyUI PocketPages Starter Source: https://github.com/benallfree/pocketpages/blob/main/packages/starters/daisyui/README.md Use these commands to clone the starter kit, install dependencies, and run the development server for both the PocketPages app and PocketBase. ```bash npx tiged benallfree/pocketpages/packages/starters/daisyui . cd daisyui npm i npm run dev pocketbase serve --dir=pb_data --dev ``` -------------------------------- ### Start Development Server Source: https://github.com/benallfree/pocketpages/blob/main/README.md Command to start the PocketPages development server in the root folder. ```bash bun dev ``` -------------------------------- ### Install PocketPages Realtime Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/realtime/README.md Install the plugin using npm. ```bash npm install pocketpages-plugin-realtime ``` -------------------------------- ### Install Auth Starter Kit Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/authentication/overview.md Use this command to download and install the complete authentication starter kit for PocketPages. This kit includes UI, all authentication methods, email verification, account management, password reset, middleware protection, and auth status layout. ```bash npx tiged benallfree/pocketpages/starters/auth . ``` -------------------------------- ### Install PHIO CLI Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/deploying.md Install the PocketHost.IO CLI utility globally to manage deployments to pockethost.io. ```bash npm i -g phio ``` -------------------------------- ### Example Usage with Frontmatter and Dynamic Content Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/marked.md Demonstrates a complete example combining frontmatter, dynamic content retrieval, and EJS loops within a Markdown file. ```markdown --- title: Getting Started layout: docs --- # <%%%= meta('title') %> <<%%=`script server`%>> const features = pb.collection('features').getFullList() ## Key Features <%%% features.forEach(feature => { %> ### <%%%= feature.name %> <%%%= feature.description %> ![<%%%= feature.name %>](<%%%= feature.image %>) <%%% } %> ``` -------------------------------- ### Install Markdown Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/marked/README.md Install the pocketpages-plugin-marked using npm. ```bash npm install pocketpages-plugin-marked ``` -------------------------------- ### Install Bun Source: https://github.com/benallfree/pocketpages/blob/main/README.md Command to install the Bun JavaScript runtime using the official installation script. ```bash curl -fsSL https://bun.sh/install | bash ``` -------------------------------- ### Complete Login Form Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/sign-in-with-password.md Provides a full HTML form example for user login using `signInWithPassword`. It includes input fields for email and password, form submission handling, and error display. ```ejs <%%= if (request.method === 'POST') { try { const { email, password } = formData // Validate required fields if (!email || !password) { throw new Error('Email and password are required') } // Attempt login const authData = signInWithPassword(email, password) // Successful login - redirect to dashboard redirect('/dashboard') } catch (error) { // Login failed %>
Login failed: <%%= error.message %>
<%% } } %> ``` ```html
``` -------------------------------- ### Serve PocketBase (Minimal Starter) Source: https://github.com/benallfree/pocketpages/blob/main/README.md Command to start the PocketBase server for the minimal starter kit, located in the 'packages/starters/minimal' directory. ```bash cd packages/starters/minimal pocketbase serve --dev ``` -------------------------------- ### Install JS SDK Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/js-sdk/README.md Install the pocketpages-plugin-js-sdk using npm. ```bash npm install pocketpages-plugin-js-sdk ``` -------------------------------- ### Install PocketPages Datastar Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/datastar/README.md Install the Datastar plugin using npm. This is the first step to integrating Datastar functionality. ```bash npm install pocketpages-plugin-datastar ``` -------------------------------- ### Serve PocketBase (Main Site) Source: https://github.com/benallfree/pocketpages/blob/main/README.md Command to start the PocketBase server for the main site, located in the 'packages/site' directory. ```bash cd packages/site pocketbase serve --dev ``` -------------------------------- ### HTTP Method-Specific Middleware (GET) Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/middleware.md Example of a '+get.js' middleware file that runs exclusively for GET requests. ```javascript // +get.js - Only runs for GET requests /** @type {import('pocketpages').MiddlewareLoaderFunc} */ module.exports = function (api) { // Handle GET requests return {} ``` -------------------------------- ### Install Micro Dash Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/micro-dash/README.md Install the pocketpages-plugin-micro-dash package using npm. ```bash npm install pocketpages-plugin-micro-dash ``` -------------------------------- ### Global Configuration Module Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/resolve.md Example of a global configuration file exported using `module.exports`. ```javascript // _private/config.js module.exports = { apiKey: env.API_KEY, baseUrl: 'https://api.example.com', limits: { maxUploadSize: 5 * 1024 * 1024, maxResults: 100, }, } ``` -------------------------------- ### Complete Registration Form Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/register-with-password.md Provides a full HTML form example for user registration using `registerWithPassword`. It includes client-side form submission handling, basic validation (password match, required fields), user creation, and redirection upon success or displays an error message on failure. ```ejs <%% if (request.method === 'POST') { const { email, password, confirmPassword } = formData try { // Basic validation if (!email || !password) { throw new Error('Email and password are required') } if (password !== confirmPassword) { throw new Error('Passwords do not match') } // Create user and sign in const authData = registerWithPassword(email, password) // User is now registered and logged in redirect('/welcome') } catch (error) { // Registration failed %>
Registration failed: <%%= error.message %>
<%% } } %>
``` -------------------------------- ### Directory Structure Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/resolve.md Organize related functionality into logical directories within the _private folder. ```directory _private/ config/ development.js production.js auth/ permissions.js validation.js ``` -------------------------------- ### Basic +config.js Structure Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/config.md A basic example of a `+config.js` file showing different ways to configure plugins. ```javascript module.exports = { plugins: [ // String format (shorthand) 'pocketpages-plugin-ejs', // Object format with name { name: 'pocketpages-plugin-ejs', // npm package name extensions: ['.ejs', '.md'], debug: false, }, // Direct factory function (config, options) => ({ // plugin implementation }), // Object format with explicit factory function { fn: (config, options) => ({ // plugin implementation }), debug: false, // other options... }, ], debug: false, } ``` -------------------------------- ### File-Based Routing Directory Structure Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/routing.md Illustrates how directories and files map to URL routes in PocketPages. Special directories like `_private` and files starting with `+` are excluded from routing. ```text pb_hooks/ pages/ _private/ # Not routable - for private files header.ejs config.js products/ +load.js # Not routable - special PocketPages file +layout.ejs # Not routable - special PocketPages file index.ejs # Routable at /products details.ejs # Routable at /products/details ``` -------------------------------- ### Install PocketPages Auth Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/auth/README.md Install the authentication plugin using npm. This is the first step to integrate authentication into your PocketPages application. ```bash npm install pocketpages-plugin-auth ``` -------------------------------- ### Set and Get Values with store Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/global-api/store.md Demonstrates basic usage of the `store` function to set a value and then retrieve it. ```javascript // Set a value store('myKey', 'myValue') // Get a value const value = store('myKey') ``` -------------------------------- ### Complete Product Details Page Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/params.md A full EJS template example for a product details page. It destructures 'category' and 'id' from params, performs a database query, handles 404s, and renders product information. Includes a debug section to display all params. ```ejs <%%= // products/[category]/[id].ejs const { category, id } = params // Use parameters for database query const product = await db.collection('products') .getOne(id) if (!product || product.category !== category) { response.html(404, `

Product Not Found

`) return } %> <%%= product.name %> - <%%= category %>

<%%= product.name %>

Category: <%%= category %>

Product ID: <%%= id %>

Price: $<%%= product.price %>

Description: <%%= product.description %>

Route Parameters
<%%= stringify(params) %>
``` -------------------------------- ### Install Prettier EJS Plugin Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/prettier.md Install the prettier-plugin-ejs package as a development dependency using bun. ```bash bun add -D prettier-plugin-ejs ``` -------------------------------- ### Example Usage: Authentication Context Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/request.md Shows how to access authenticated user information and use it with the PocketBase client. ```APIDOC ## Example Usage: Authentication Context ### Access Auth Record and PB Client ```ejs <%% if (request.auth) { // Access auth record properties const { id, email } = request.auth // Use with pb() client const client = pb({ request }) } %> ``` ``` -------------------------------- ### OAuth2 Callback Route Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/sign-in-with-oauth2.md This example demonstrates how to use signInWithOAuth2 within a server-side script on your OAuth2 callback route. It handles the redirection and potential errors. ```javascript ``` -------------------------------- ### Product List Data Loader (+load.js) Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/loading-data.md A +load.js example for the '/products' route, fetching active products sorted by creation date. ```javascript /** @type {import('pocketpages').PageDataLoaderFunc} */ module.module.exports = function (api) { const products = $app.findRecordsByFilter('products', { filter: 'active = true', sort: '-created', }) return { products } } ``` -------------------------------- ### Example Private Directory Structure Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/private-files.md Demonstrates a nested directory structure showcasing global and section-specific private files. ```text pb_hooks/ pages/ _private/ # Global shared files layout.ejs # Base layout template auth.js # Authentication utilities config.js # Global configuration products/ _private/ # Product-specific files product-card.ejs # Product display partial queries.js # Product database queries categories/ _private/ # Category-specific files category-nav.ejs # Category navigation partial helpers.js # Category-specific utilities index.ejs index.ejs index.ejs ``` -------------------------------- ### Basic File-Based Routing Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/routing.md Shows a simple directory structure and the corresponding URL routes for root-level and nested pages. ```text pb_hooks/ pages/ about.ejs contact.ejs index.ejs products/ details.ejs index.ejs reviews/ index.ejs latest.ejs ``` -------------------------------- ### Plugin Processing Order Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/config.md Demonstrates how the order of plugins in the `plugins` array affects processing. This example shows EJS processing within Markdown files. ```javascript module.exports = { plugins: [ // Processes first - enables EJS in Markdown { name: 'pocketpages-plugin-ejs', extensions: ['.ejs', '.md'], }, // Processes second - converts Markdown to HTML 'pocketpages-plugin-marked', ], } ``` -------------------------------- ### Setting Environment Variables in .env File Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/secrets.md Provides an example of how to define environment variables in a `.env` file for local development. ```bash # .env file API_KEY=your_api_key DB_PASSWORD=your_db_password ``` -------------------------------- ### Complete OTP Flow Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/sign-in-with-otp.md A full example of an OTP authentication flow, including requesting a new OTP, confirming an OTP, and handling errors. This snippet is designed to be integrated into an HTML form for user interaction. ```ejs <%%= let error = null let otpId = request.body().otpId || null const { mode, otpCode, identity } = { mode: 'otp-request', ...request.body() } if (request.method === 'POST') { switch (mode) { case 'otp-request': try { // Request a new OTP code const res = requestOTP(identity) otpId = res.otpId } catch (e) { error = e.message } break case 'otp-confirm': try { // Verify the OTP code const res = signInWithOTP(otpId, otpCode) redirect('/', { message: 'Login successful' }) } catch (e) { error = e.message } break } } %> ``` ```html <%% if (error) { %> <%%= error %> <%% } %>

We have sent you an OTP code

Please check your email for the OTP code and enter it below.

Didn't receive an OTP code?
``` -------------------------------- ### Complete Response with Headers and JSON Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/response.md Example demonstrating setting multiple headers, a secure cookie, and sending a JSON response. ```ejs <%%= // Set headers response.header('Cache-Control', 'no-cache') response.header('X-Custom-Header', 'custom-value') // Set a cookie response.cookie('session', 'xyz789', { httpOnly: true, secure: true }) // Send JSON response response.json(200, { success: true, data: { message: 'Operation completed' } }) %> ``` -------------------------------- ### Example Usage: Basic Request Information Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/request.md Demonstrates how to retrieve the HTTP method, URL, and specific headers from the request object. ```APIDOC ## Example Usage: Basic Request Information ### Get Method and URL ```ejs <%% // Get method and URL const { method, url } = request // Access query parameters const page = url.query.page const sort = url.query.sort // Get headers const userAgent = request.header('User-Agent') %> ``` ``` -------------------------------- ### Product List Data Loader Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/data.md Example of a `+load.js` file for a product list route, fetching and returning active categories. ```javascript /** @type {import('pocketpages').PageDataLoaderFunc} */ module.exports = function (api) { const categories = $app.findRecordsByFilter('categories', { filter: 'active = true', sort: 'name', }) return { categories } ``` -------------------------------- ### Documenting Required Environment Variables Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/secrets.md Shows an example of documenting required environment variables using JSDoc comments for clarity. ```javascript /** * Required environment variables: * - API_KEY: External service API key * - DB_PASSWORD: Database password * - SMTP_PASSWORD: Email service password */ ``` -------------------------------- ### Example PocketPages Directory Structure Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/directory-structure.md Illustrates the mandatory `pb_hooks/pages/` root directory and how to organize flat and nested page files using EJS templates. ```plaintext pb_hooks/ pages/ index.ejs about.ejs contact.ejs products/ index.ejs details.ejs ``` -------------------------------- ### Counter with Realtime Updates Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/datastar/README.md This example shows how to increment a counter stored in the application and then return the updated counter, presumably for a realtime update. ```javascript // Increment counter $app.runInTransaction(() => { store('count', (store('count') || 1) + 1) }) // Return updated counter <%- include('count.ejs') %> ``` -------------------------------- ### Include Partial using Absolute Path Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/partials.md Demonstrates how to use an absolute path starting from the root to explicitly include a specific partial file. ```ejs <%%- include('/blog/_private/blog-sidebar.ejs', { api }) %> // Explicitly uses /blog/_private/blog-sidebar.ejs ``` -------------------------------- ### onRequest Hook Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/authoring.md The onRequest hook is called at the start of each request to modify request or response objects. ```javascript onRequest({ request, response }) { // Modify request/response // Add headers, check auth, etc. } ``` -------------------------------- ### Micro Dash Collection Operations Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/micro-dash.md Demonstrates using forEach, keys, and values for iterating and accessing data within collections. ```ejs <%%% // Iterate over arrays or objects forEach([1, 2, 3], (value) => { echo(value) }) // Get object keys const obj = { a: 1, b: 2 } const objKeys = keys(obj) // ['a', 'b'] // Get object values const objValues = values(obj) // [1, 2] %> ``` -------------------------------- ### Get Page Title in EJS Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/meta.md Example of retrieving the 'title' metadata value within an EJS template. This is useful for dynamically setting the page's title. ```ejs <%% const pageTitle = meta('title'); %> ``` -------------------------------- ### Copy GitHub Actions Starter for pockethost.io Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/deploying.md Copy the starter files for setting up automated deployments to pockethost.io using Github Actions. ```bash cp -r node_modules/pocketpages/starters/deploy-pockethost-ga . ``` -------------------------------- ### Client-Side Button Click Binding Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/datastar.md Example of using a data-on-click attribute to trigger a GET request to an API endpoint and update a span with data-bind-count. Assumes Datastar loader script is included. ```html ``` -------------------------------- ### Copy Starter Files for Fly.io Deployment Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/deploying.md Copy the starter files for setting up deployment to Fly.io. This includes a Dockerfile and fly.toml. ```bash cp -r node_modules/pocketpages/starters/deploy-fly-ga . ``` -------------------------------- ### Basic EJS Template Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/loading-data.md A simple EJS template demonstrating how to display site name and iterate through navigation items using loaded data. ```ejs

<%%= data.siteName %>

``` -------------------------------- ### Use PocketPages Site as a Starter Kit Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/RADME.md Clone the PocketPages site repository to use it as a starter kit for your project. Navigate into the cloned directory and start the PocketBase development server. ```bash bunx tiged benallfree/pocketpages/site . cd site pocketbase serve --dir=pb_data --dev ``` -------------------------------- ### All Plugin Configuration Formats Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/config.md Illustrates all supported formats for configuring plugins within `+config.js`, including string shorthand, object with name, direct factory, and object with explicit factory. ```javascript module.exports = { plugins: [ // Format 1: String shorthand (npm package name) 'pocketpages-plugin-ejs', // Format 2: Object with npm package name { name: 'pocketpages-plugin-ejs', debug: false, // Any other options are passed to the plugin extensions: ['.ejs', '.md'], }, // Format 3: Direct factory function (config, options) => ({ onRequest(context) { config.global.dbg('Request:', context.request.method) }, }), // Format 4: Object with explicit factory { fn: (config, options) => ({ onRequest(context) { config.global.dbg('Request:', context.request.method) }, }), debug: false, // Any other options are passed to the plugin }, ], } ``` -------------------------------- ### Setting Environment Variables in Production Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/secrets.md Shows how to set environment variables directly in the production hosting environment using the `export` command. ```bash # Set directly in your hosting environment export API_KEY=your_api_key export DB_PASSWORD=your_db_password ``` -------------------------------- ### Get OAuth2 Login URL Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/request-oauth2-login.md Call requestOAuth2Login with the provider name to get the authorization URL. This is useful when autoRedirect is set to false. ```javascript const authUrl = requestOAuth2Login(providerName) ``` -------------------------------- ### Single Product Data Loader with 404 Handling Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/data.md Example of a `+load.js` file for a dynamic product route, fetching a specific product by ID and handling not found cases. ```javascript /** @type {import('pocketpages').PageDataLoaderFunc} */ module.exports = function (api) { const { findRecordByFilter, params, response } = api const product = findRecordByFilter('products', { filter: `id = "${params.id}"`, }) if (!product) { response.status(404) return { error: 'Product not found' } } return { product } ``` -------------------------------- ### Protected Route Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/auth.md An EJS example demonstrating how to protect routes by checking for `request.auth`. If the user is not authenticated, they are redirected to the login page. ```ejs <%%%= if (!request.auth) { redirect('/login', { message: 'Please login first', returnTo: request.url }) } // Access auth record properties const userId = request.auth.id const email = request.auth.email %> ``` ```html

Welcome <%%%= request.auth.username %>

``` -------------------------------- ### Basic Chat Example with SSE Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/htmx.md Integrate PocketBase SSE for real-time chat updates. The hx-ext="pocketbase-sse" attribute enables SSE, and sse-swap="topic" subscribes to a topic. ```html
``` ```ejs <%% const { message } = body() realtime.send('chat') %>
<%%= message %>
``` -------------------------------- ### Protected Route Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/auth/README.md Example of an EJS template for a protected route. It checks for `request.auth` and redirects to login if not authenticated. It also shows how to access authenticated user properties. ```ejs <%% if (!request.auth) { redirect('/login', { message: 'Please login first', returnTo: request.url }) } // Access auth record properties const userId = request.auth.id const email = request.auth.email %>

Welcome <%%= request.auth.username %>

``` -------------------------------- ### Basic Realtime Subscription and Message Sending Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/realtime.md Subscribe to a 'ping' topic and send messages to it at a regular interval. This example demonstrates basic SSE data flow. ```html ``` -------------------------------- ### Get and Set Metadata with `meta` Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/meta.md Demonstrates the function signature for getting and setting string values using the `meta` function. Use `meta(key)` to retrieve a value and `meta(key, value)` to set one. ```typescript meta(key: string): string | undefined meta(key: string, value: string): string ``` -------------------------------- ### resolve Examples in Different Contexts Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/resolve.md Illustrates various `resolve` usage patterns including simple names, absolute paths, and level jumping to access modules from different directory levels. ```ejs <%% // In /products/categories/index.ejs: const formatter = resolve('formatter') // Uses /products/categories/_private/formatter.js const queries = resolve('queries') // Uses /products/_private/queries.js const config = resolve('config') // Uses /_private/config.js // Using absolute path const productQueries = resolve('/products/_private/queries') // Level jumping const parentHelpers = resolve('../helpers') // Skips local _private/helpers.js and uses parent's version %> ``` -------------------------------- ### Micro Dash Array Operations Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/micro-dash.md Demonstrates shuffling an array using the shuffle function. ```ejs <%%% // Shuffle an array const numbers = [1, 2, 3, 4, 5] const shuffled = shuffle(numbers) %> ``` -------------------------------- ### Best Practice: Using Appropriate Logging Levels Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/global-api/log.md Demonstrates the correct usage of different logging levels (dbg, info, warn, error) for various scenarios. Avoids misusing severity levels. ```javascript // Good: Correct severity levels dbg('Processing data...') // Development details info('User logged in') // Normal operations warn('Cache miss') // Potential issues error('Database failed') // Actual problems // Bad: Wrong severity error('Processing data...') // Should be dbg dbg('Database failed') // Should be error ``` -------------------------------- ### onRender Hook Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/authoring.md The onRender hook allows transformation of content during the rendering process, such as processing templates. ```javascript onRender({ api, content, filePath, plugins }) { // Transform content // Process templates // Add features return modifiedContent; } ``` -------------------------------- ### HTTP Method-Specific Middleware (POST) Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/middleware.md Example of a '+post.js' middleware file that runs exclusively for POST requests. ```javascript // +post.js - Only runs for POST requests /** @type {import('pocketpages').MiddlewareLoaderFunc} */ module.exports = function (api) { // Handle POST requests return {} ``` -------------------------------- ### Complete EJS Example with Local and Global Assets Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/asset.md Demonstrates how to use the asset() helper for both local (relative paths) and global (absolute paths) assets within a complete HTML structure, including CSS and images. ```ejs Header Logo ``` -------------------------------- ### SPA Example with Content Updates Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/datastar.md Demonstrates a full HTML structure with SPA mode enabled, where navigation links update content within a specified div. ```html <%%- datastar.scripts({ spa: { scope: 'nav', selector: 'content' } }) %>
``` -------------------------------- ### Accessing Passed Data in Partial Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/partials.md Example of how data passed during an include statement is accessed within the partial template. ```ejs

<%%= title %>

<%% if (user) { %> <%% } %>
``` -------------------------------- ### Content with Named Slots Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/layouts.md Example of how to define content sections for named slots within an EJS content file. ```ejs

Product Details

This is the main content of the product page.

``` -------------------------------- ### Simple Layout Using Slot Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/layouts.md A minimal EJS layout example that uses the 'slot' variable to render its content. ```ejs <%%- slot %> ``` -------------------------------- ### Using Global API in Libraries (Example) Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/global-api/index.md Demonstrates how to use Global API functions like dbg and stringify within a custom library function when imported via require('pocketpages').globalApi. ```javascript // myLibrary.js const { globalApi } = require('pocketpages') const { dbg, stringify } = globalApi function processUserData(user) { dbg('Processing user:', stringify(user)) // ... processing logic } module.exports = { processUserData } ``` -------------------------------- ### Section-Specific Utilities Module Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/resolve.md Example of a section-specific utility module for product queries, exporting functions using `module.exports`. ```javascript // products/_private/queries.js module.exports = { getActiveProducts: () => { return $app.findRecordsByExpr('products', 'status = ?', ['active']) }, getCategoryProducts: (categoryId) => { return $app.findRecordsByExpr('products', 'category = ?', [categoryId]) }, } ``` -------------------------------- ### Configuring with Global API Access Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/config.md Example of exporting a function from `+config.js` that receives the global API, allowing access to environment variables and other global settings. ```javascript module.exports = function (api) { return { plugins: [ { name: 'pocketpages-plugin-js-sdk', host: api.env('POCKETPAGES_HOST'), }, 'pocketpages-plugin-ejs', ], debug: true, } } ``` -------------------------------- ### Basic Hello World Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/_private/overview.md A simple EJS template to display 'Hello, world!'. This is the most basic example of a PocketPages template. ```ejs // index.ejs <%%= `Hello, world!` %> ``` -------------------------------- ### Serve a File Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/context-api/response.md Use the `file()` method to serve a file from the filesystem. Specify the file path as an argument. ```ejs <%%= // Serve a PDF file response.file('/path/to/document.pdf') %> ``` -------------------------------- ### Get Object Values with values Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/global-api/micro-dash.md Retrieve an array of an object's own enumerable property values using the values function. ```javascript const { values } = require('pocketpages') const obj = { a: 1, b: 2, c: 3 } const propertyValues = values(obj) // => [1, 2, 3] ``` -------------------------------- ### Sign In and Register with Password Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/authentication/password.md Use `signInWithPassword` to authenticate existing users or `registerWithPassword` to create new users. Both return an AuthData object. ```javascript const authData = api.signInWithPassword(email, password) const authData = api.registerWithPassword(email, password) ``` -------------------------------- ### HTTP Method-Specific Loaders (POST Example) Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/loading-data.md Illustrates the use of method-specific loaders, showing a +post.js file that would run only for POST requests after the general +load.js. ```javascript // Example for pb_hooks/pages/contact/+post.js // This code would execute only for POST requests to the /contact route. ``` -------------------------------- ### Get Object Keys with keys Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/global-api/micro-dash.md Retrieve an array of an object's own enumerable property names using the keys function. ```javascript const { keys } = require('pocketpages') const obj = { a: 1, b: 2, c: 3 } const propertyNames = keys(obj) // => ['a', 'b', 'c'] ``` -------------------------------- ### Get Unauthenticated Client in EJS Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/js-sdk/README.md Obtain an anonymous PocketBase client in an EJS template by calling `pb()` without arguments. ```ejs <%% // Get an anonymous client const client = pb() %> ``` -------------------------------- ### Establish SSE Connection and Handle Events Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/datastar/src/realtime.html Connects to the SSE endpoint, listens for 'PB_CONNECT' and 'datastar' events, and dispatches custom events. Requires a fetch call to subscribe to specific data streams after initial connection. ```javascript const source = new EventSource('/api/realtime') // URL to your SSE endpoint source.addEventListener('PB_CONNECT', function (event) { const e = JSON.parse(event.data) // console.log('PB_CONNECT event:', e) const { clientId } = e fetch(`/api/realtime`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ clientId, subscriptions: ['datastar'], }), }).catch(console.error) patchSignals({ clientId }) }) source.addEventListener('datastar', function (event) { const e = JSON.parse(event.data) // console.log('datastar event:', e) document.dispatchEvent( new CustomEvent('datastar-fetch', { detail: e, }) ) }) ``` -------------------------------- ### Get Authenticated Client in EJS Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/js-sdk/README.md Retrieve an authenticated PocketBase client within an EJS template using the request context. ```ejs <%% // Get an authenticated client for the current request const client = pb({ request }) // Use any PocketBase SDK method with the authenticated context const records = client.collection('posts').getFullList({ sort: '-created', expand: 'author', }) %> ``` -------------------------------- ### EJS Smart Partial Resolution Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/plugins/ejs/README.md Illustrates how the `include` function resolves partials by searching up the directory tree in `_private` folders, trying configured extensions. ```ejs <%%- include('header', { title: 'My Page' }) %> ``` -------------------------------- ### Initialize PocketBase Client Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/global-api/pb.md Instantiate the PocketBase client for use in JSVM. This client is automatically configured based on your `+config.js` settings. ```javascript const pb = require('pocketpages').pb() // Use any PocketBase SDK method const users = pb.collection('users').getFullList() const posts = pb.collection('posts').getList(1, 20) ``` -------------------------------- ### Create New PocketPages Project with npm Source: https://github.com/benallfree/pocketpages/blob/main/packages/create-pocketpages/README.md Use this command to scaffold a new PocketPages project using npm. ```bash npm create pocketpages ``` -------------------------------- ### Example Plugin: API Extension Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/authoring.md An API extension plugin that adds a formatDate method to the context API for formatting dates. ```javascript module.exports = (config, options) => { return { onExtendContextApi: ({ api }) => { api.formatDate = (date) => { return new Date(date).toLocaleDateString() } }, } } ``` -------------------------------- ### Running PocketBase with Data Directory Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/installation.md This command starts PocketBase, ensuring it uses the current directory for data storage. This is a crucial step for PocketPages to function correctly. ```bash cd your_project_directory pocketbase serve --dir=pb_data ``` -------------------------------- ### onResponse Hook Example Source: https://github.com/benallfree/pocketpages/blob/main/packages/site/pb_hooks/pages/(main)/docs/plugins/authoring.md The onResponse hook performs final processing before sending the response, such as modifying output or handling caching. ```javascript onResponse({ api, content }) { // Modify final output // Add headers // Handle caching return false; // Continue processing } ```