├── .changeset ├── README.md └── config.json ├── .cursorrules ├── .gitignore ├── README.md ├── bun.lock ├── freshen-branches.sh ├── package.json └── packages ├── plugins ├── auth │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── ejs │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── js-sdk │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── marked │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── micro-dash │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts └── sse │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts ├── pocketpages ├── CHANGELOG.md ├── README.md ├── package.json ├── src │ ├── handlers │ │ ├── AfterBootstrapHandler.ts │ │ └── MiddlewareHandler.ts │ ├── index.ts │ └── lib │ │ ├── debug.ts │ │ ├── fingerprint.ts │ │ ├── globalApi.ts │ │ ├── helpers.ts │ │ ├── loadPlugins.ts │ │ ├── resolveRoute.ts │ │ └── types.ts ├── tsconfig.json └── tsup.config.ts ├── site ├── CHANGELOG.md ├── RADME.md ├── README.md ├── jsconfig.json ├── logo.png ├── logo.pxd ├── package.json ├── pb_hooks │ ├── pages │ │ ├── (main) │ │ │ ├── +layout.ejs │ │ │ └── docs │ │ │ │ ├── +layout.ejs │ │ │ │ ├── _private │ │ │ │ ├── overview.md │ │ │ │ └── toc.md │ │ │ │ ├── asset-management.md │ │ │ │ ├── authentication.md │ │ │ │ ├── authentication │ │ │ │ ├── anonymous.md │ │ │ │ ├── oauth2.md │ │ │ │ ├── otp.md │ │ │ │ ├── overview.md │ │ │ │ ├── password.md │ │ │ │ └── token.md │ │ │ │ ├── caching.md │ │ │ │ ├── config.md │ │ │ │ ├── context-api │ │ │ │ ├── api.md │ │ │ │ ├── asset.md │ │ │ │ ├── auth.md │ │ │ │ ├── body.md │ │ │ │ ├── data.md │ │ │ │ ├── echo.md │ │ │ │ ├── form-data.md │ │ │ │ ├── index.md │ │ │ │ ├── meta.md │ │ │ │ ├── params.md │ │ │ │ ├── redirect.md │ │ │ │ ├── register-with-password.md │ │ │ │ ├── request-oauth2-login.md │ │ │ │ ├── request.md │ │ │ │ ├── resolve.md │ │ │ │ ├── response.md │ │ │ │ ├── send.md │ │ │ │ ├── sign-in-anonymously.md │ │ │ │ ├── sign-in-with-oauth2.md │ │ │ │ ├── sign-in-with-otp.md │ │ │ │ ├── sign-in-with-password.md │ │ │ │ ├── sign-in-with-token.md │ │ │ │ └── sign-out.md │ │ │ │ ├── creating-a-page.md │ │ │ │ ├── database.md │ │ │ │ ├── debugging.md │ │ │ │ ├── deploying.md │ │ │ │ ├── directory-structure.md │ │ │ │ ├── features.md │ │ │ │ ├── github-deploy-action.md │ │ │ │ ├── global-api │ │ │ │ ├── env.md │ │ │ │ ├── index.md │ │ │ │ ├── log.md │ │ │ │ ├── micro-dash.md │ │ │ │ ├── pb.md │ │ │ │ ├── store.md │ │ │ │ ├── stringify.md │ │ │ │ ├── url.md │ │ │ │ └── users.md │ │ │ │ ├── htmx.md │ │ │ │ ├── index.md │ │ │ │ ├── installation.md │ │ │ │ ├── json.md │ │ │ │ ├── jsvm.md │ │ │ │ ├── layouts.md │ │ │ │ ├── loading-data.md │ │ │ │ ├── markdown.md │ │ │ │ ├── middleware.md │ │ │ │ ├── overview.md │ │ │ │ ├── parameters.md │ │ │ │ ├── partials.md │ │ │ │ ├── plugins │ │ │ │ ├── auth.md │ │ │ │ ├── authoring.md │ │ │ │ ├── ejs.md │ │ │ │ ├── index.md │ │ │ │ ├── js-sdk.md │ │ │ │ ├── markdown.md │ │ │ │ ├── micro-dash.md │ │ │ │ └── realtime.md │ │ │ │ ├── prettier.md │ │ │ │ ├── private-files.md │ │ │ │ ├── realtime.md │ │ │ │ ├── routing.md │ │ │ │ ├── secrets.md │ │ │ │ ├── speedruns │ │ │ │ ├── custom-domain-fly-cloudflare.md │ │ │ │ ├── custom-domain-pockethost.md │ │ │ │ ├── google-oauth2 │ │ │ │ │ ├── 2025-02-08-06-54-56.png │ │ │ │ │ ├── 2025-02-08-06-56-00.png │ │ │ │ │ ├── 2025-02-08-06-56-28.png │ │ │ │ │ ├── 2025-02-08-06-56-56.png │ │ │ │ │ ├── 2025-02-08-06-57-07.png │ │ │ │ │ ├── 2025-02-08-06-57-19.png │ │ │ │ │ ├── 2025-02-08-06-57-27.png │ │ │ │ │ ├── 2025-02-08-06-57-57.png │ │ │ │ │ ├── 2025-02-08-06-58-27.png │ │ │ │ │ ├── 2025-02-08-06-58-37.png │ │ │ │ │ ├── 2025-02-08-06-59-00.png │ │ │ │ │ ├── 2025-02-08-06-59-09.png │ │ │ │ │ ├── 2025-02-08-06-59-17.png │ │ │ │ │ ├── 2025-02-08-06-59-24.png │ │ │ │ │ ├── 2025-02-08-06-59-32.png │ │ │ │ │ ├── 2025-02-08-06-59-59.png │ │ │ │ │ ├── 2025-02-08-07-00-42.png │ │ │ │ │ ├── 2025-02-08-15-28-44.png │ │ │ │ │ └── index.md │ │ │ │ ├── gs-gmail │ │ │ │ │ ├── 2024-09-08-19-04-47.png │ │ │ │ │ ├── 2024-09-08-19-06-15.png │ │ │ │ │ ├── 2024-09-08-19-07-10.png │ │ │ │ │ ├── 2024-09-08-19-07-35.png │ │ │ │ │ ├── 2024-09-08-19-11-38.png │ │ │ │ │ ├── 2024-09-08-19-12-14.png │ │ │ │ │ ├── 2024-09-08-19-12-59.png │ │ │ │ │ ├── 2024-09-08-19-14-04.png │ │ │ │ │ ├── 2024-09-08-19-15-06.png │ │ │ │ │ ├── 2024-09-08-19-21-45.png │ │ │ │ │ ├── 2024-09-08-19-24-55.png │ │ │ │ │ ├── 2024-09-08-19-25-14.png │ │ │ │ │ ├── 2024-09-08-19-25-59.png │ │ │ │ │ ├── 2024-09-08-19-39-27.png │ │ │ │ │ ├── 2024-09-08-19-51-48.png │ │ │ │ │ ├── 2024-09-08-19-56-56.png │ │ │ │ │ ├── 2024-09-08-19-57-35.png │ │ │ │ │ └── index.md │ │ │ │ └── ses │ │ │ │ │ ├── 2024-09-03-06-20-55.png │ │ │ │ │ ├── 2024-09-03-07-00-59.png │ │ │ │ │ ├── 2024-09-08-20-29-10.png │ │ │ │ │ ├── 2024-09-08-20-30-52.png │ │ │ │ │ ├── 2024-09-08-20-33-41.png │ │ │ │ │ ├── 2024-09-08-22-28-33.png │ │ │ │ │ ├── 2024-09-08-22-32-26.png │ │ │ │ │ ├── 2024-09-08-22-33-32.png │ │ │ │ │ ├── 2024-09-08-22-35-46.png │ │ │ │ │ ├── 2024-09-08-22-38-12.png │ │ │ │ │ ├── 2024-09-08-22-38-51.png │ │ │ │ │ ├── 2024-09-08-22-41-08.png │ │ │ │ │ ├── 2024-09-08-22-42-35.png │ │ │ │ │ ├── 2024-09-08-22-45-05.png │ │ │ │ │ ├── 2024-09-08-22-48-53.png │ │ │ │ │ ├── 2024-09-08-22-53-02.png │ │ │ │ │ └── index.md │ │ │ │ ├── starter-kits.md │ │ │ │ ├── static-content.md │ │ │ │ ├── structure.md │ │ │ │ ├── toc.md │ │ │ │ ├── upgrading.md │ │ │ │ └── vscode.md │ │ ├── (splash) │ │ │ ├── +layout.ejs │ │ │ ├── +load.js │ │ │ └── index.ejs │ │ ├── +config.js │ │ ├── +layout.ejs │ │ ├── _private │ │ │ ├── browser.ejs │ │ │ ├── npm.ejs │ │ │ ├── quickstart.ejs │ │ │ └── version.ejs │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── assets │ │ │ ├── app.css │ │ │ ├── app.tailwind.css │ │ │ ├── prism.css │ │ │ └── prism.js │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── otp.pb.js │ │ └── site.webmanifest │ └── pocketpages.pb.js ├── postcss.config.js └── tailwind.config.js └── starters ├── .gitignore ├── auth ├── CHANGELOG.md ├── README.md ├── package.json ├── pb_hooks │ ├── pages │ │ ├── +config.js │ │ ├── +layout.ejs │ │ ├── account │ │ │ ├── +middleware.js │ │ │ ├── change-email │ │ │ │ └── index.ejs │ │ │ └── index.ejs │ │ ├── auth │ │ │ ├── confirm │ │ │ │ └── [token] │ │ │ │ │ ├── email-change.ejs │ │ │ │ │ ├── password-reset.ejs │ │ │ │ │ └── verification.ejs │ │ │ ├── forgot │ │ │ │ └── index.ejs │ │ │ ├── login │ │ │ │ ├── _private │ │ │ │ │ ├── anonymous.ejs │ │ │ │ │ ├── mfa.ejs │ │ │ │ │ ├── oauth2.ejs │ │ │ │ │ ├── otp.ejs │ │ │ │ │ └── password.ejs │ │ │ │ ├── index.ejs │ │ │ │ └── otp.ejs │ │ │ ├── logout │ │ │ │ └── index.ejs │ │ │ ├── oauth │ │ │ │ ├── confirm.ejs │ │ │ │ └── login.ejs │ │ │ └── register │ │ │ │ └── index.ejs │ │ └── index.ejs │ └── pocketpages.pb.js └── pb_migrations │ ├── 1738509036_init.js │ ├── 1738527865_updated_users.js │ ├── 1738527881_updated_users.js │ ├── 1738527895_updated_users.js │ ├── 1738530766_updated_users.js │ └── 1738981268_updated_users.js ├── daisyui-docs ├── CHANGELOG.md ├── README.md ├── package.json ├── pb_hooks │ ├── pages │ │ ├── (main) │ │ │ ├── +layout.ejs │ │ │ └── docs │ │ │ │ ├── +layout.ejs │ │ │ │ ├── _private │ │ │ │ └── toc.md │ │ │ │ └── overview.md │ │ ├── (splash) │ │ │ ├── +layout.ejs │ │ │ └── index.ejs │ │ ├── +config.js │ │ ├── +layout.ejs │ │ └── assets │ │ │ ├── app.css │ │ │ └── app.tailwind.css │ └── pocketpages.pb.js └── tailwind.config.js ├── daisyui ├── CHANGELOG.md ├── README.md ├── package.json ├── pb_hooks │ ├── pages │ │ ├── +layout.ejs │ │ ├── app.css │ │ ├── app.tailwind.css │ │ └── index.ejs │ └── pocketpages.pb.js └── tailwind.config.js ├── deploy-fly-ga └── .github │ └── workflows │ └── fly-deploy.yml ├── deploy-fly-manual ├── .dockerignore ├── Dockerfile └── fly.toml ├── deploy-pockethost-ga └── .github │ └── workflows │ └── deploy-pockethost.yaml ├── deploy-pockethost-manual ├── .env-deploy-pockethost └── deploy-pockethost.ts ├── htmx ├── CHANGELOG.md ├── README.md ├── package.json └── pb_hooks │ ├── pages │ ├── (site) │ │ ├── +layout.ejs │ │ └── index.ejs │ ├── +config.js │ ├── _private │ │ └── count.ejs │ └── api │ │ ├── chat.ejs │ │ └── count.ejs │ └── pocketpages.pb.js ├── minimal ├── CHANGELOG.md ├── README.md ├── package.json └── pb_hooks │ ├── pages │ └── index.ejs │ └── pocketpages.pb.js └── mvp ├── CHANGELOG.md ├── README.md ├── package.json └── pb_hooks ├── pages └── index.ejs └── pocketpages.pb.js /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["pocketpages-starter-*", "pocketpages-site"] 11 | } 12 | -------------------------------------------------------------------------------- /.cursorrules: -------------------------------------------------------------------------------- 1 | # PocketPages 2 | 3 | This project uses the PocketBase JSVM. In code samples, nothing is awaitable and we do not use the PocketBase JS SDK at all. All demo code should use the PocketBase JSVM API. 4 | 5 | # Code sample syntax 6 | 7 | - Escape the EJS start tag `<%` by using `<%%` 8 | - Use `<%%=` for variable interpolation. 9 | - Use `<%%` for control flow like `if` statements. 10 | 11 | # Documentation Style 12 | 13 | - Do not include summary sections 14 | - Focus on slim clients and an ethos of pure html/js rather than reactive programming 15 | - Assume modern browsers and features. 16 | - Assume JavaScript is enabled. 17 | 18 | # Programming Style 19 | 20 | - Prefer factory functions that return an API object instead of classes 21 | - Prefer early returns 22 | 23 | # Generating Markdown 24 | 25 | - When proposing an edit to a markdown file, first decide if there will be code snippets in the markdown file. 26 | - If there are no code snippets, wrap the beginning and end of your answer in backticks and markdown as the language. 27 | - If there are code snippets, indent the code snippets with two spaces and the correct language for proper rendering. Indentations level 0 and 4 is not allowed. 28 | - If a markdown code block is indented with any value other than 2 spaces, automatically fix it 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | *.tgz 4 | pb_data 5 | !docs/pb_hooks 6 | .env 7 | docs/.cache 8 | .secrets 9 | .ftp-deploy-sync-state.json 10 | package-lock.json 11 | bun.lockb 12 | dist 13 | tmp 14 | dist 15 | .vscode 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PocketPages 2 | 3 | > **_Really fast Server Side pages for PocketBase_** 4 | 5 | PocketPages is a lightweight EJS and router engine that runs as a PocketBase JS hook. It's super fast and can render pages <40ms. 6 | 7 | Write your web apps like old-school PHP: 8 | 9 | ```ejs 10 | // pb_hooks/pages/index.ejs 11 | <%= `Hello, world!` %> 12 | ``` 13 | 14 | ### >>> [Official docs](https://pocketpages.dev/docs) <<< 15 | 16 | ## Why did I make this? 17 | 18 | - Because when I have a new app idea, I want to make contact with the real world as soon as possible 19 | - Because I want to start simply and grow as needed, in any direction I decide 20 | - Because I want a unified SEO-friendly platform without needing to worry about SSR/SSG/SPA 21 | - Because I miss the good parts of PHP 22 | - Because I think pure client-side reactive frameworks like AlpineJS and HTMLx are a perfect compliment to Server Side pages. 23 | - Send a PR to add your reasons here :) 24 | 25 | ## Contributing 26 | 27 | PR's are welcome. 28 | 29 | - Docs 30 | - Core features 31 | - Starter kits 32 | - Showcases 33 | -------------------------------------------------------------------------------- /freshen-branches.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get all branches that start with 'feat/' and store them in an array 4 | branches=($(git branch --list 'chore/*' 'feat/*' 'fix/*' 'enh/*' 'test/*' 'next'| sed 's/ //')) 5 | 6 | # Loop through each 'feat/' branch 7 | for branch in "${branches[@]}"; do 8 | echo "Processing branch: $branch" 9 | 10 | # Checkout the 'feat/' branch 11 | git checkout "$branch" 12 | 13 | # Merge 'main' into the 'feat/' branch 14 | echo "Merging 'main' into '$branch'..." 15 | git merge main 16 | 17 | # Check if there are merge conflicts 18 | if [ $? -ne 0 ]; then 19 | echo "Merge conflict detected in '$branch'. Resolve the conflict and then press Enter to continue..." 20 | read -p "" 21 | fi 22 | done 23 | 24 | # Checkout master branch or the initial branch after completing the merges 25 | git checkout main 26 | 27 | echo "All branches have been processed." 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-monorepo", 3 | "private": true, 4 | "devDependencies": { 5 | "@changesets/cli": "^2.28.0", 6 | "concurrently": "^9.1.2", 7 | "prettier": "^3.5.1", 8 | "prettier-plugin-organize-imports": "^4.1.0", 9 | "typescript": "^5.7.3" 10 | }, 11 | "scripts": { 12 | "dev": "concurrently 'bun run dev:*'", 13 | "dev:pocketpages": "cd packages/pocketpages && bun run dev", 14 | "dev:plugins:auth": "cd packages/plugins/auth && bun run dev", 15 | "dev:plugins:ejs": "cd packages/plugins/ejs && bun run dev", 16 | "dev:plugins:js-sdk": "cd packages/plugins/js-sdk && bun run dev", 17 | "dev:plugins:marked": "cd packages/plugins/marked && bun run dev", 18 | "dev:plugins:micro-dash": "cd packages/plugins/micro-dash && bun run dev", 19 | "dev:plugins:sse": "cd packages/plugins/sse && bun run dev", 20 | "build": "concurrently 'bun run build:*'", 21 | "build:pocketpages": "cd packages/pocketpages && bun run build", 22 | "build:plugins:auth": "cd packages/plugins/auth && bun run build", 23 | "build:plugins:ejs": "cd packages/plugins/ejs && bun run build", 24 | "build:plugins:js-sdk": "cd packages/plugins/js-sdk && bun run build", 25 | "build:plugins:marked": "cd packages/plugins/marked && bun run build", 26 | "build:plugins:micro-dash": "cd packages/plugins/micro-dash && bun run build", 27 | "build:plugins:sse": "cd packages/plugins/sse && bun run build", 28 | "publish": "bun run build && concurrently 'bun run publish:*'", 29 | "publish:pocketpages": "cd packages/pocketpages && bun publish", 30 | "publish:plugins:auth": "cd packages/plugins/auth && bun publish", 31 | "publish:plugins:ejs": "cd packages/plugins/ejs && bun publish", 32 | "publish:plugins:js-sdk": "cd packages/plugins/js-sdk && bun publish", 33 | "publish:plugins:marked": "cd packages/plugins/marked && bun publish", 34 | "publish:plugins:micro-dash": "cd packages/plugins/micro-dash && bun publish", 35 | "publish:plugins:sse": "cd packages/plugins/sse && bun publish" 36 | }, 37 | "prettier": { 38 | "singleQuote": true, 39 | "trailingComma": "es5", 40 | "semi": false, 41 | "plugins": [ 42 | "prettier-plugin-organize-imports" 43 | ] 44 | }, 45 | "workspaces": [ 46 | "packages/*", 47 | "packages/plugins/*", 48 | "packages/starters/*" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /packages/plugins/auth/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-plugin-auth 2 | 3 | ## 0.2.0 4 | 5 | ### Minor Changes 6 | 7 | - 8fef39f: Plugins now require a `name` field 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [8fef39f] 12 | - pocketpages-plugin-js-sdk@0.1.0 13 | 14 | ## 0.1.1 15 | 16 | ### Patch Changes 17 | 18 | - df9995a: Fix: make js-sdk a required dep 19 | 20 | ## 0.1.0 21 | 22 | ### Minor Changes 23 | 24 | - 4286e4f: Renamed signInWithToken to signIn and fixed cookie writing bug 25 | 26 | ### Patch Changes 27 | 28 | - Updated dependencies [d80bbb2] 29 | - pocketpages-plugin-js-sdk@0.0.9 30 | 31 | ## 0.0.8 32 | 33 | ### Patch Changes 34 | 35 | - Fix: build 36 | - Updated dependencies 37 | - pocketpages-plugin-js-sdk@0.0.8 38 | 39 | ## 0.0.7 40 | 41 | ### Patch Changes 42 | 43 | - 79dc05d: Fix: update pocketbase-js-sdk-jsvm 44 | - Updated dependencies [79dc05d] 45 | - pocketpages-plugin-js-sdk@0.0.7 46 | 47 | ## 0.0.6 48 | 49 | ### Patch Changes 50 | 51 | - Fix: bad build 52 | - Updated dependencies 53 | - pocketpages-plugin-js-sdk@0.0.6 54 | 55 | ## 0.0.5 56 | 57 | ### Patch Changes 58 | 59 | - a612d93: Fix: renamed global plugin config context to globalApi 60 | - Updated dependencies [a612d93] 61 | - pocketpages-plugin-js-sdk@0.0.5 62 | 63 | ## 0.0.4 64 | 65 | ### Patch Changes 66 | 67 | - Removed workspace protocol from dependencies 68 | - Updated dependencies 69 | - pocketpages-plugin-js-sdk@0.0.4 70 | 71 | ## 0.0.3 72 | 73 | - Initial release 74 | -------------------------------------------------------------------------------- /packages/plugins/auth/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages Auth Plugin 2 | 3 | A comprehensive authentication plugin for PocketPages that provides user management, authentication flows, and session handling. 4 | 5 | Official documentation: https://pocketpages.dev/docs/plugins/auth 6 | -------------------------------------------------------------------------------- /packages/plugins/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-plugin-auth", 3 | "version": "0.2.0", 4 | "description": "", 5 | "main": "dist/index.cjs", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsup", 9 | "dev": "chokidar 'src/**/*' -c 'bun run build'" 10 | }, 11 | "dependencies": { 12 | "pocketpages-plugin-js-sdk": "workspace:^0.1.0" 13 | }, 14 | "devDependencies": { 15 | "@changesets/cli": "^2.27.12", 16 | "chokidar-cli": "^3.0.0", 17 | "pocketbase-js-sdk-jsvm": "^0.25.10004", 18 | "pocketbase-jsvm": "^0.25.10001", 19 | "tsup": "^8.3.6", 20 | "typescript": "^5.7.3" 21 | }, 22 | "files": [ 23 | "dist", 24 | "*.md" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /packages/plugins/auth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "CommonJS", 5 | "types": ["pocketbase-jsvm"] 6 | }, 7 | "include": ["src/**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/plugins/auth/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | outExtension: ({ format }) => { 9 | return { 10 | js: format === 'cjs' ? '.cjs' : '.js', 11 | } 12 | }, 13 | dts: { 14 | resolve: true, 15 | compilerOptions: { 16 | module: 'ESNext', 17 | moduleResolution: 'bundler', 18 | skipLibCheck: false, 19 | types: ['pocketbase-jsvm'], 20 | }, 21 | banner: '/// ', 22 | }, 23 | clean: false, 24 | outDir: 'dist', 25 | shims: true, 26 | skipNodeModulesBundle: false, 27 | target: 'node20', 28 | platform: 'node', 29 | minify: false, 30 | sourcemap: false, 31 | splitting: false, 32 | bundle: true, 33 | banner: { 34 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 35 | }, 36 | }) 37 | -------------------------------------------------------------------------------- /packages/plugins/ejs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-plugin-ejs 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 8fef39f: Plugins now require a `name` field 8 | 9 | ### Patch Changes 10 | 11 | - 8fef39f: Fix: Includefile double render 12 | 13 | ## 0.0.7 14 | 15 | ### Patch Changes 16 | 17 | - 06b9fed: Fix: include(file,data) now works properly 18 | 19 | ## 0.0.6 20 | 21 | ### Patch Changes 22 | 23 | - b1c4f31: Fix: corrected build name and main source name 24 | - 3712c73: Enh: include() with omitted extensions will search extensions[] 25 | 26 | ## 0.0.5 27 | 28 | ### Patch Changes 29 | 30 | - Fix: bad build 31 | 32 | ## 0.0.4 33 | 34 | ### Patch Changes 35 | 36 | - Removed workspace protocol from dependencies 37 | 38 | ## 0.0.3 39 | 40 | - Initial release 41 | -------------------------------------------------------------------------------- /packages/plugins/ejs/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages EJS Plugin 2 | 3 | A comprehensive EJS plugin for PocketPages that provides server-side rendering, partial resolution, and smart partials. 4 | 5 | Official documentation: https://pocketpages.dev/docs/plugins/ejs 6 | -------------------------------------------------------------------------------- /packages/plugins/ejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-plugin-ejs", 3 | "version": "0.1.0", 4 | "description": "EJS plugin for PocketPages", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsup", 9 | "dev": "bun run build && chokidar 'src/**/*' -c 'bun run build'" 10 | }, 11 | "dependencies": { 12 | "pocketbase-ejs": "^3.1.10006", 13 | "pocketbase-node": "^0.0.3", 14 | "pocketbase-stringify": "^0.0.2" 15 | }, 16 | "devDependencies": { 17 | "pocketpages": "workspace:^0.16.0", 18 | "@s-libs/micro-dash": "^18.0.0", 19 | "chokidar-cli": "^3.0.0", 20 | "tsup": "^8.3.6", 21 | "typescript": "^5.7.3" 22 | }, 23 | "files": [ 24 | "dist", 25 | "*.md" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/plugins/ejs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["pocketbase-jsvm"], 4 | "strict": true, 5 | "strictNullChecks": true, 6 | "noUncheckedIndexedAccess": true, 7 | "noImplicitAny": true, 8 | "target": "ES6", 9 | "module": "CommonJS", 10 | "moduleResolution": "node", 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true 13 | }, 14 | "include": ["src/**/*"] 15 | } 16 | -------------------------------------------------------------------------------- /packages/plugins/ejs/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | dts: { 9 | resolve: true, 10 | compilerOptions: { 11 | module: 'ES6', 12 | moduleResolution: 'bundler', 13 | skipLibCheck: false, 14 | types: ['pocketbase-jsvm'], 15 | }, 16 | banner: '/// ', 17 | }, 18 | clean: false, 19 | outDir: 'dist', 20 | shims: true, 21 | skipNodeModulesBundle: false, 22 | target: 'node20', 23 | platform: 'node', 24 | minify: false, 25 | sourcemap: false, 26 | splitting: false, 27 | bundle: true, 28 | banner: { 29 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 30 | }, 31 | external: ['pocketpages', 'marked'], 32 | noExternal: ['@s-libs/micro-dash'], 33 | }) 34 | -------------------------------------------------------------------------------- /packages/plugins/js-sdk/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-plugin-js-sdk 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 8fef39f: Plugins now require a `name` field 8 | 9 | ## 0.0.9 10 | 11 | ### Patch Changes 12 | 13 | - d80bbb2: Enh: added options and caching to maintain multiple client objects with different auth 14 | 15 | ## 0.0.8 16 | 17 | ### Patch Changes 18 | 19 | - Fix: build 20 | 21 | ## 0.0.7 22 | 23 | ### Patch Changes 24 | 25 | - 79dc05d: Fix: update pocketbase-js-sdk-jsvm 26 | 27 | ## 0.0.6 28 | 29 | ### Patch Changes 30 | 31 | - Fix: bad build 32 | 33 | ## 0.0.5 34 | 35 | ### Patch Changes 36 | 37 | - a612d93: Fix: renamed global plugin config context to globalApi 38 | 39 | ## 0.0.4 40 | 41 | ### Patch Changes 42 | 43 | - Removed workspace protocol from dependencies 44 | 45 | ## 0.0.3 46 | 47 | - Initial release 48 | -------------------------------------------------------------------------------- /packages/plugins/js-sdk/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages Server-Side JS SDK Plugin 2 | 3 | A comprehensive server-side JS SDK plugin for PocketPages that provides a JS SDK for PocketBase. 4 | 5 | Official documentation: https://pocketpages.dev/docs/plugins/js-sdk 6 | -------------------------------------------------------------------------------- /packages/plugins/js-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-plugin-js-sdk", 3 | "version": "0.1.0", 4 | "description": "PocketBase JS SDK for JSVM", 5 | "main": "dist/index.cjs", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsup", 9 | "dev": "bun run build && chokidar 'src/**/*' -c 'bun run build'" 10 | }, 11 | "devDependencies": { 12 | "@changesets/cli": "^2.27.12", 13 | "chokidar-cli": "^3.0.0", 14 | "pocketbase-jsvm": "^0.25.10001", 15 | "tsup": "^8.3.6", 16 | "typescript": "^5.7.3", 17 | "pocketpages": "workspace:^0.16.0" 18 | }, 19 | "dependencies": { 20 | "pocketbase-js-sdk-jsvm": "^0.25.10004" 21 | }, 22 | "files": [ 23 | "dist", 24 | "*.md" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /packages/plugins/js-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import PocketBase from 'pocketbase-js-sdk-jsvm' 2 | import { PagesRequest, PluginFactory, PluginOptionsBase } from 'pocketpages' 3 | 4 | export type JSSdkPluginOptions = PluginOptionsBase & { 5 | host: string 6 | } 7 | 8 | export type PocketBaseClientOptions = { 9 | auth?: core.Record 10 | host: string 11 | request?: PagesRequest 12 | } 13 | 14 | const jsSdkPluginFactory: PluginFactory = ( 15 | config, 16 | extra 17 | ) => { 18 | const { globalApi } = config 19 | const { dbg } = globalApi 20 | 21 | const newClient = (host: string, auth?: core.Record) => { 22 | const pb = new PocketBase(host) 23 | if (auth) { 24 | dbg(`auth`, typeof auth, auth) 25 | const token = auth.newAuthToken() 26 | pb.authStore.save(token, JSON.parse(JSON.stringify(auth))) 27 | dbg( 28 | `created new PocketBase client for ${host} with saved auth: ${auth.id} ${token}` 29 | ) 30 | } else { 31 | dbg(`created new PocketBase client for ${host}`) 32 | } 33 | return pb 34 | } 35 | 36 | const pbCache = new Map() 37 | 38 | globalApi.pb = (options?: Partial) => { 39 | const host = options?.host ?? extra?.host ?? `http://localhost:8090` 40 | const auth = options?.auth ?? options?.request?.auth 41 | const key = `${host}-${auth?.id}` 42 | if (pbCache.has(key)) { 43 | return pbCache.get(key) 44 | } 45 | dbg(`creating new pb client for ${key}`) 46 | const pb = newClient(host, auth) 47 | pbCache.set(key, pb) 48 | return pb 49 | } 50 | 51 | return { 52 | name: 'js-sdk', 53 | } 54 | } 55 | 56 | export default jsSdkPluginFactory 57 | -------------------------------------------------------------------------------- /packages/plugins/js-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "CommonJS", 5 | "types": ["pocketbase-jsvm"] 6 | }, 7 | "include": ["src/**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/plugins/js-sdk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | outExtension: ({ format }) => { 9 | return { 10 | js: format === 'cjs' ? '.cjs' : '.js', 11 | } 12 | }, 13 | dts: { 14 | resolve: true, 15 | compilerOptions: { 16 | module: 'ESNext', 17 | moduleResolution: 'bundler', 18 | skipLibCheck: false, 19 | types: ['pocketbase-jsvm'], 20 | }, 21 | banner: '/// ', 22 | }, 23 | clean: false, 24 | outDir: 'dist', 25 | shims: true, 26 | skipNodeModulesBundle: false, 27 | target: 'node20', 28 | platform: 'node', 29 | minify: false, 30 | sourcemap: false, 31 | splitting: false, 32 | bundle: true, 33 | banner: { 34 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 35 | }, 36 | }) 37 | -------------------------------------------------------------------------------- /packages/plugins/marked/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-plugin-marked 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 8fef39f: Plugins now require a `name` field 8 | 9 | ## 0.0.5 10 | 11 | ### Patch Changes 12 | 13 | - Fix: bad build 14 | 15 | ## 0.0.4 16 | 17 | ### Patch Changes 18 | 19 | - Removed workspace protocol from dependencies 20 | 21 | ## 0.0.3 22 | 23 | - Initial release 24 | -------------------------------------------------------------------------------- /packages/plugins/marked/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages Markdown Plugin 2 | 3 | A comprehensive Markdown plugin for PocketPages. 4 | 5 | Official documentation: https://pocketpages.dev/docs/plugins/markdown 6 | -------------------------------------------------------------------------------- /packages/plugins/marked/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-plugin-marked", 3 | "version": "0.1.0", 4 | "main": "dist/index.cjs", 5 | "types": "dist/index.d.ts", 6 | "scripts": { 7 | "build": "tsup", 8 | "dev": "bun run build && chokidar 'src/**/*' -c 'bun run build'" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "description": "", 13 | "dependencies": { 14 | "marked": "^15.0.7", 15 | "remark-frontmatter": "^5.0.0", 16 | "remark-frontmatter-yaml": "^1.3.0", 17 | "remark-parse": "^11.0.0", 18 | "remark-stringify": "^11.0.0", 19 | "unified": "^11.0.5", 20 | "front-matter": "^4.0.2" 21 | }, 22 | "devDependencies": { 23 | "@s-libs/micro-dash": "^18.0.0", 24 | "chokidar-cli": "^3.0.0", 25 | "pocketpages": "workspace:^0.16.0", 26 | "tsup": "^8.3.6", 27 | "typescript": "^5.7.3" 28 | }, 29 | "files": [ 30 | "dist", 31 | "*.md" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /packages/plugins/marked/src/index.ts: -------------------------------------------------------------------------------- 1 | import { forEach } from '@s-libs/micro-dash' 2 | import fm, { FrontMatterResult } from 'front-matter' 3 | import { Marked } from 'marked' 4 | import { PluginFactory, PluginOptionsBase } from 'pocketpages' 5 | 6 | export type FrontMatter = Record 7 | 8 | export type MarkedPluginOptions = PluginOptionsBase & { 9 | extensions: string[] 10 | } 11 | 12 | const markedPluginFactory: PluginFactory = ( 13 | config, 14 | extra 15 | ) => { 16 | const { dbg } = config 17 | 18 | const opts: MarkedPluginOptions = { 19 | extensions: ['.md'], 20 | ...extra, 21 | } 22 | 23 | const _handles = (filePath: string) => { 24 | return opts.extensions.includes($filepath.ext(filePath)) 25 | } 26 | 27 | return { 28 | name: 'marked', 29 | handles: ({ filePath }) => { 30 | return _handles(filePath) 31 | }, 32 | onRender: ({ content, api, filePath }) => { 33 | if (!_handles(filePath)) return content 34 | dbg(`marked onRender`, { filePath }) 35 | 36 | var frontmatter: FrontMatterResult | null = null 37 | 38 | function preprocess(markdown: string) { 39 | frontmatter = fm(markdown) 40 | dbg(`frontmatter`, frontmatter) 41 | return frontmatter.body 42 | } 43 | 44 | const marked = new Marked({ 45 | hooks: { preprocess }, 46 | renderer: { 47 | heading({ tokens, depth }) { 48 | const id = tokens[0]?.raw 49 | .toLowerCase() // Convert to lowercase 50 | .trim() // Remove leading/trailing spaces 51 | .replace(/[^a-z0-9\-_ ]/g, '') // Remove invalid characters 52 | .replace(/\s+/g, '-') // Replace spaces with hyphens 53 | .replace(/^-+|-+$/g, '') // Remove leading/trailing hyphens 54 | // dbg({ tokens, depth, id }) 55 | return `${this.parser.parseInline( 56 | tokens 57 | )}\n` 58 | }, 59 | image({ href, title, text }) { 60 | return `${text}` 61 | }, 62 | }, 63 | }) 64 | 65 | const html = marked.parse(content) as string 66 | 67 | forEach( 68 | (frontmatter as FrontMatterResult | null)?.attributes ?? 69 | {}, 70 | (value, key) => { 71 | api.meta(key, value) 72 | } 73 | ) 74 | dbg(`markdown`, { html }) 75 | return html 76 | }, 77 | } 78 | } 79 | 80 | export default markedPluginFactory 81 | -------------------------------------------------------------------------------- /packages/plugins/marked/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["pocketbase-jsvm"], 4 | "strict": true, 5 | "strictNullChecks": true, 6 | "noUncheckedIndexedAccess": true, 7 | "noImplicitAny": true, 8 | "target": "ES6", 9 | "module": "CommonJS", 10 | "moduleResolution": "node", 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true, 13 | "baseUrl": ".", 14 | "paths": { 15 | "$util/*": ["src/lib/util/*"] 16 | } 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /packages/plugins/marked/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | outExtension: ({ format }) => { 9 | return { 10 | js: format === 'cjs' ? '.cjs' : '.js', 11 | } 12 | }, 13 | dts: { 14 | resolve: true, 15 | compilerOptions: { 16 | module: 'ESNext', 17 | moduleResolution: 'bundler', 18 | skipLibCheck: false, 19 | types: ['pocketbase-jsvm'], 20 | }, 21 | banner: '/// ', 22 | }, 23 | clean: false, 24 | outDir: 'dist', 25 | shims: true, 26 | skipNodeModulesBundle: false, 27 | target: 'node20', 28 | platform: 'node', 29 | minify: false, 30 | sourcemap: false, 31 | splitting: false, 32 | bundle: true, 33 | banner: { 34 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 35 | }, 36 | }) 37 | -------------------------------------------------------------------------------- /packages/plugins/micro-dash/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-plugin-micro-dash 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 8fef39f: Plugins now require a `name` field 8 | 9 | ## 0.0.6 10 | 11 | ### Patch Changes 12 | 13 | - Fix: bad build 14 | 15 | ## 0.0.5 16 | 17 | ### Patch Changes 18 | 19 | - a612d93: Fix: renamed global plugin config context to globalApi 20 | 21 | ## 0.0.4 22 | 23 | ### Patch Changes 24 | 25 | - Removed workspace protocol from dependencies 26 | 27 | ## 0.0.3 28 | 29 | - Initial release 30 | -------------------------------------------------------------------------------- /packages/plugins/micro-dash/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages Micro Dash Plugin 2 | 3 | A comprehensive Micro Dash plugin for PocketPages that provides a micro-dash for PocketPages. 4 | 5 | Official documentation: https://pocketpages.dev/docs/plugins/micro-dash 6 | -------------------------------------------------------------------------------- /packages/plugins/micro-dash/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-plugin-micro-dash", 3 | "version": "0.1.0", 4 | "description": "", 5 | "main": "dist/index.cjs", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsup", 9 | "dev": "bun run build && chokidar 'src/**/*' -c 'bun run build'" 10 | }, 11 | "devDependencies": { 12 | "@s-libs/micro-dash": "^18.0.0", 13 | "chokidar-cli": "^3.0.0", 14 | "tsup": "^8.3.6", 15 | "typescript": "^5.7.3", 16 | "pocketpages": "workspace:^0.16.0" 17 | }, 18 | "files": [ 19 | "dist", 20 | "*.md" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/plugins/micro-dash/src/index.ts: -------------------------------------------------------------------------------- 1 | import { forEach, keys, merge, pick, shuffle, values } from '@s-libs/micro-dash' 2 | 3 | import { PluginFactory } from '../../../pocketpages/src/lib/types' 4 | 5 | const microDashPluginFactory: PluginFactory = (config) => { 6 | const { globalApi } = config 7 | globalApi.forEach = forEach 8 | globalApi.keys = keys 9 | globalApi.values = values 10 | globalApi.merge = merge 11 | globalApi.pick = pick 12 | globalApi.shuffle = shuffle 13 | return { 14 | name: 'micro-dash', 15 | } 16 | } 17 | 18 | export default microDashPluginFactory 19 | -------------------------------------------------------------------------------- /packages/plugins/micro-dash/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "CommonJS", 5 | "types": ["pocketbase-jsvm"] 6 | }, 7 | "include": ["src/**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/plugins/micro-dash/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | outExtension: ({ format }) => { 9 | return { 10 | js: format === 'cjs' ? '.cjs' : '.js', 11 | } 12 | }, 13 | dts: { 14 | resolve: true, 15 | compilerOptions: { 16 | module: 'ESNext', 17 | moduleResolution: 'bundler', 18 | skipLibCheck: false, 19 | types: ['pocketbase-jsvm'], 20 | }, 21 | banner: '/// ', 22 | }, 23 | clean: false, 24 | outDir: 'dist', 25 | shims: true, 26 | skipNodeModulesBundle: false, 27 | target: 'node20', 28 | platform: 'node', 29 | minify: false, 30 | sourcemap: false, 31 | splitting: false, 32 | bundle: true, 33 | banner: { 34 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 35 | }, 36 | noExternal: ['@s-libs/micro-dash'], 37 | }) 38 | -------------------------------------------------------------------------------- /packages/plugins/sse/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-plugin-sse 2 | 3 | ## 0.1.0 4 | 5 | ### Minor Changes 6 | 7 | - 8fef39f: Plugins now require a `name` field 8 | 9 | ## 0.0.5 10 | 11 | ### Patch Changes 12 | 13 | - Fix: bad build 14 | 15 | ## 0.0.4 16 | 17 | ### Patch Changes 18 | 19 | - Removed workspace protocol from dependencies 20 | 21 | ## 0.0.3 22 | 23 | - Initial release 24 | -------------------------------------------------------------------------------- /packages/plugins/sse/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages Realtime SSE Plugin 2 | 3 | A comprehensive Realtime SSE plugin for PocketPages that provides realtime SSE for PocketPages. 4 | 5 | Official documentation: https://pocketpages.dev/docs/plugins/sse 6 | -------------------------------------------------------------------------------- /packages/plugins/sse/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-plugin-sse", 3 | "version": "0.1.0", 4 | "description": "SSE plugin for PocketPages", 5 | "main": "dist/index.cjs", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsup", 9 | "dev": "bun run build && chokidar 'src/**/*' -c 'bun run build'" 10 | }, 11 | "devDependencies": { 12 | "chokidar-cli": "^3.0.0", 13 | "pocketbase-jsvm": "^0.25.10001", 14 | "tsup": "^8.3.6", 15 | "typescript": "^5.7.3", 16 | "pocketpages": "workspace:^0.16.0" 17 | }, 18 | "files": [ 19 | "dist", 20 | "*.md" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/plugins/sse/src/index.ts: -------------------------------------------------------------------------------- 1 | import { PluginFactory } from 'pocketpages' 2 | 3 | export type SseFilter = (clientId: string, client: any) => boolean 4 | 5 | const _sseSend = (name: string, data: string, filter: SseFilter) => { 6 | const payload = new SubscriptionMessage({ 7 | name, 8 | data, 9 | }) 10 | 11 | const clients = $app.subscriptionsBroker().clients() 12 | 13 | const filteredClients = Object.entries(clients).filter( 14 | ([clientId, client]) => 15 | client.hasSubscription(name) && filter(clientId, client) 16 | ) 17 | 18 | filteredClients.forEach(([clientId, client]) => { 19 | client.send(payload) 20 | }) 21 | } 22 | 23 | const ssePluginFactory: PluginFactory = (config) => { 24 | const { dbg } = config 25 | 26 | const deferredSse: { 27 | topic: string 28 | filter: SseFilter 29 | } = { 30 | topic: '', 31 | filter: () => false, //Noop 32 | } 33 | 34 | return { 35 | name: 'sse', 36 | onExtendContextApi: ({ api }) => { 37 | const DefaultSseFilter: SseFilter = (clientId: string, client: any) => { 38 | return api.auth?.id ? client.get('auth')?.id === api.auth?.id : true 39 | } 40 | 41 | // Function overloads for sseSend 42 | function sseSend(topic: string, message: string, filter?: SseFilter): void 43 | function sseSend(topic: string, filter?: SseFilter): void 44 | function sseSend( 45 | topic: string, 46 | messageOrFilter: string | SseFilter = DefaultSseFilter, 47 | filter: SseFilter = DefaultSseFilter 48 | ): void { 49 | const isDeferred = typeof messageOrFilter === 'function' 50 | if (isDeferred) { 51 | deferredSse.topic = topic 52 | deferredSse.filter = messageOrFilter as SseFilter 53 | dbg('Deferred SSE', { deferredSse }) 54 | return 55 | } 56 | return _sseSend(topic, messageOrFilter as string, filter) 57 | } 58 | 59 | api.sseSend = sseSend 60 | }, 61 | onResponse: ({ api, content }) => { 62 | const { stringify, response } = api 63 | dbg('Deferred SSE', { deferredSse }) 64 | 65 | if (!deferredSse.topic) return false 66 | 67 | _sseSend(deferredSse.topic, stringify(content), deferredSse.filter) 68 | response.json(200, { sse: 'ok' }) 69 | return true 70 | }, 71 | } 72 | } 73 | 74 | export default ssePluginFactory 75 | -------------------------------------------------------------------------------- /packages/plugins/sse/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "CommonJS", 5 | "types": ["pocketbase-jsvm"] 6 | }, 7 | "include": ["src/**/*.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/plugins/sse/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | outExtension: ({ format }) => { 9 | return { 10 | js: format === 'cjs' ? '.cjs' : '.js', 11 | } 12 | }, 13 | dts: { 14 | resolve: true, 15 | compilerOptions: { 16 | module: 'ESNext', 17 | moduleResolution: 'bundler', 18 | skipLibCheck: false, 19 | types: ['pocketbase-jsvm'], 20 | }, 21 | banner: '/// ', 22 | }, 23 | clean: false, 24 | outDir: 'dist', 25 | shims: true, 26 | skipNodeModulesBundle: false, 27 | target: 'node20', 28 | platform: 'node', 29 | minify: false, 30 | sourcemap: false, 31 | splitting: false, 32 | bundle: true, 33 | banner: { 34 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 35 | }, 36 | }) 37 | -------------------------------------------------------------------------------- /packages/pocketpages/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages 2 | 3 | > **_Really fast Server Side pages for PocketBase_** 4 | 5 | PocketPages is a lightweight EJS and router engine that runs as a PocketBase JS hook. It's super fast and can render pages <40ms. 6 | 7 | Write your web apps like old-school PHP: 8 | 9 | ```ejs 10 | // pb_hooks/pages/index.ejs 11 | <%= `Hello, world!` %> 12 | ``` 13 | 14 | ### >>> [Official docs](https://pocketpages.dev/docs) <<< 15 | 16 | ## Why did I make this? 17 | 18 | - Because when I have a new app idea, I want to make contact with the real world as soon as possible 19 | - Because I want to start simply and grow as needed, in any direction I decide 20 | - Because I want a unified SEO-friendly platform without needing to worry about SSR/SSG/SPA 21 | - Because I miss the good parts of PHP 22 | - Because I think pure client-side reactive frameworks like AlpineJS and HTMLx are a perfect compliment to Server Side pages. 23 | - Send a PR to add your reasons here :) 24 | 25 | ## Contributing 26 | 27 | PR's are welcome. 28 | 29 | - Docs 30 | - Core features 31 | - Starter kits 32 | - Showcases 33 | -------------------------------------------------------------------------------- /packages/pocketpages/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages", 3 | "version": "0.18.0", 4 | "description": "Server-side JS pages for PocketBase", 5 | "author": { 6 | "name": "Ben Allfree", 7 | "github": "benallfree" 8 | }, 9 | "main": "dist/index.js", 10 | "types": "dist/index.d.ts", 11 | "license": "MIT", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/benallfree/pocketpages" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/benallfree/pocketpages/issues" 18 | }, 19 | "homepage": "https://pocketpages.dev", 20 | "files": [ 21 | "dist", 22 | "*.md" 23 | ], 24 | "scripts": { 25 | "build": "tsup", 26 | "dev": "bun run build && chokidar 'src/**/*' 'package.json' '*.js' '*.ts' -c 'bun run build'" 27 | }, 28 | "dependencies": { 29 | "@s-libs/micro-dash": "^18.0.0", 30 | "cookie": "^1.0.2", 31 | "pocketbase-log": "^0.0.2", 32 | "pocketpages-plugin-ejs": "workspace:^0.1.0", 33 | "qs-lite": "^1.0.0", 34 | "url-parse": "^1.5.10" 35 | }, 36 | "devDependencies": { 37 | "@types/url-parse": "^1.4.11", 38 | "pocketbase-jsvm": "^0.25.10001", 39 | "prettier": "^3.3.3", 40 | "prettier-plugin-organize-imports": "^4.1.0", 41 | "rimraf": "^6.0.1", 42 | "tsup": "^8.3.5" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/pocketpages/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as log from 'pocketbase-log' 2 | export { stringify } from 'pocketbase-stringify' 3 | export { AfterBootstrapHandler } from './handlers/AfterBootstrapHandler' 4 | export { MiddlewareHandler } from './handlers/MiddlewareHandler' 5 | export { globalApi } from './lib/globalApi' 6 | export { moduleExists } from './lib/helpers' 7 | export * from './lib/types' 8 | 9 | const isInHandler = typeof onBootstrap === 'undefined' 10 | 11 | if (!isInHandler) { 12 | onBootstrap((e) => { 13 | e.next() 14 | require(`pocketpages`).AfterBootstrapHandler(e) 15 | }) 16 | 17 | routerUse((e) => { 18 | require(`pocketpages`).MiddlewareHandler(e) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /packages/pocketpages/src/lib/debug.ts: -------------------------------------------------------------------------------- 1 | import * as log from 'pocketbase-log' 2 | 3 | export const dbg = (...args: any[]) => { 4 | const dbgVal = $app.store().get('__pocketpages_debug') 5 | 6 | // console.log(JSON.stringify({ dbgVal }, null, 2)) 7 | if (!dbgVal) return 8 | return log.dbg(...args) 9 | } 10 | -------------------------------------------------------------------------------- /packages/pocketpages/src/lib/fingerprint.ts: -------------------------------------------------------------------------------- 1 | export const fingerprint = (nodeName: string, fingerprint: string) => { 2 | // Split filename into base and extension 3 | const lastDotIndex = nodeName.lastIndexOf('.') 4 | if (lastDotIndex === -1) { 5 | // No extension - just append fingerprint 6 | return `${nodeName}.${fingerprint}` 7 | } 8 | 9 | const base = nodeName.slice(0, lastDotIndex) 10 | const ext = nodeName.slice(lastDotIndex) 11 | 12 | // Insert fingerprint between base and extension 13 | return `${base}.${fingerprint}${ext}` 14 | } 15 | -------------------------------------------------------------------------------- /packages/pocketpages/src/lib/globalApi.ts: -------------------------------------------------------------------------------- 1 | import * as log from 'pocketbase-log' 2 | import { stringify } from 'pocketbase-stringify' 3 | import { default as parse } from 'url-parse' 4 | import { PagesGlobalContext } from './types' 5 | 6 | export const globalApi: PagesGlobalContext = { 7 | url: (path: string) => parse(path, true), 8 | stringify, 9 | env: (key: string) => process.env[key] ?? '', 10 | store: (name: string, value?: any) => { 11 | if (value === undefined) { 12 | return $app.store().get(name) 13 | } 14 | $app.store().set(name, value) 15 | }, 16 | ...log, 17 | } 18 | -------------------------------------------------------------------------------- /packages/pocketpages/src/lib/loadPlugins.ts: -------------------------------------------------------------------------------- 1 | import { omit } from '@s-libs/micro-dash' 2 | import { error } from 'pocketbase-log' 3 | import { globalApi } from 'src/lib/globalApi' 4 | import { 5 | Cache, 6 | Plugin, 7 | PluginConfigItem, 8 | PluginConfigItemShortHand, 9 | PluginFactory, 10 | PluginFactoryConfig, 11 | PluginOptions, 12 | } from 'src/lib/types' 13 | import { dbg as systemDbg } from './debug' 14 | import { pagesRoot } from './helpers' 15 | 16 | const normalizePlugin = ( 17 | plugin: PluginConfigItemShortHand 18 | ): PluginConfigItem => { 19 | if (typeof plugin === 'string') { 20 | return { debug: false, fn: loadFactory(plugin) } 21 | } 22 | if (typeof plugin === 'function') { 23 | return { debug: false, fn: plugin } 24 | } 25 | if (typeof plugin === 'object' && 'fn' in plugin) { 26 | return { debug: false, fn: plugin.fn!, ...plugin } 27 | } 28 | if (typeof plugin === 'object' && 'name' in plugin) { 29 | return { 30 | debug: false, 31 | ...omit(plugin, 'name'), 32 | fn: loadFactory(plugin.name), 33 | } 34 | } 35 | throw new Error('Invalid plugin config') 36 | } 37 | 38 | const loadFactory = (plugin: string) => { 39 | const factory = (() => { 40 | const module = require(plugin) 41 | return (module.default ?? module) as PluginFactory 42 | })() 43 | // dbg(`factory`, { factory }) 44 | return factory 45 | } 46 | 47 | export const loadPlugins = (cache: Cache): Plugin[] => { 48 | const { config, routes } = cache 49 | 50 | return [ 51 | ...config.plugins.map((pluginConfigItem) => { 52 | const normalizedPlugin = normalizePlugin(pluginConfigItem) 53 | 54 | const extra = omit(normalizedPlugin, 'fn') as PluginOptions 55 | 56 | try { 57 | const factoryConfig: PluginFactoryConfig = { 58 | pagesRoot, 59 | config, 60 | globalApi, 61 | routes, 62 | dbg: (...args: any[]) => 63 | extra.debug 64 | ? globalApi.dbg(`[${plugin.name}]`, ...args) 65 | : systemDbg(`[${plugin.name}]`, ...args), 66 | } 67 | const plugin = normalizedPlugin.fn(factoryConfig, extra) 68 | systemDbg(`loaded plugin ${plugin.name}`) 69 | return plugin 70 | } catch (e) { 71 | error(`error loading plugin`, { plugin: pluginConfigItem, error: e }) 72 | throw e 73 | } 74 | }), 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /packages/pocketpages/src/lib/resolveRoute.ts: -------------------------------------------------------------------------------- 1 | import * as qs from 'qs-lite' 2 | import URLParse from 'url-parse' 3 | import { Route } from '../handlers/AfterBootstrapHandler' 4 | import { dbg } from './debug' 5 | import { fingerprint } from './fingerprint' 6 | import { Cache, PagesParams } from './types' 7 | 8 | export const resolveRoute = (url: URLParse, routes: Route[]) => { 9 | const { config } = $app.store().get(`pocketpages`) 10 | 11 | const urlPath = url.pathname.slice(1) 12 | // dbg(`***resolveRoute`, { url, urlPath }) 13 | const params: PagesParams = qs.parse(url.query.slice(1)) 14 | const tryFnames = [urlPath || 'index'] 15 | if (tryFnames[0] !== 'index') { 16 | tryFnames.push(`${urlPath}/index`) 17 | } 18 | // dbg({ tryFnames }) 19 | for (const maybeFname of tryFnames) { 20 | const parts = $filepath 21 | .toSlash(maybeFname) 22 | .split('/') 23 | .filter((p) => p) 24 | // dbg(`incoming parts`, parts) 25 | for (const route of routes) { 26 | // dbg(`checking route`, route) 27 | const matched = route.segments.every((segment, i) => { 28 | const { nodeName, paramName } = segment 29 | if (paramName) return true // Match any value for param route segments 30 | const part = parts[i] 31 | const matchesWithFingerprint = (() => { 32 | if (i !== route.segments.length - 1) return false 33 | if (!route.isStatic) return false 34 | const fingerprinted = fingerprint(segment.nodeName, route.fingerprint) 35 | // dbg(`fingerprint details`, { segment, fingerprinted, parts }) 36 | return fingerprinted === parts[i] 37 | })() 38 | // dbg(`match status`, { nodeName, part, matchesWithFingerprint }) 39 | return nodeName === part || matchesWithFingerprint 40 | }) 41 | if (matched) { 42 | dbg(`Matched route ${route.relativePath}`) 43 | route.segments.forEach((segment, i) => { 44 | const { paramName } = segment 45 | if (paramName) { 46 | params[paramName] = parts[i]! 47 | return true 48 | } 49 | }) 50 | return { route, params } 51 | } 52 | } 53 | } 54 | return null 55 | } 56 | -------------------------------------------------------------------------------- /packages/pocketpages/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["pocketbase-jsvm"], 4 | "strict": true, 5 | "strictNullChecks": true, 6 | "noUncheckedIndexedAccess": true, 7 | "noImplicitAny": true, 8 | "target": "ES6", 9 | "module": "CommonJS", 10 | "moduleResolution": "node", 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true, 13 | "baseUrl": ".", 14 | "paths": { 15 | "$util/*": ["src/lib/util/*"] 16 | } 17 | }, 18 | "include": ["src/**/*"] 19 | } 20 | -------------------------------------------------------------------------------- /packages/pocketpages/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/index.ts', 6 | }, 7 | format: ['cjs'], 8 | dts: { 9 | resolve: true, 10 | compilerOptions: { 11 | module: 'ESNext', 12 | moduleResolution: 'bundler', 13 | skipLibCheck: false, 14 | types: ['pocketbase-jsvm'], 15 | }, 16 | banner: '/// ', 17 | }, 18 | clean: false, 19 | outDir: 'dist', 20 | shims: true, 21 | skipNodeModulesBundle: false, 22 | target: 'node20', 23 | platform: 'node', 24 | minify: false, 25 | sourcemap: false, 26 | splitting: false, 27 | bundle: true, 28 | banner: { 29 | js: `if (typeof module === 'undefined') { module = { exports: {} } };`, 30 | }, 31 | external: ['pocketpages', /^[^tsup]$/, /pocketbase-.*/], 32 | noExternal: ['@s-libs/micro-dash'], 33 | }) 34 | -------------------------------------------------------------------------------- /packages/site/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @pocketpages/site 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-marked@0.0.2-rc.5 10 | - pocketpages-plugin-ejs@0.0.2-rc.5 11 | - pocketpages@0.14.0-rc.5 12 | 13 | ## 0.0.2-rc.4 14 | 15 | ### Patch Changes 16 | 17 | - Testing 18 | - Updated dependencies 19 | - pocketpages-plugin-marked@0.0.2-rc.4 20 | - pocketpages-plugin-ejs@0.0.2-rc.4 21 | - pocketpages@0.14.0-rc.4 22 | 23 | ## 0.0.2-rc.3 24 | 25 | ### Patch Changes 26 | 27 | - Publish testing 28 | - Updated dependencies 29 | - pocketpages-plugin-marked@0.0.2-rc.3 30 | - pocketpages-plugin-ejs@0.0.2-rc.3 31 | - pocketpages@0.14.0-rc.3 32 | 33 | ## 0.0.2-rc.2 34 | 35 | ### Patch Changes 36 | 37 | - Publish testing 38 | - Updated dependencies 39 | - pocketpages-plugin-marked@0.0.2-rc.2 40 | - pocketpages-plugin-ejs@0.0.2-rc.2 41 | - pocketpages@0.14.0-rc.2 42 | 43 | ## 0.0.2-rc.1 44 | 45 | ### Patch Changes 46 | 47 | - Publish testing 48 | - Updated dependencies 49 | - pocketpages-plugin-marked@0.0.2-rc.1 50 | - pocketpages-plugin-ejs@0.0.2-rc.1 51 | - pocketpages@0.14.0-rc.1 52 | 53 | ## 0.0.2-rc.0 54 | 55 | ### Patch Changes 56 | 57 | - Updated dependencies 58 | - pocketpages@0.14.0-rc.0 59 | - pocketpages-plugin-ejs@0.0.2-rc.0 60 | - pocketpages-plugin-marked@0.0.2-rc.0 61 | -------------------------------------------------------------------------------- /packages/site/RADME.md: -------------------------------------------------------------------------------- 1 | # PocketPages Site 2 | 3 | This is the site for PocketPages. It is built with Tailwind CSS and DaisyUI. 4 | 5 | You can use this package as a starter kit: 6 | 7 | ```bash 8 | bunx tiged benallfree/pocketpages/site . 9 | cd site 10 | pocketbase serve --dir=pb_data --dev 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/site/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages 2 | 3 | > **_Really fast Server Side pages for PocketBase_** 4 | 5 | PocketPages is a lightweight EJS and router engine that runs as a PocketBase JS hook. It's super fast and can render pages <40ms. 6 | 7 | Write your web apps like old-school PHP: 8 | 9 | ```ejs 10 | // pb_hooks/pages/index.ejs 11 | <%= `Hello, world!` %> 12 | ``` 13 | 14 | ### >>> [Official docs](https://pocketpages.dev/docs) <<< 15 | 16 | ## Why did I make this? 17 | 18 | - Because when I have a new app idea, I want to make contact with the real world as soon as possible 19 | - Because I want to start simply and grow as needed, in any direction I decide 20 | - Because I want a unified SEO-friendly platform without needing to worry about SSR/SSG/SPA 21 | - Because I miss the good parts of PHP 22 | - Because I think pure client-side reactive frameworks like AlpineJS and HTMLx are a perfect compliment to Server Side pages. 23 | - Send a PR to add your reasons here :) 24 | 25 | ## Contributing 26 | 27 | PR's are welcome. 28 | 29 | - Docs 30 | - Core features 31 | - Starter kits 32 | - Showcases 33 | -------------------------------------------------------------------------------- /packages/site/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | 5 | "types": ["pocketpages", "pocketbase-jsvm"], 6 | "moduleResolution": "node" 7 | }, 8 | "include": ["./pb_hooks/**/*.js"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/site/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/logo.png -------------------------------------------------------------------------------- /packages/site/logo.pxd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/logo.pxd -------------------------------------------------------------------------------- /packages/site/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-site", 3 | "private": true, 4 | "version": "0.0.2", 5 | "author": { 6 | "name": "Ben Allfree", 7 | "github": "benallfree" 8 | }, 9 | "homepage": "https://pocketpages.dev", 10 | "license": "MIT", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/benallfree/pocketpages/tree/main/packages/site" 14 | }, 15 | "scripts": { 16 | "dev": "tailwindcss -i ./pb_hooks/pages/assets/app.tailwind.css -o ./pb_hooks/pages/assets/app.css --watch" 17 | }, 18 | "devDependencies": { 19 | "@tailwindcss/typography": "^0.5.15", 20 | "daisyui": "^4.12.10", 21 | "postcss-import": "^16.1.0", 22 | "tailwindcss": "^3.4.11", 23 | "pocketbase-jsvm": "^0.23.10002", 24 | "prettier": "^3.3.3", 25 | "typescript": "^5.6.2" 26 | }, 27 | "dependencies": { 28 | "pocketpages": "workspace:^0.16.0", 29 | "pocketpages-plugin-marked": "workspace:^0.1.0" 30 | }, 31 | "files": [ 32 | "pb_hooks", 33 | "*.md" 34 | ], 35 | "pockethost": { 36 | "instanceName": "pocketpages" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/+layout.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 15 | <%- slots.body || slot %> 16 |
17 |
18 | 19 | 23 |
24 |
-------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/+layout.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 10 |
<%- slots.body || slot %>
11 | 12 | 13 |
14 |
15 | 20 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/_private/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | description: PocketPages is a powerful Multi Page Application (MPA) preprocessor for PocketBase with a pluggable architecture. 4 | --- 5 | 6 | # Overview 7 | 8 | PocketPages is a 23KB pluggable Multi-Page Application (MPA) preprocessor for PocketBase. It ships with an EJS template engine and uses a flexible plugin system that lets you efficiently choose additional features (including other templating engines) for your application while maintaining maximum performance. 9 | 10 | Use PocketPages to create slim and modern web apps: 11 | 12 | - Start small and iterate 13 | - SEO-first principals 14 | - No build step 15 | - Fast server-side rendering 16 | 17 | ## Hello world in just one file 18 | 19 | ```ejs 20 | // index.ejs 21 | <%%= `Hello, world!` %> 22 | ``` 23 | 24 | <%- include(`browser.ejs`, { content: `Hello, world!`}) %> 25 | 26 | With PocketPages, building apps is easy again. Inside `<%%` and `%>`, you can leverage the full power of ES6 JavaScript inside PocketBase's [JSVM](https://pocketbase.io/jsvm/index.html), which exposes all of PocketBase's built-in functions. 27 | 28 | ## Retro file-based routing 29 | 30 | PocketPages borrows inspiration from SvelteKit's [file-based routing](https://kit.svelte.dev/docs/routing) architecture, so you can do this: 31 | 32 | ```ejs 33 | // +layout.ejs 34 | 35 | 36 | <%%- slot> 37 | 38 | 39 | ``` 40 | 41 | <%- include(`browser.ejs`, { bodyTags: `style="background-color: #b5dcb5"`, content: `Hello, world!`}) %> 42 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/_private/toc.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | - [Overview of PocketPages](/docs/overview) 4 | 5 | # Getting Started 6 | 7 | - [Installation](/docs/installation) 8 | - [Starter Kits](/docs/starter-kits) 9 | - [Upgrading](/docs/upgrading) 10 | 11 | # User Guide 12 | 13 | - Basics 14 | 15 | - [Creating a Page](/docs/creating-a-page) 16 | - [Directory Structure](/docs/directory-structure) 17 | - [Routing](/docs/routing) 18 | - [Accessing Parameters](/docs/parameters) 19 | - [Loading Data](/docs/loading-data) 20 | - [JSON](/docs/json) 21 | 22 | - Templating 23 | 24 | - [Partials](/docs/partials) 25 | - [Layouts](/docs/layouts) 26 | 27 | - Security and Content 28 | 29 | - [Private files](/docs/private-files) 30 | - [Middleware](/docs/middleware) 31 | - [Asset Management](/docs/asset-management) 32 | - [Static content](/docs/static-content) 33 | - [Managing Secrets](/docs/secrets) 34 | 35 | - Configuration 36 | 37 | - [+config.js](/docs/config) 38 | - [Caching](/docs/caching) 39 | - [Debugging](/docs/debugging) 40 | - [Going Live](/docs/deploying) 41 | 42 | - Official Plugins 43 | - [Overview](/docs/plugins) 44 | - [EJS](/docs/plugins/ejs) 45 | - [Markdown](/docs/plugins/markdown) 46 | - [Realtime](/docs/plugins/realtime) 47 | - [Authentication](/docs/plugins/auth) 48 | - [JS SDK](/docs/plugins/js-sdk) 49 | - [Micro Dash](/docs/plugins/micro-dash) 50 | - [Authoring](/docs/plugins/authoring) 51 | 52 | # Reference 53 | 54 | - [Global API](/docs/global-api) 55 | 56 | - [dbg](/docs/global-api/log) 57 | - [info](/docs/global-api/log) 58 | - [warn](/docs/global-api/log) 59 | - [error](/docs/global-api/log) 60 | - [env](/docs/global-api/env) 61 | - [store](/docs/global-api/store) 62 | - [stringify](/docs/global-api/stringify) 63 | - [url](/docs/global-api/url) 64 | 65 | - [Context API](/docs/context-api) 66 | - [auth](/docs/context-api/auth) 67 | - [api](/docs/context-api/api) 68 | - [asset](/docs/context-api/asset) 69 | - [body](/docs/context-api/body) 70 | - [data](/docs/context-api/data) 71 | - [echo](/docs/context-api/echo) 72 | - [formData](/docs/context-api/form-data) 73 | - [meta](/docs/context-api/meta) 74 | - [params](/docs/context-api/params) 75 | - [redirect/flash](/docs/context-api/redirect) 76 | - [request](/docs/context-api/request) 77 | - [resolve](/docs/context-api/resolve) 78 | - [response](/docs/context-api/response) 79 | - [JSVM](/docs/jsvm) 80 | - [Plugin Authoring](/docs/plugins/authoring) 81 | 82 | # Guides 83 | 84 | - [📒 HTMX Integration](/docs/htmx) 85 | - [📒 Custom Domains on Fly+Cloudflare](/docs/speedruns/custom-domain-fly-cloudflare) 86 | - [📒 Custom Domains on pockethost.io](/docs/speedruns/custom-domain-pockethost) 87 | - [📒 Google OAuth2](/docs/speedruns/google-oauth2) 88 | - [📒 One-Time Passwords](/docs/speedruns/otp) 89 | - [📒 Outgoing Email with Amazon SES](/docs/speedruns/ses) 90 | - [📒 Setting up a new email domain in Google Suite](/docs/speedruns/gs-gmail) 91 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/asset-management.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Asset Management 3 | description: PocketPages handles static assets with automatic fingerprinting and cache invalidation. 4 | --- 5 | 6 | # Asset Management 7 | 8 | PocketPages provides built-in asset management with content-based fingerprinting for efficient cache invalidation. 9 | 10 | ## Directory Structure 11 | 12 | Place your static assets (images, CSS, JS, etc.) alongside the pages that use them: 13 | 14 | ``` 15 | pb_hooks/ 16 | pages/ 17 | feature/ 18 | index.md # Your content 19 | styles.css # Feature-specific styles 20 | header.jpg # Feature-specific image 21 | shared/ 22 | logo.png # Shared across pages 23 | ``` 24 | 25 | ## Using Assets 26 | 27 | ### In Markdown 28 | 29 | Use standard markdown syntax for images - paths are automatically resolved relative to the current file: 30 | 31 | ```markdown 32 | ![Logo](logo.png) # Local image 33 | ![Header](/shared/logo.png) # Absolute path 34 | ``` 35 | 36 | ### In EJS Templates 37 | 38 | Use the `asset()` helper to generate fingerprinted URLs: 39 | 40 | ```ejs 41 | 42 | 43 | ``` 44 | 45 | ## How It Works 46 | 47 | 1. During startup, PocketPages generates content-based fingerprints for all static files 48 | 2. The `asset()` helper and markdown images automatically generate fingerprinted URLs 49 | 3. URLs are served with long-term cache headers for optimal performance 50 | 51 | ## Best Practices 52 | 53 | 1. Keep assets close to the pages that use them 54 | 2. Use a shared directory (like `shared/` or `assets/`) for common resources 55 | 3. Always verify assets exist in your pages directory 56 | 57 | For detailed information about the `asset()` helper and its features, see the [asset helper documentation](/docs/request-context/asset). 58 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/api.md: -------------------------------------------------------------------------------- 1 | # `api` - The PocketPages API Object 2 | 3 | - **Type**: Object 4 | - **Description**: The `api` property refers to the PocketPages API object itself. This object contains all the methods and properties needed for page rendering and is spread into the global context of each EJS page, making all its methods available as globals. This can be useful if you need to pass the entire API object downstream, for example, when making further processing decisions or passing it to other modules. 5 | 6 | ## Example Usage: 7 | 8 | ```ejs 9 | <%% 10 | function processApi(api) { 11 | // Access API methods directly 12 | api.print('Hello World'); 13 | api.redirect('/some/path'); 14 | 15 | // Or use them as globals (since they're spread into the context) 16 | print('Hello World'); 17 | redirect('/some/path'); 18 | } 19 | 20 | // Pass the entire API object 21 | processApi(api); 22 | %> 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/body.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: body - Raw Request Body 3 | description: Access the raw request body data in PocketPages templates through a function call. 4 | --- 5 | 6 | # `body` - Parsed Request Body 7 | 8 | - **Type**: `() => Record | string` 9 | - **Description**: Returns the request body, parsed by Pocketbase according to the request's Content-Type. Supported types include JSON, XML and form-data. 10 | 11 | ## Basic Usage 12 | 13 | ### Handling JSON Requests 14 | 15 | ```ejs 16 | <%% if (request.method === 'POST') { %> 17 | <%% if (request.headers['content-type']?.includes('application/json')) { %> 18 |
19 | Received JSON data: 20 |
<%%= stringify(body()) %>
21 |
22 | <%% } %> 23 | <%% } %> 24 | ``` 25 | 26 | ### API Endpoint Example 27 | 28 | ```ejs 29 | <%% 30 | if (request.method === 'POST') { 31 | const data = body() 32 | if (typeof data !== 'object' || !data.username || !data.password) { 33 | response.status(400) 34 | response.json({ 35 | error: 'Missing required fields' 36 | }) 37 | return 38 | } 39 | 40 | try { 41 | const user = signInUserWithPassword(data.username, data.password) 42 | response.json({ 43 | success: true, 44 | user: user 45 | }) 46 | } catch (error) { 47 | response.status(401) 48 | response.json({ 49 | error: error.message 50 | }) 51 | } 52 | } 53 | %> 54 | ``` 55 | 56 | ## Raw Body Processing 57 | 58 | ```ejs 59 | <%% 60 | if (request.method === 'POST') { 61 | const rawBody = body() 62 | 63 | if (typeof rawBody === 'string') { 64 | // Process raw string data 65 | const lines = rawBody.split('\n') 66 | // ... process the data 67 | response.json({ 68 | linesProcessed: lines.length 69 | }) 70 | } else { 71 | response.status(400) 72 | response.json({ error: 'Expected raw text data' }) 73 | } 74 | } 75 | %> 76 | ``` 77 | 78 | ## Important Notes 79 | 80 | 1. `body()` is a function that must be called to access the request body 81 | 2. Returns a JavaScript object for JSON content types 82 | 3. Returns a string for other content types 83 | 4. Consider type checking the return value before using it 84 | 85 | See [Request Handling](/docs/request-handling) for more detailed information about working with HTTP requests in PocketPages. 86 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/echo.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: echo - Response Output Helper 3 | description: Write directly to the response output, useful for both debugging and custom response handling. 4 | --- 5 | 6 | # `echo()` - Response Output Helper 7 | 8 | - **Type**: `Function(...args: any[]) => void` 9 | - **Description**: Writes values directly to the response output stream 10 | - **Global**: Yes (available as `echo()` in templates) 11 | - **API Method**: `api.echo(...args)` 12 | 13 | > **Note**: `echo()` writes immediately to the response output stream when called, whether in a loader or template. Objects are automatically stringified, so there's no need to call `JSON.stringify()` unless you need special formatting. 14 | 15 | ## Basic Usage 16 | 17 | ```ejs 18 | 19 | <%% echo(someVariable) %> 20 | 21 | 22 | <%% echo({ hello: 'world' }) %> 23 | 24 | 25 | <%% echo('Status:', status, 'Count:', count) %> 26 | ``` 27 | 28 | ## Common Use Cases 29 | 30 | ### Debugging 31 | 32 | ```ejs 33 | 34 |
35 | <%% echo('Data: ', data) %>
36 | <%% echo('Params: ', params) %>
37 | <%% echo('Form: ', formData) %>
38 | 
39 | 40 | 41 | <%% echo('>>> Checkpoint 1') %> 42 | ``` 43 | 44 | ### Custom Responses 45 | 46 | ```javascript 47 | /** @type {import('pocketpages').MiddlewareLoaderFunc} */ 48 | module.exports = function (api) { 49 | const { echo, request } = api 50 | 51 | // Early response - outputs before headers are sent 52 | if (request.header('Accept') === 'application/json') { 53 | echo({ ok: true }) 54 | return {} 55 | } 56 | 57 | // Continue to template rendering 58 | return { 59 | /* ... */ 60 | } 61 | } 62 | ``` 63 | 64 | ### Function Inspection 65 | 66 | ```ejs 67 | 68 |
69 | <%% echo(mysteriousFunction) %>
70 | 
71 | ``` 72 | 73 | ## echo() vs Logging 74 | 75 | - **echo()**: Immediate response output 76 | 77 | ```ejs 78 | <%% echo(data) %> 79 | ``` 80 | 81 | - **dbg(), info()**: Server-side logging 82 | ```ejs 83 | <%% dbg(data) %> 84 | ``` 85 | 86 | ## Important Notes 87 | 88 | - In loaders, `echo()` writes to the response stream before headers are sent 89 | - In templates, `echo()` writes inline with the template output 90 | - No need to use `<%%= %>` - just `<%% echo() %>` is sufficient 91 | - Multiple arguments are automatically space-separated 92 | - Objects are automatically stringified 93 | 94 | ## See Also 95 | 96 | - [Logging Functions](/docs/global-api/log) 97 | - [Global API](/docs/global-api) 98 | - [Context API Documentation](/docs/context-api) 99 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/meta.md: -------------------------------------------------------------------------------- 1 | # `meta` - Managing Page Metadata and Global Values 2 | 3 | - **Type**: Function 4 | - **Description**: The `meta` function provides a way to get and set metadata and other global values during request processing. While it can be used for any global values, it's most commonly used to manage page metadata like titles, descriptions, and OpenGraph tags. 5 | 6 | ## Function Signature: 7 | 8 | ```typescript 9 | meta(key: string): string | undefined 10 | meta(key: string, value: string): string 11 | ``` 12 | 13 | ## Usage Patterns: 14 | 15 | 1. **Getting a value**: 16 | 17 | ```ejs 18 | <%% const pageTitle = meta('title'); %> 19 | ``` 20 | 21 | 2. **Setting a value**: 22 | 23 | ```ejs 24 | <%% meta('title', 'Welcome to My Site'); %> 25 | ``` 26 | 27 | ## Common Use Cases: 28 | 29 | The most common use case for `meta` is setting page metadata in your `+load.js` files and then using those values in your layout templates. Here's a typical example from a layout file: 30 | 31 | ```ejs 32 | 33 | <%%= meta('title') || 'PocketPages' %> 34 | 35 | 39 | 40 | 41 | 42 | 46 | 50 | 54 | 55 | ``` 56 | 57 | ## Setting Metadata in Load Files: 58 | 59 | You can set metadata values in your `+load.js` files before the page renders: 60 | 61 | ```js 62 | export default async ({ meta }) => { 63 | meta('title', 'About Us') 64 | meta('description', 'Learn more about our company and mission') 65 | meta('image', 'https://example.com/about-preview.jpg') 66 | 67 | return { 68 | // ... other loaded data 69 | } 70 | } 71 | ``` 72 | 73 | ## Additional Use Cases: 74 | 75 | While metadata is the primary use case, `meta` can be used for any global values that need to be accessed across different parts of your application during a request: 76 | 77 | ```ejs 78 | <%% 79 | // Set a global theme 80 | meta('theme', 'dark'); 81 | 82 | // Set the current user's preferred language 83 | meta('language', 'en-US'); 84 | 85 | // Later, access these values anywhere in your templates 86 | const theme = meta('theme'); 87 | const language = meta('language'); 88 | %> 89 | ``` 90 | 91 | > **Note**: Values set using `meta` only persist for the duration of the current request. They do not persist across different requests or between different users. 92 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/params.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: params - Route Parameters 3 | description: Access URL route parameters in PocketPages templates using the params object. 4 | --- 5 | 6 | # `params` - Route Parameters 7 | 8 | - **Type**: Object 9 | - **Description**: The `params` object contains routing parameters derived from placeholder directory and file names (parts of the path wrapped in square brackets). For query string parameters, you'll need to parse them manually from `request.url`. 10 | 11 | ## Route Parameters 12 | 13 | Route parameters are defined using square brackets in file and directory names. For example: 14 | 15 | ``` 16 | pb_hooks/ 17 | pages/ 18 | products/ 19 | [category]/ # params.category 20 | [id].ejs # params.id 21 | users/ 22 | [userId]/ 23 | posts/ 24 | [postId].ejs # Both params.userId and params.postId available 25 | ``` 26 | 27 | ## Example Usage 28 | 29 | ### Basic Parameter Access 30 | 31 | ```ejs 32 | 33 |

Category: <%%= params.category %>

34 |

Product ID: <%%= params.id %>

35 | ``` 36 | 37 | ### Complete Example: Product Details Page 38 | 39 | ```ejs 40 | <%% 41 | // products/[category]/[id].ejs 42 | const { category, id } = params 43 | 44 | // Use parameters for database query 45 | const product = await db.collection('products') 46 | .getOne(id) 47 | 48 | if (!product || product.category !== category) { 49 | response.html(404, `

Product Not Found

`) 50 | return 51 | } 52 | %> 53 | 54 | 55 | 56 | 57 | <%%= product.name %> - <%%= category %> 58 | 59 | 60 | 63 | 64 |
65 |

<%%= product.name %>

66 |

Category: <%%= category %>

67 |

Product ID: <%%= id %>

68 |

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

69 |

Description: <%%= product.description %>

70 |
71 | 72 | 73 |
74 | Route Parameters 75 |
<%%= stringify(params) %>
76 |
77 | 78 | 79 | ``` 80 | 81 | ## Important Notes 82 | 83 | 1. `params` only contains route parameters (from square brackets in paths) 84 | 2. Query string parameters are not directly supported - you'll need to parse them manually from `request.url` 85 | 3. All parameter values are strings 86 | 4. Route parameters are required - if a route parameter is missing, the page won't match 87 | 88 | For query string parameters, you can parse them manually from the request URL: 89 | 90 | ```ejs 91 | <%% 92 | // URL: /products/electronics/123?sort=price&order=desc 93 | const url = new URL(request.url) 94 | const sort = url.searchParams.get('sort') 95 | const order = url.searchParams.get('order') 96 | %> 97 | ``` 98 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/request-oauth2-login.md: -------------------------------------------------------------------------------- 1 | # requestOAuth2Login 2 | 3 | Initiates the OAuth2 authentication flow by redirecting to the provider's authorization endpoint. 4 | 5 | ## Usage 6 | 7 | ```javascript 8 | const authUrl = requestOAuth2Login(providerName) 9 | ``` 10 | 11 | ## Parameters 12 | 13 | - `providerName` (string) - The name of the OAuth2 provider (e.g. "google", "github") 14 | - `options` (object, optional) 15 | - `collection` (string) - The collection to authenticate against (defaults to "users") 16 | - `redirectPath` (string) - The path to redirect to after authentication (defaults to "/auth/oauth/confirm") 17 | - `cookieName` (string) - The name of the cookie to store OAuth2 state (defaults to "pp_oauth_state") 18 | - `autoRedirect` (boolean) - Whether to automatically redirect to the provider (defaults to true) 19 | 20 | ## Returns 21 | 22 | Returns the authorization URL if `autoRedirect` is false. Otherwise redirects to the provider's authorization endpoint. 23 | 24 | ## Example 25 | 26 | ```javascript 27 | 37 | 38 |
39 | 40 | 41 |
42 | ``` 43 | 44 | ## Notes 45 | 46 | - The function automatically generates and stores a state parameter to prevent CSRF attacks 47 | - The state and other OAuth2 parameters are stored in a cookie for validation during callback 48 | - The default redirect URL is constructed using your app's base URL + the redirectPath option 49 | - Make sure the redirect URL matches what is configured in your OAuth2 provider settings 50 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/sign-in-with-oauth2.md: -------------------------------------------------------------------------------- 1 | # signInWithOAuth2 2 | 3 | Completes the OAuth2 authentication flow by exchanging the authorization code for an access token and user data. 4 | 5 | ## Usage 6 | 7 | ```javascript 8 | const authData = signInWithOAuth2(state, code) 9 | ``` 10 | 11 | ## Parameters 12 | 13 | - `state` (string) - The state parameter returned from the OAuth2 provider 14 | - `code` (string) - The authorization code returned from the OAuth2 provider 15 | - `options` (object, optional) - Additional options 16 | - `collection` (string) - The collection to authenticate against (defaults to "users") 17 | - `cookieName` (string) - The name of the cookie storing the OAuth2 state (defaults to "pp_oauth_state") 18 | 19 | ## Returns 20 | 21 | Returns an object containing: 22 | 23 | - `token` - The authentication token 24 | - `record` - The user record 25 | 26 | ## Example 27 | 28 | ```javascript 29 | 39 | ``` 40 | 41 | ## Notes 42 | 43 | - This function is typically called on your OAuth2 callback route after the provider redirects back to your application 44 | - The function automatically validates the state parameter against the stored state to prevent CSRF attacks 45 | - On successful authentication, the user is automatically signed in and the auth cookie is set 46 | - Throws an error if the state validation fails or if the OAuth2 flow cannot be completed 47 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/sign-in-with-token.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: signInWithToken - Token Authentication 3 | description: Set authentication state using a token in PocketPages templates. 4 | --- 5 | 6 | # `signInWithToken` - Token Authentication 7 | 8 | - **Type**: `(token: string) => void` 9 | - **Description**: Core authentication function that sets the `pb_auth` cookie. All other authentication methods (`signInWithPassword`, `registerWithPassword`, `signInAnonymously`) internally use this function to set the cookie. 10 | 11 | ## Basic Usage 12 | 13 | ```ejs 14 | <%% 15 | // Set authentication using a token 16 | signInWithToken('your-auth-token-here') 17 | redirect('/dashboard') 18 | %> 19 | ``` 20 | 21 | ## Cookie Management 22 | 23 | This is the only function that directly sets the `pb_auth` cookie. Other authentication methods work like this: 24 | 25 | ```typescript 26 | // How signInWithPassword works internally 27 | function signInWithPassword(email: string, password: string) { 28 | // 1. Authenticate with PocketBase 29 | const authData = pb.collection('users').authWithPassword(...) 30 | 31 | // 2. Use signInWithToken to set the cookie 32 | signInWithToken(authData.token) 33 | 34 | return authData 35 | } 36 | ``` 37 | 38 | ## Common Use Cases 39 | 40 | ### OAuth Flow Completion 41 | 42 | ```ejs 43 | <%% 44 | // After receiving token from OAuth provider 45 | const token = params.token 46 | if (token) { 47 | signInWithToken(token) 48 | redirect('/dashboard') 49 | } else { 50 | redirect('/login?error=missing_token') 51 | } 52 | %> 53 | ``` 54 | 55 | ### Custom Authentication Flow 56 | 57 | ```ejs 58 | <%% 59 | if (request.method === 'POST') { 60 | try { 61 | // Custom authentication logic 62 | const response = await customAuthProvider.authenticate(formData) 63 | 64 | if (response.token) { 65 | signInWithToken(response.token) 66 | redirect('/dashboard') 67 | } 68 | 69 | } catch (error) { 70 | %> 71 |
72 | Authentication failed: <%%= error.message %> 73 |
74 | <%% 75 | } 76 | } 77 | %> 78 | ``` 79 | 80 | ## Important Notes 81 | 82 | 1. **Cookie Management**: This function: 83 | 84 | - Is the core cookie-setting function used by all auth methods 85 | - Sets the `pb_auth` cookie with the provided token 86 | - Does not validate the token 87 | - Does not fetch the user record 88 | 89 | 2. **Security Considerations**: 90 | 91 | - Always validate tokens before using them 92 | - Use HTTPS in production 93 | - Consider token expiration 94 | - Protect against CSRF attacks 95 | 96 | 3. **Usage Context**: Typically used: 97 | - After third-party authentication 98 | - In custom authentication flows 99 | - When implementing token refresh logic 100 | - Internally by other auth methods 101 | 102 | ## Related Topics 103 | 104 | - [`signInWithPassword`](/docs/context-api/sign-in-with-password) 105 | - [`signOut`](/docs/context-api/sign-out) 106 | - [`request.auth`](/docs/context-api/auth) 107 | - [Authentication Guide](/docs/authentication) 108 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/context-api/sign-out.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: signOut - User Logout 3 | description: Sign out the current user by clearing their authentication cookie in PocketPages templates. 4 | --- 5 | 6 | # `signOut` - User Logout 7 | 8 | - **Type**: `() => void` 9 | - **Description**: Signs out the current user by clearing their authentication cookie. After calling this function, `request.auth` will be `undefined` on subsequent requests. 10 | 11 | ## Basic Usage 12 | 13 | ```ejs 14 | <%% 15 | signOut() 16 | redirect('/login') 17 | %> 18 | ``` 19 | 20 | ## Common Use Cases 21 | 22 | ### Logout Button/Form 23 | 24 | ```ejs 25 | <%% 26 | if (request.method === 'POST' && formData.action === 'logout') { 27 | signOut() 28 | redirect('/login') 29 | } 30 | %> 31 | 32 |
33 | 34 | 35 |
36 | ``` 37 | 38 | ### Session Expiry Handler 39 | 40 | ```ejs 41 | <%% 42 | if (request.auth) { 43 | const lastActivity = new Date(request.auth.get('lastActivity')) 44 | const now = new Date() 45 | const inactiveTime = now - lastActivity 46 | 47 | if (inactiveTime > 30 * 60 * 1000) { // 30 minutes 48 | signOut() 49 | redirect('/login?reason=session_expired') 50 | return 51 | } 52 | } 53 | %> 54 | ``` 55 | 56 | ## Important Notes 57 | 58 | 1. **Cookie Management**: This function: 59 | 60 | - Clears the authentication cookie 61 | - Takes effect immediately 62 | - Does not require a server response 63 | 64 | 2. **Security Considerations**: 65 | 66 | - Always redirect after logout 67 | - Clear any client-side state 68 | - Consider implementing CSRF protection 69 | - Use POST requests for logout actions 70 | 71 | 3. **Best Practices**: 72 | 73 | - Redirect to login page after logout 74 | - Show confirmation messages 75 | - Handle errors gracefully 76 | - Consider cleanup of user-specific data 77 | 78 | 4. **Client-Side Integration**: 79 | - This function only clears the server-side cookie 80 | - If using the PocketBase JS SDK on the frontend, you'll need to handle its authentication state separately 81 | - The SDK uses localStorage for JWT storage, which isn't affected by cookie changes 82 | - Consider implementing a complete logout that handles both: 83 | 84 | ```ejs 85 | 86 | 99 | 100 | 101 | ``` 102 | 103 | ## Related Topics 104 | 105 | - [`signInWithPassword`](/docs/context-api/sign-in-with-password) 106 | - [`signInWithToken`](/docs/context-api/sign-in-with-token) 107 | - [`request.auth`](/docs/context-api/auth) 108 | - [Authentication Guide](/docs/authentication) 109 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/creating-a-page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating a PocketPages Page 3 | description: Step-by-step process for creating and organizing EJS template files in PocketPages, including file naming conventions, directory structure, and URL routing patterns. 4 | --- 5 | 6 | # Creating a PocketPages Page 7 | 8 | PocketPages allows you to create dynamic pages for your application using EJS templating. Below are the steps and guidelines to create a page that will be served by PocketPages. 9 | 10 | ## Creating Pages 11 | 12 | 1. **Create an EJS File**: Inside the `pb_hooks/pages/` directory, create an `.ejs` file. This file will represent the page that you want to serve. 13 | 14 | For example, to create an "About" page: 15 | 16 | ```text 17 | pb_hooks/pages/about.ejs 18 | ``` 19 | 20 | 2. **Special Case - `index.ejs`**: The `index.ejs` file has a special role at any directory level. 21 | 22 | At the root level: 23 | 24 | ```text 25 | pb_hooks/pages/index.ejs -> serves "/" 26 | ``` 27 | 28 | In subdirectories: 29 | 30 | ```text 31 | pb_hooks/pages/products/index.ejs -> serves "/products" 32 | ``` 33 | 34 | 3. **Serving Pages**: Any `.ejs` file within `pb_hooks/pages/` can be served directly. The name of the file (minus the `.ejs` extension) will correspond to the URL path. 35 | 36 | Example file structure: 37 | 38 | ```text 39 | pb_hooks/pages/ 40 | ├── index.ejs -> "/" 41 | ├── about.ejs -> "/about" 42 | ├── contact.ejs -> "/contact" 43 | └── products/ 44 | ├── index.ejs -> "/products" 45 | └── details.ejs -> "/products/details" 46 | ``` 47 | 48 | 4. **Nested Pages**: You can organize your pages into subdirectories. The routing will follow the directory structure. If no specific file matches the route, an `index.ejs` in the corresponding directory will be served. 49 | 50 | Example routing table: 51 | 52 | ```text 53 | URL Path File Path 54 | / pb_hooks/pages/index.ejs 55 | /about pb_hooks/pages/about.ejs 56 | /contact pb_hooks/pages/contact.ejs 57 | /products pb_hooks/pages/products/index.ejs 58 | /products/details pb_hooks/pages/products/details.ejs 59 | ``` 60 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/database.md: -------------------------------------------------------------------------------- 1 | # Server-side Data 2 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/debugging.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Debugging in PocketPages 3 | description: Learn how to enable and configure debugging output in PocketPages applications. 4 | --- 5 | 6 | # Debugging in PocketPages 7 | 8 | PocketPages provides several levels of debugging output to help you develop and troubleshoot your application. 9 | 10 | ## Development Mode 11 | 12 | Running PocketBase with the `--dev` flag automatically enables debug output from the `dbg()` function (see [Logging Functions](/docs/global-api/log) for details): 13 | 14 | ```bash 15 | pocketbase serve --dev 16 | ``` 17 | 18 | Without the `--dev` flag, all `dbg()` output is suppressed, making your production logs cleaner and more focused on important information. 19 | 20 | ## Plugin Debugging 21 | 22 | Each plugin can have its own debug output enabled or disabled. By default, plugin debugging is disabled. You can enable it for specific plugins in your `+config.js` file: 23 | 24 | ```javascript 25 | module.exports = { 26 | plugins: [ 27 | // Enable debugging for just the EJS plugin 28 | { 29 | name: 'pocketpages-plugin-ejs', 30 | debug: true, 31 | }, 32 | 33 | // Other plugins remain quiet 34 | 'pocketpages-plugin-marked', 35 | ], 36 | debug: false, 37 | } 38 | ``` 39 | 40 | See [Configuration](/docs/config) for more details about plugin configuration. 41 | 42 | ## Core Debugging 43 | 44 | PocketPages core debugging is disabled by default. While rarely needed, you can enable it by setting the top-level `debug` option in your `+config.js`: 45 | 46 | ```javascript 47 | module.exports = { 48 | plugins: ['pocketpages-plugin-ejs'], 49 | debug: true, // Enable core debugging 50 | } 51 | ``` 52 | 53 | This will output detailed information about routes, parameters, and other internal details that can be helpful when troubleshooting core PocketPages behavior. 54 | 55 | > **Note**: Enabling core debugging can produce a lot of output. It's recommended to only enable it when specifically debugging PocketPages core functionality. 56 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/deploying.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deploying to Production 3 | description: Deploy PocketPages to pockethost.io with manual or GitHub Actions workflows, or self-host on Fly.io. Includes deployment scripts, environment setup, and configuration steps. 4 | --- 5 | 6 | # Deploying to Production 7 | 8 | PocketPages is easy to deploy. If you follow the [recommended project structure](/docs/structure), everything in `/pb_*` can be deployed. 9 | 10 | The two most popular ways to go live with PocketBase are to use [pockethost.io](https://pockethost.io) or to self-host using [Fly.io](https://fly.io). 11 | 12 | ## Recommended: Deploy to pockethost.io 13 | 14 | pockethost.io is the premiere PocketBase hosting service trusted by over 10,000 developers and millions of end users. 15 | 16 | In under 30 seconds, you can provision a free instance with unlimited (Fair Use) resources. 17 | 18 | ### Manual Deployment 19 | 20 | The easiest way to deploy is using the PocketHost.IO CLI utility (PHIO). Here's how: 21 | 22 | 1. Install the PHIO CLI globally: 23 | 24 | ```bash 25 | npm i -g phio 26 | ``` 27 | 28 | 2. Login to your PocketHost account: 29 | 30 | ```bash 31 | phio login 32 | ``` 33 | 34 | 3. Link your local project to your PocketHost instance: 35 | 36 | ```bash 37 | phio link 38 | ``` 39 | 40 | 4. Deploy your project: 41 | 42 | ```bash 43 | phio deploy 44 | ``` 45 | 46 | ### Github Actions Deployment 47 | 48 | To set up automated deployments using Github Actions: 49 | 50 | ```bash 51 | cp -r node_modules/pocketpages/starters/deploy-pockethost-ga . 52 | ``` 53 | 54 | You'll need to set a few Github secrets. Look in the YAML file for details. 55 | 56 | ## Deploy to Fly.io 57 | 58 | _Warning: Self-hosting is an advanced setup. I know Fly pretty well and it still took me an hour._ 59 | 60 | To set up Fly.io deployment: 61 | 62 | ```bash 63 | cp -r node_modules/pocketpages/starters/deploy-fly-ga . 64 | ``` 65 | 66 | After this, you should see a `Dockerfile` and `fly.toml`. 67 | 68 | Use `fly launch` and `fly deploy` to create a Fly app and deploy it. 69 | 70 | For more information, see [Host for Free on Fly.io](https://github.com/pocketbase/pocketbase/discussions/537) 71 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/directory-structure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Directory Structure 3 | description: File organization requirements and conventions for PocketPages applications, including the mandatory pb_hooks/pages/ root directory and examples of nested page structures. 4 | --- 5 | 6 | # Directory Structure 7 | 8 | All PocketPages must reside within the `pb_hooks/pages/` directory of your project. This is the designated location where PocketPages looks for pages to serve. 9 | 10 | ### Example Structure: 11 | 12 | ``` 13 | pb_hooks/ 14 | pages/ 15 | index.ejs 16 | about.ejs 17 | contact.ejs 18 | products/ 19 | index.ejs 20 | details.ejs 21 | ``` 22 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/features.md: -------------------------------------------------------------------------------- 1 | # Key Features 2 | 3 | PocketPages is a modern web framework built on PocketBase that combines the simplicity of file-based routing with the power of server-side rendering. It's designed to help developers build fast, secure, and SEO-friendly web applications with minimal configuration. Whether you're building a simple landing page or a complex web application, PocketPages provides the tools and features you need while maintaining a lightweight footprint. 4 | 5 | ## Fast and Lightweight 6 | 7 | - Built on Golang and Goja for high performance 8 | - Minimal dependencies and small footprint 9 | - Quick startup times and efficient resource usage 10 | 11 | ## Powered by PocketBase 12 | 13 | - Full access to PocketBase JSVM API 14 | - Native database integration 15 | - Built-in authentication and authorization 16 | - Real-time capabilities 17 | 18 | ## Modern Development Experience 19 | 20 | - File-based routing for intuitive navigation 21 | - EJS templating for dynamic content 22 | - Built-in asset management with fingerprinting 23 | - Hot reloading in development 24 | - TypeScript support 25 | 26 | ## Server-Side Rendering 27 | 28 | - SEO-friendly by default 29 | - Fast initial page loads 30 | - Reduced client-side JavaScript 31 | - Support for meta tags and OpenGraph 32 | 33 | ## Robust Features 34 | 35 | - Global proxy network support 36 | - Content-based cache invalidation 37 | - Private file handling 38 | - Form processing 39 | - Middleware support 40 | - Markdown processing 41 | - Environment variable management 42 | 43 | ## Developer Tools 44 | 45 | - VSCode/Cursor integration 46 | - Built-in debugging helpers 47 | - Comprehensive type definitions 48 | - Clear error messages 49 | 50 | ## Framework Integration 51 | 52 | - HTMX support for dynamic updates 53 | - AlpineJS for client-side interactivity 54 | - TailwindCSS + DaisyUI for styling 55 | - Markdown with code highlighting 56 | 57 | ## Deployment Options 58 | 59 | - One-click deploy to pockethost.io 60 | - Self-hosting support on Fly.io 61 | - GitHub Actions integration 62 | - Custom domain configuration 63 | - Environment-based configuration 64 | 65 | ## Security Features 66 | 67 | - Secure by default 68 | - Private directory protection 69 | - Environment variable management 70 | - Form validation helpers 71 | - CSRF protection 72 | 73 | ## Performance 74 | 75 | - Automatic asset fingerprinting 76 | - Efficient caching strategies 77 | - CDN-friendly architecture 78 | - Response compression 79 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/global-api/env.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: env - Environment Variable Access 3 | description: Securely access environment variables in PocketPages applications 4 | --- 5 | 6 | # `env` - Environment Variable Access 7 | 8 | - **Type**: `(key: string) => string` 9 | - **Description**: The `env` function provides secure access to environment variables. It returns an empty string if the variable is not found. 10 | 11 | ## Basic Usage 12 | 13 | ```javascript 14 | const apiKey = env('API_KEY') 15 | const dbPassword = env('DB_PASSWORD') 16 | ``` 17 | 18 | ## Template Usage 19 | 20 | ```ejs 21 | <%% const apiKey = env('API_KEY') %> 22 |

Using API key: <%%= apiKey %>

23 | ``` 24 | 25 | ## Security Notes 26 | 27 | - Returns empty string for undefined variables 28 | - Use for sensitive configuration 29 | - Avoid exposing secrets in templates 30 | - Prefer environment variables over hardcoded values 31 | 32 | ## Best Practices 33 | 34 | 1. **Check for Required Variables** 35 | 36 | ```javascript 37 | const apiKey = env('API_KEY') 38 | if (!apiKey) { 39 | error('Missing required API_KEY environment variable') 40 | // Handle error case 41 | } 42 | ``` 43 | 44 | 2. **Use Descriptive Names** 45 | 46 | ```javascript 47 | // Good 48 | const stripeSecretKey = env('STRIPE_SECRET_KEY') 49 | 50 | // Avoid 51 | const key = env('KEY') 52 | ``` 53 | 54 | 3. **Document Required Variables** 55 | 56 | ```javascript 57 | // Document required environment variables in your README or configuration files 58 | /** 59 | * Required environment variables: 60 | * - API_KEY: Your API key for external service 61 | * - DB_PASSWORD: Database password 62 | * - SMTP_PASSWORD: Email service password 63 | */ 64 | ``` 65 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/global-api/micro-dash.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Micro-dash Functions 3 | description: Lightweight utility functions for working with arrays and objects 4 | --- 5 | 6 | # Micro-dash Functions 7 | 8 | PocketPages includes a subset of utility functions from [@s-libs/micro-dash](https://github.com/simontonsoftware/s-libs/tree/master/projects/micro-dash) for working with arrays and objects. These functions are available globally in templates and via `require('pocketpages')`. 9 | 10 | ## Available Functions 11 | 12 | ### forEach 13 | 14 | Iterates over elements of a collection and invokes an iteratee for each element. 15 | 16 | ```js 17 | const { forEach } = require('pocketpages') 18 | 19 | forEach([1, 2, 3], (value) => { 20 | dbg(value) 21 | }) 22 | 23 | forEach({ a: 1, b: 2 }, (value, key) => { 24 | dbg(key, value) 25 | }) 26 | ``` 27 | 28 | ### keys 29 | 30 | Gets the object's property names as an array. 31 | 32 | ```js 33 | const { keys } = require('pocketpages') 34 | 35 | const obj = { a: 1, b: 2, c: 3 } 36 | const propertyNames = keys(obj) 37 | // => ['a', 'b', 'c'] 38 | ``` 39 | 40 | ### values 41 | 42 | Gets the object's property values as an array. 43 | 44 | ```js 45 | const { values } = require('pocketpages') 46 | 47 | const obj = { a: 1, b: 2, c: 3 } 48 | const propertyValues = values(obj) 49 | // => [1, 2, 3] 50 | ``` 51 | 52 | ### merge 53 | 54 | Recursively merges own enumerable properties of source objects into the destination object. 55 | 56 | ```js 57 | const { merge } = require('pocketpages') 58 | 59 | const object = { 60 | a: [{ b: 2 }, { d: 4 }], 61 | } 62 | 63 | const other = { 64 | a: [{ c: 3 }, { e: 5 }], 65 | } 66 | 67 | merge(object, other) 68 | // => { a: [{ b: 2, c: 3 }, { d: 4, e: 5 }] } 69 | ``` 70 | 71 | ### pick 72 | 73 | Creates an object composed of the picked object properties. 74 | 75 | ```js 76 | const { pick } = require('pocketpages') 77 | 78 | const object = { a: 1, b: 2, c: 3, d: 4 } 79 | pick(object, ['a', 'c']) 80 | // => { a: 1, c: 3 } 81 | ``` 82 | 83 | ## Using in Templates 84 | 85 | These functions are automatically available in EJS templates: 86 | 87 | ```ejs 88 | <%% 89 | forEach(['Home', 'About', 'Contact'], (page) => { 90 | echo(`${page}`) 91 | }) 92 | %> 93 | 94 | <%% 95 | const config = { theme: 'dark', lang: 'en' } 96 | const userPrefs = { theme: 'light' } 97 | const finalConfig = merge({}, config, userPrefs) 98 | %> 99 | ``` 100 | 101 | ## Using in JavaScript Files 102 | 103 | Import the functions you need from the PocketPages package: 104 | 105 | ```js 106 | const { forEach, keys, values, merge, pick } = require('pocketpages') 107 | 108 | function processObject(obj) { 109 | forEach(keys(obj), (key) => { 110 | dbg(`Processing ${key}:`, obj[key]) 111 | }) 112 | } 113 | ``` 114 | 115 | For more detailed information about these utility functions, refer to the [@s-libs/micro-dash documentation](https://github.com/simontonsoftware/s-libs/tree/master/projects/micro-dash). 116 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/global-api/stringify.md: -------------------------------------------------------------------------------- 1 | # `stringify` - Circular-Safe Stringify Helper 2 | 3 | - **Type**: Function 4 | - **Description**: The `stringify` helper is a `JSON.stringify` replacement that prevents circular references from causing errors. It is useful when you need to serialize complex objects for logging or debugging. 5 | 6 | ## Example Usage: 7 | 8 | ```ejs 9 | <%% log.dbg("Request Context:", stringify(context)); %> 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/global-api/url.md: -------------------------------------------------------------------------------- 1 | # `url` - URL Parsing Function 2 | 3 | - **Type**: Function 4 | - **Description**: The `url` function is used to parse a URL string. It returns an object equivalent to using `new URL()` in the browser's Web API, with the addition of automatic query string parsing into an object. This can be helpful for manipulating or inspecting URLs within your EJS templates. 5 | 6 | ## Example Usage: 7 | 8 | ```ejs 9 | <%% 10 | // Basic URL parsing 11 | const parsedUrl = url('https://example.com/path?query=123'); 12 | %> 13 |

Hostname: <%%= parsedUrl.hostname %>

14 |

Pathname: <%%= parsedUrl.pathname %>

15 |

Search: <%%= parsedUrl.search %>

16 | 17 | <%% 18 | // Query string parsing 19 | const withQuery = url('https://example.com/search?name=john&age=25&tags[]=one&tags[]=two') 20 | 21 | // Query parameters are automatically parsed into an object 22 | dbg({ 23 | name: withQuery.query.name, // "john" 24 | age: withQuery.query.age, // "25" 25 | tags: withQuery.query.tags // ["one", "two"] 26 | }) 27 | %> 28 | ``` 29 | 30 | ## Query String Parsing 31 | 32 | The `query` property contains an object with all query parameters parsed: 33 | 34 | - Simple parameters become string values 35 | - Array parameters (using `[]`) become arrays 36 | - Empty values become empty strings 37 | - Missing values become `undefined` 38 | 39 | ```ejs 40 | <%% 41 | const examples = [ 42 | url('/?name=alice'), // query.name === "alice" 43 | url('/?items[]=1&items[]=2'), // query.items === ["1", "2"] 44 | url('/?empty='), // query.empty === "" 45 | url('/?missing'), // query.missing === undefined 46 | url('/?a=1&b=2&c=3') // query === { a: "1", b: "2", c: "3" } 47 | ] 48 | %> 49 | ``` 50 | 51 | ## See Also 52 | 53 | - [Request Context](/docs/context-api/request) 54 | - [Redirect](/docs/context-api/redirect) 55 | - [Parameters](/docs/parameters) 56 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/index.md: -------------------------------------------------------------------------------- 1 | <%- include('overview.md') %> 2 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | description: Step-by-step guide for installing PocketPages. 4 | --- 5 | 6 | # Installation 7 | 8 | > **PocketPages requires PocketBase v0.25.5 or later.** 9 | 10 | Installing PocketPages is easy. 11 | 12 | <%- include(`quickstart.ejs`) %> 13 | 14 | _Note: `--dir=pb_data` is necessary to tell PocketBase to use the current directory for data storage._ 15 | 16 | Browse to `http://localhost:8090` and with any luck at all, you'll see: 17 | 18 | <%- include(`browser.ejs`, { url: `http://localhost:8090`, content: `Hello, world!`}) %> 19 | 20 | To start editing, find 21 | 22 | ``` 23 | ./pb_hooks/pages/index.ejs 24 | ``` 25 | 26 | Changes appear immediately on the next refresh. 27 | 28 | ## How does it work? 29 | 30 | PocketPages is a Multi-Page Application (MPA) preprocessor for PocketBase. It listens for requests and renders pages using file-based routing rules like old school PHP. 31 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/jsvm.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: JavaScript API 3 | description: PocketBase's JavaScript runtime environment capabilities, limitations, and examples for database operations, with details on NPM package compatibility and available APIs. 4 | --- 5 | 6 | # JavaScript API 7 | 8 | PocketBase's JavaScript runtime environment is neither Browser nor NodeJS. As such, it lacks Web APIs and NodeJS APIs such as `Buffer` and `require('fs')`. 9 | 10 | There is [extensive documentation](https://pocketbase.io/docs/js-overview/) covering many aspects of extending PocketBase with JS hooks. You'll probably be most concerned with [database operations](https://pocketbase.io/docs/js-database/) and higher-level [record operations](https://pocketbase.io/docs/js-records/), like this: 11 | 12 | ```js 13 | const records = $app.findRecordsByExpr( 14 | 'articles', 15 | $dbx.exp('LOWER(username) = {:username}', { username: 'John.Doe' }), 16 | $dbx.hashExp({ status: 'pending' }) 17 | ) 18 | ``` 19 | 20 | Going even deeper, look at the [PocketBase JSVM docs](https://pocketbase.io/jsvm/index.html) to see available APIs. It's a little hard to understand, so hopefully the examples we provide will help to fill in any unfamiliar concepts. 21 | 22 | ## But can I use my favorite NPM package? 23 | 24 | Probably not, but maybe you're luckier than I am. Any NPM modules that work as pure EcmaScript will also work inside PocketBase, as long as they are CommonJS. 25 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/markdown.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Support 3 | description: PocketPages processes .md files through EJS templating and Markdown parsing, with built-in frontmatter support for metadata extraction via the meta() function in templates. 4 | --- 5 | 6 | # Markdown Support in PocketPages 7 | 8 | PocketPages supports rendering `.md` files, treating them similarly to `.ejs` files but with an additional step: Markdown parsing. 9 | 10 | ## How It Works: 11 | 12 | 1. **EJS Processing**: Any file with the `.md` extension is first processed through the EJS engine, just like a regular `.ejs` file. This means you can use all the dynamic templating features of EJS within your Markdown files. 13 | 14 | 2. **Markdown Parsing**: After EJS processing, the content is passed through a Markdown parser. This ensures that any Markdown syntax (such as headers, lists, and links) is properly rendered into HTML. 15 | 16 | 3. **Final Output**: The last step in the pipeline is Markdown parsing, so the final output is HTML content that reflects both your EJS logic and your Markdown formatting. 17 | 18 | ## Frontmatter Support 19 | 20 | Any frontmatter properties defined at the top of your Markdown file will be automatically available through the request context's `meta` function. For example: 21 | 22 | ```markdown 23 | --- 24 | title: My Blog Post 25 | description: A detailed guide about something interesting 26 | author: John Doe 27 | --- 28 | 29 | # Content starts here... 30 | ``` 31 | 32 | You can then access these values in your layouts or other templates using the `meta` function: 33 | 34 | ```ejs 35 | <%%= meta('title') %> 36 | 37 | 38 | ``` 39 | 40 | ## Important Notes: 41 | 42 | - **Layouts Cannot Be Markdown**: While `.md` files can include dynamic content through EJS and Markdown, they cannot be used as layouts. Layouts must be `.ejs` files. 43 | 44 | By supporting Markdown in this way, PocketPages allows you to combine the power of dynamic EJS templates with the simplicity and readability of Markdown, making it easier to manage content-heavy projects. 45 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/overview.md: -------------------------------------------------------------------------------- 1 | <%- include('overview.md') %> 2 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/parameters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Route and Query Parameters' 3 | description: 'Access URL path segments and query strings in PocketPages templates using params.paramName. Route parameters use [brackets] in file/directory names. Query parameters override route parameters when names conflict.' 4 | --- 5 | 6 | # Route and Query Parameters 7 | 8 | PocketPages lets you access both route parameters (from URL paths) and query parameters (from query strings) in your templates. 9 | 10 | ## Route Parameters 11 | 12 | Use square brackets `[]` in file or directory names to capture URL path segments as parameters. 13 | 14 | ### Example Structure 15 | 16 | ``` 17 | pb_hooks/pages/ 18 | products/ 19 | [productId]/ 20 | index.ejs 21 | [productId]/reviews/ 22 | [reviewId].ejs 23 | ``` 24 | 25 | This structure handles URLs like: 26 | 27 | - `/products/123` 28 | - `/products/123/reviews/456` 29 | 30 | ### Using Route Parameters 31 | 32 | Access route parameters through `params` in your templates: 33 | 34 | ```ejs 35 | 36 |

Product: <%%= params.productId %>

37 | 38 | 39 |

Product: <%%= params.productId %>

40 |

Review: <%%= params.reviewId %>

41 | ``` 42 | 43 | ## Query Parameters 44 | 45 | Query parameters come from the URL's query string (after the `?`). They're also available through `params`: 46 | 47 | ``` 48 | /products/123?sort=latest&highlight=true 49 | ``` 50 | 51 | Access them the same way in templates: 52 | 53 | ```ejs 54 |

Sort by: <%%= params.sort %>

55 |

Highlight: <%%= params.highlight %>

56 | ``` 57 | 58 | ## Parameter Priority 59 | 60 | Query parameters override route parameters when they have the same name: 61 | 62 | ``` 63 | /products/123?productId=789 64 | ``` 65 | 66 | Here, `params.productId` will be `789`, not `123`. 67 | 68 | ## Complete Example 69 | 70 | URL: 71 | 72 | ``` 73 | /products/123/reviews/456?sort=latest&highlight=true 74 | ``` 75 | 76 | Template: 77 | 78 | ```ejs 79 |

Product: <%%= params.productId %>

80 |

Review: <%%= params.reviewId %>

81 |

Sort by: <%%= params.sort %>

82 |

Highlight: <%%= params.highlight %>

83 | ``` 84 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/plugins/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Plugins 3 | description: Extend PocketPages with custom functionality using its powerful plugin architecture. 4 | --- 5 | 6 | # Plugins 7 | 8 | PocketPages has a highly **flexible plugin architecture** that allows you to extend the framework far beyond templating. Plugins can interact with various stages of your application, from request and response handling to rendering and extending the API context. 9 | 10 | ## Official Plugins 11 | 12 | PocketPages comes with several official plugins: 13 | 14 | - **EJS Plugin**: Template processing with enhanced features 15 | - **Markdown Plugin**: Process Markdown files with frontmatter support 16 | - **Realtime Plugin**: Add Server-Sent Events (SSE) support 17 | - **Authentication Plugin**: Complete auth system with multiple methods 18 | - **JS SDK Plugin**: PocketBase JavaScript SDK integration 19 | - **Micro Dash Plugin**: Lightweight utility functions for data manipulation 20 | 21 | ## What Can Plugins Do? 22 | 23 | - **Extend Request and Response:** 24 | Use hooks such as `onRequest` and `onResponse` to modify request processing and response delivery. 25 | - **Customize Rendering:** 26 | Intercept and modify output with the `onRender` hook. 27 | - **Extend the API:** 28 | Add custom functions or even integrate entire sub-applications via `onExtendContextApi`. 29 | 30 | ## Plugin Processing Order 31 | 32 | Plugins are processed in the order they appear in your `plugins` array. This is particularly important when plugins modify content, as each plugin's output becomes the input for the next plugin. 33 | 34 | For example, when using both EJS and Markdown plugins: 35 | 36 | ```javascript 37 | module.exports = { 38 | plugins: [ 39 | // First: Process EJS templates 40 | 'pocketpages-plugin-ejs', 41 | // Second: Convert Markdown to HTML 42 | 'pocketpages-plugin-marked', 43 | ], 44 | } 45 | ``` 46 | 47 | This sequential processing allows you to: 48 | 49 | - Chain transformations 50 | - Extend functionality incrementally 51 | - Control how content is processed 52 | 53 | Consider the processing order when configuring plugins that work together or modify the same types of content. 54 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/plugins/micro-dash.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Micro Dash Plugin 3 | description: Lightweight utility functions for data manipulation in PocketPages applications. 4 | --- 5 | 6 | # Micro Dash Plugin 7 | 8 | The Micro Dash plugin (`pocketpages-plugin-micro-dash`) provides a set of lightweight utility functions for data manipulation, based on the `@s-libs/micro-dash` library. 9 | 10 | ## Installation 11 | 12 | ```bash 13 | npm install pocketpages-plugin-micro-dash 14 | ``` 15 | 16 | ## Configuration 17 | 18 | Add the plugin to your `+config.js` file: 19 | 20 | ```javascript 21 | module.exports = { 22 | plugins: [ 23 | 'pocketpages-plugin-micro-dash', 24 | // ... other plugins 25 | ], 26 | } 27 | ``` 28 | 29 | ## Available Functions 30 | 31 | The plugin adds several utility functions to the global context: 32 | 33 | ```typescript 34 | // Collection Operations 35 | function forEach( 36 | collection: T[], 37 | iteratee: (value: T, key: number) => void 38 | ): void 39 | function keys(object: object): string[] 40 | function values(object: { [key: string]: T }): T[] 41 | 42 | // Object Operations 43 | function merge(...objects: object[]): object 44 | function pick(object: T, ...props: string[]): Partial 45 | 46 | // Array Operations 47 | function shuffle(array: T[]): T[] 48 | ``` 49 | 50 | ## Usage Examples 51 | 52 | ### Collection Operations 53 | 54 | ```ejs 55 | <%% 56 | // Iterate over arrays or objects 57 | forEach([1, 2, 3], (value) => { 58 | echo(value) 59 | }) 60 | 61 | // Get object keys 62 | const obj = { a: 1, b: 2 } 63 | const objKeys = keys(obj) // ['a', 'b'] 64 | 65 | // Get object values 66 | const objValues = values(obj) // [1, 2] 67 | %> 68 | ``` 69 | 70 | ### Object Operations 71 | 72 | ```ejs 73 | <%% 74 | // Merge objects 75 | const merged = merge( 76 | { a: 1 }, 77 | { b: 2 }, 78 | { c: 3 } 79 | ) // { a: 1, b: 2, c: 3 } 80 | 81 | // Pick specific properties 82 | const user = { 83 | id: 1, 84 | name: 'John', 85 | email: 'john@example.com', 86 | password: 'secret' 87 | } 88 | const safeUser = pick(user, 'id', 'name', 'email') 89 | %> 90 | ``` 91 | 92 | ### Array Operations 93 | 94 | ```ejs 95 | <%% 96 | // Shuffle an array 97 | const numbers = [1, 2, 3, 4, 5] 98 | const shuffled = shuffle(numbers) 99 | %> 100 | ``` 101 | 102 | ## Performance 103 | 104 | The micro-dash functions are optimized for size and performance, making them ideal for server-side use in the JSVM environment. They provide a subset of Lodash functionality without the full library overhead. 105 | 106 | ## Type Safety 107 | 108 | All functions are fully typed and provide TypeScript support out of the box: 109 | 110 | ```typescript 111 | interface User { 112 | id: number 113 | name: string 114 | email: string 115 | } 116 | 117 | // Types are preserved 118 | const users: User[] = [ 119 | /*...*/ 120 | ] 121 | forEach(users, (user: User) => { 122 | // user is properly typed 123 | }) 124 | 125 | const userObj: User = { 126 | /*...*/ 127 | } 128 | const partial = pick(userObj, 'id', 'name') 129 | // partial is Partial> 130 | ``` 131 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/prettier.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Prettier Configuration 3 | description: Configure Prettier code formatting for PocketPages using prettier-plugin-ejs. Install the plugin via package manager, add configuration to package.json, and format EJS templates with standard Prettier options. 4 | --- 5 | 6 | # Prettier PocketPages 7 | 8 | If you like using Prettier to format your code, you'll be happy to know that [prettier-plugin-ejs](https://github.com/ecmel/prettier-plugin-ejs) works pretty well (but not perfectly). 9 | 10 | ``` 11 | bun add -D prettier-plugin-ejs 12 | ``` 13 | 14 | Then, in `package.json`: 15 | 16 | ```json 17 | "prettier": { 18 | "semi": false, 19 | "singleQuote": true, 20 | "trailingComma": "es5", 21 | "plugins": [ 22 | "prettier-plugin-ejs" 23 | ] 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/custom-domain-fly-cloudflare.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Speedrun: Connecting Your Fly.io App to a Custom Domain with Cloudflare Proxy' 3 | description: 'Step-by-step process to configure DNS records, SSL certificates, and domain verification between Fly.io and Cloudflare. Includes specific settings for A/AAAA records, CNAME verification, and SSL/TLS encryption modes.' 4 | --- 5 | 6 | # Speedrun: Connecting Your Fly.io App to a Custom Domain with Cloudflare Proxy 7 | 8 | Custom domains on your Fly.io app with Cloudflare in front can be a little complex because you must validate the domain on Fly.io BEFORE turning on Cloudflare proxying. Follow these steps. 9 | 10 | ## 1. Create the Fly.io App 11 | 12 | - Start by deploying your app on [Fly.io](https://fly.io/). Follow the standard process to get your app up and running. 13 | 14 | ## 2. Register Your Domain 15 | 16 | - If you haven't already, register your domain. It's often convenient to register it through [Cloudflare](https://cloudflare.com), which will also handle your DNS and proxying needs. 17 | 18 | ## 3. Configure DNS in Cloudflare 19 | 20 | - In Cloudflare's DNS settings, add **A** and **AAAA** records pointing to your Fly.io app's public IPv4 and IPv6 addresses. 21 | - **Important:** Turn off proxying (the orange cloud icon) for these records. This ensures that the Fly.io app can be accessed directly. 22 | 23 | ## 4. Add a Certificate in Fly.io 24 | 25 | - In your Fly.io dashboard, add an SSL certificate for your custom domain. 26 | - Since proxying is turned off, Fly.io should be able to validate the certificate immediately. Your app should now respond on your custom domain, but it's not yet proxied through Cloudflare. 27 | 28 | ## 5. Verify Domain Ownership and Proxying 29 | 30 | - From the Fly.io certificate area, add the **CNAME** record required for domain ownership verification. 31 | - **Important:** Turn off proxying for the CNAME record as well. Fly.io needs to verify ownership whenever the SSL certificate is renewed, which requires direct access. 32 | - Go back to Fly.io, check the certificate, and ensure domain ownership verification is successful. 33 | 34 | ## 6. Turn On Proxying in Cloudflare 35 | 36 | - Once everything is verified and working, return to Cloudflare and turn on proxying (enable the orange cloud) for your A and AAAA records. 37 | - In Cloudflare’s **SSL/TLS** settings, set the encryption mode to **Full** (not Full Strict) to ensure proper SSL handshakes between Cloudflare and Fly.io. 38 | 39 | ## 7. Test Your Setup 40 | 41 | - Finally, browse to your new domain to confirm everything is working as expected with Cloudflare proxying enabled. 42 | 43 | You now have a fully functioning Fly.io app served through a custom domain with Cloudflare as the proxy! 44 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/custom-domain-pockethost.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Speedrun: Setting Up a Custom Domain on PocketHost' 3 | description: "Configure DNS CNAME records, verify domain ownership via TXT records, and enable custom domains on PocketHost Pro. Uses Cloudflare's CNAME flattening for root domain support without www prefix." 4 | --- 5 | 6 | # Speedrun: Setting Up a Custom Domain on PocketHost 7 | 8 | Custom domains are a **Pro feature** on PocketHost, which also unlocks unlimited projects and domains—a great deal if you plan to manage multiple projects. 9 | 10 | ## 1. Add the Custom Domain in PocketHost 11 | 12 | - Go to your PocketHost instance dashboard. 13 | - In the settings, add your custom domain. If you haven't upgraded yet, switch to the Pro plan to enable this feature. 14 | 15 | ## 2. Configure DNS with Your Provider 16 | 17 | - Add a **CNAME** record pointing to your PocketHost instance using your DNS provider. 18 | - **Recommendation:** Use [Cloudflare](https://cloudflare.com) to manage your DNS, as it supports **CNAME flattening**. This allows you to CNAME directly to your root domain, avoiding the need to use `www`. 19 | 20 | ## 3. Verify Domain Ownership 21 | 22 | - After adding the CNAME, follow the instructions to contact **@noaxis** on Discord. He'll provide the **TXT record** needed for Cloudflare to verify your domain ownership. 23 | 24 | ## 4. Test Your Setup 25 | 26 | - Once everything is set up, test your configuration by browsing to your custom domain to ensure everything is working as expected. 27 | 28 | By following these steps, you can easily set up a custom domain for your PocketHost projects and take advantage of the Pro plan's features. 29 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-54-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-54-56.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-56-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-56-00.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-56-28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-56-28.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-56-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-56-56.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-07.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-19.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-27.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-57-57.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-58-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-58-27.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-58-37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-58-37.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-00.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-09.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-17.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-24.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-32.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-06-59-59.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-07-00-42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-07-00-42.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-15-28-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/google-oauth2/2025-02-08-15-28-44.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-04-47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-04-47.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-06-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-06-15.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-07-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-07-10.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-07-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-07-35.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-11-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-11-38.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-12-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-12-14.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-12-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-12-59.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-14-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-14-04.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-15-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-15-06.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-21-45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-21-45.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-24-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-24-55.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-25-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-25-14.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-25-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-25-59.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-39-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-39-27.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-51-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-51-48.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-56-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-56-56.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-57-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/gs-gmail/2024-09-08-19-57-35.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-03-06-20-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-03-06-20-55.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-03-07-00-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-03-07-00-59.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-20-29-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-20-29-10.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-20-30-52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-20-30-52.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-20-33-41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-20-33-41.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-28-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-28-33.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-32-26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-32-26.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-33-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-33-32.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-35-46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-35-46.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-38-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-38-12.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-38-51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-38-51.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-41-08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-41-08.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-42-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-42-35.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-45-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-45-05.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-48-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-48-53.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-53-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/(main)/docs/speedruns/ses/2024-09-08-22-53-02.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/static-content.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Serving Static Content in PocketPages 3 | description: Static content in PocketPages includes files like HTML, CSS, JavaScript, images, and documents that are served directly to clients without server-side processing. The Echo framework manages content type inference, streaming, and caching for these files. 4 | --- 5 | 6 | # Serving Static Content in PocketPages 7 | 8 | In PocketPages, serving static content is straightforward and integrated seamlessly into the framework. Any file that isn't an EJS template (`*.ejs`), doesn't begin with a `+`, and isn't in a `_private` directory is treated as a static file. These files are served directly by the underlying Echo framework, which handles content type inference, streaming, and other necessary details. 9 | 10 | ## What is Considered Static Content? 11 | 12 | Static content refers to files that are served directly to the client without server-side processing or dynamic generation. These files typically include: 13 | 14 | - HTML files (`*.html`) 15 | - CSS files (`*.css`) 16 | - JavaScript files (`*.js`) 17 | - Image files (`*.jpg`, `*.png`, etc.) 18 | - Font files (`*.woff`, `*.ttf`, etc.) 19 | - Other binary files or documents (e.g., PDFs, videos) 20 | 21 | For dynamic asset handling in your templates and pages, PocketPages provides the `asset()` function that helps generate correct URLs for your static assets. This function ensures your assets are properly referenced regardless of your application's base path configuration. 22 | 23 | For more details on managing and organizing your static assets effectively, see the [Asset Management Guide](/docs/guides/asset-management). 24 | 25 | ### Example Directory Structure 26 | 27 | ```plaintext 28 | my-pocketpages-app/ 29 | ├── pages/ 30 | │ ├── assets/ # Static assets directory 31 | │ │ ├── css/ 32 | │ │ │ ├── main.css 33 | │ │ │ └── components.css 34 | │ │ ├── js/ 35 | │ │ │ ├── app.js 36 | │ │ │ └── utils.js 37 | │ │ ├── images/ 38 | │ │ │ ├── logo.png 39 | │ │ │ └── hero.jpg 40 | │ │ └── fonts/ 41 | │ │ ├── OpenSans.woff2 42 | │ │ └── Roboto.woff2 43 | │ ├── documents/ # Static documents 44 | │ │ ├── terms.pdf 45 | │ │ └── privacy.pdf 46 | │ ├── layout.ejs # Layout template (not served as static) 47 | │ ├── +middleware.js # Middleware file (not served as static) 48 | │ ├── index.ejs # Dynamic page template 49 | │ └── about.html # Static HTML page 50 | ``` 51 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/structure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Recommended Project Structure 3 | description: Standard directory layout for PocketBase projects with hooks, migrations, and data storage, compatible with pockethost.io deployment and local development. 4 | --- 5 | 6 | # Recommended Project Structure 7 | 8 | This recommended project structure makes it easy to upload everything in `/pb_*` directly to your production PocketBase instance. It also mirrors the directory structure of [pockethost.io](https://pockethost.io) and PocketBase's sample directory names. 9 | 10 | ``` 11 | package.json 12 | pb_hooks/ 13 | pages/ 14 | +boot.pb.js 15 | index.ejs 16 | pb_migrations/ 17 | pb_data/ 18 | storage/ 19 | data.db 20 | logs.db 21 | ``` 22 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/toc.md: -------------------------------------------------------------------------------- 1 | # Quick Start 2 | 3 | - [Introduction](/docs/introduction) 4 | - [Quick Start Guide](/docs/quickstart) 5 | - [Project Setup](/docs/setup) 6 | - [TypeScript Support](/docs/typescript) 7 | 8 | # Core Concepts 9 | 10 | - [Pages](/docs/pages) 11 | 12 | - [File-based Routing](/docs/routing) 13 | - [Dynamic Routes](/docs/dynamic-routes) 14 | - [Route Parameters](/docs/params) 15 | 16 | - [Data Flow](/docs/data) 17 | 18 | - [Data Loading](/docs/data-loading) 19 | - [Form Handling](/docs/forms) 20 | - [Database Access](/docs/database) 21 | - [Authentication](/docs/auth) 22 | 23 | - [Templates](/docs/templates) 24 | - [EJS Syntax](/docs/ejs) 25 | - [Layouts](/docs/layouts) 26 | - [Partials](/docs/partials) 27 | - [Slots](/docs/slots) 28 | 29 | # Request Context 30 | 31 | - [Overview](/docs/context) 32 | - [Request Object](/docs/request) 33 | - [Response Object](/docs/response) 34 | - [Form Data](/docs/form-data) 35 | - [Parameters](/docs/params) 36 | - [Session](/docs/session) 37 | 38 | # Asset Pipeline 39 | 40 | - [Asset Management](/docs/assets) 41 | - [Static Files](/docs/static) 42 | - [Resource Resolution](/docs/resolve) 43 | - [Private Files](/docs/private) 44 | - [Meta Tags](/docs/meta) 45 | 46 | # PocketBase Integration 47 | 48 | - [JSVM Overview](/docs/jsvm) 49 | - [Database Access](/docs/db) 50 | - [Authentication](/docs/auth) 51 | - [File Storage](/docs/files) 52 | - [Collections](/docs/collections) 53 | 54 | # Utilities 55 | 56 | - [Environment Variables](/docs/env) 57 | - [Logging](/docs/logging) 58 | - [URL Handling](/docs/url) 59 | - [JSON Operations](/docs/json) 60 | - [Collection Helpers](/docs/collections) 61 | 62 | # Deployment 63 | 64 | - [Production Checklist](/docs/production) 65 | - [Environment Setup](/docs/environments) 66 | - [Caching Strategies](/docs/caching) 67 | - [Security Best Practices](/docs/security) 68 | - [Performance Tips](/docs/performance) 69 | 70 | # Integrations 71 | 72 | - [HTMX Guide](/docs/htmx) 73 | - [AlpineJS Guide](/docs/alpine) 74 | - [TailwindCSS](/docs/tailwind) 75 | - [Markdown Processing](/docs/markdown) 76 | 77 | # Recipes 78 | 79 | - [Authentication Flow](/docs/recipes/auth) 80 | - [File Uploads](/docs/recipes/uploads) 81 | - [API Endpoints](/docs/recipes/api) 82 | - [Custom Domains](/docs/recipes/domains) 83 | - [Email Setup](/docs/recipes/email) 84 | 85 | # Development 86 | 87 | - [IDE Setup](/docs/ide) 88 | - [Debugging](/docs/debug) 89 | - [Testing](/docs/testing) 90 | - [Type System](/docs/types) 91 | - [Contributing](/docs/contributing) 92 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/upgrading.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Upgrading PocketPages' 3 | description: 'Step-by-step instructions for upgrading PocketPages using tiged.' 4 | --- 5 | 6 | # Upgrading PocketPages 7 | 8 | PocketPages ships as an NPM package. Keeping it up to date ensures you have access to the latest features, improvements, and security patches. The upgrade process is simple: 9 | 10 | ```bash 11 | # Update PocketPages in your project 12 | npm i pocketpages@latest 13 | ``` 14 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(main)/docs/vscode.md: -------------------------------------------------------------------------------- 1 | # VS Code / Cursor Enhancements for PocketPages 2 | 3 | PocketPages includes some helpful VS Code configurations to improve your development experience. You can add these to your project by copying the `.vscode` directory from the PocketPages starter files: 4 | 5 | ```bash 6 | cp .vscode .vscode-backup 7 | cp -r ./node_modules/pocketpages/starters/vscode . 8 | ``` 9 | 10 | ## Features 11 | 12 | ### EJS Formatting 13 | 14 | The configuration includes [EJS Beautifier](https://marketplace.visualstudio.com/items?itemName=j69.ejs-beautify) as the default formatter for HTML files. This ensures your EJS templates stay properly formatted. 15 | 16 | To use: 17 | 18 | 1. Install the EJS Beautifier extension 19 | 2. Format your EJS files using `Alt+Shift+F` (Windows/Linux) or `Cmd+Shift+F` (Mac) 20 | 21 | ### Code Snippets 22 | 23 | Common PocketPages patterns are available as VS Code snippets: 24 | 25 | #### `ppld` 26 | 27 | Creates a new loader function with proper TypeScript types: 28 | 29 | ```javascript 30 | /** @type {import('pocketpages').PageDataLoaderFunc} */ 31 | module.exports = (api) => { 32 | const { dbg } = api 33 | 34 | dbg(new loader(), { api }) 35 | 36 | return {} 37 | } 38 | ``` 39 | 40 | #### `ppmd` 41 | 42 | Creates a new middleware function with proper TypeScript types: 43 | 44 | ```javascript 45 | /** @type {import('pocketpages').MiddlewareFunc} */ 46 | module.exports = (api) => { 47 | const { dbg } = api 48 | 49 | dbg(new loader(), { api }) 50 | 51 | return {} 52 | } 53 | ``` 54 | 55 | To use snippets: 56 | 57 | 1. Type the snippet prefix (e.g., `ppld`) 58 | 2. Press `Tab` to insert the snippet 59 | 3. Use `Tab` to move between the customizable fields 60 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(splash)/+layout.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 | <%- slot %> 4 |
-------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(splash)/+load.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('pocketpages').PageDataLoaderFunc} 3 | */ 4 | const load = (context) => { 5 | return { 6 | version: require(`${__hooks}/../package.json`).version, 7 | } 8 | } 9 | 10 | module.exports = load 11 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/(splash)/index.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

PocketPages

5 | 6 |
7 | Build faster with Server-Side web pages - no build chain or complicated 8 | tech stack required. 9 |
10 | 11 |
12 |
// pb_hooks/pages/index.ejs
13 | <%%= `Hello, PocketPages!` %>
14 |
15 | 16 | <%- include(`browser.ejs`, { content: `Hello, PocketPages!` }) %> 17 | 18 |
19 |
Quickstart
20 | <%- include(`quickstart.ejs`) %> 21 |
22 | Read the Docs 23 |
24 |
25 |
26 |
27 |
-------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/+config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | { 4 | name: `pocketpages-plugin-ejs`, 5 | extensions: ['.ejs', '.md'], 6 | debug: true, 7 | }, 8 | 'pocketpages-plugin-marked', 9 | ], 10 | } 11 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/_private/browser.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= `http://localhost:8090` %> 5 |
6 |
7 |
> 8 | <%- data.content||`This page is empty.`%> 9 |
10 |
-------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/_private/npm.ejs: -------------------------------------------------------------------------------- 1 |
2 | 10 |
11 |
<%= data.commands.bun %>
14 |
15 | 22 |
23 |
<%= data.commands.pnpm %>
26 |
27 | 34 |
35 |
<%= data.commands.yarn %>
38 |
39 | 46 |
47 |
<%= data.commands.npm %>
50 |
51 |
52 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/_private/quickstart.ejs: -------------------------------------------------------------------------------- 1 |
2 | Step 1: Copy the minimal starter. 3 |
4 | 5 | 6 |
7 |
npx tiged benallfree/pocketpages/packages/starters/minimal .
 8 | cd minimal
 9 | npm install
10 |
11 | 12 |
13 | Step 2: Run. 14 |
15 |
16 | 17 |
pocketbase --dir=minimal/pb_data --dev serve 
18 | 
19 |
-------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/_private/version.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/android-chrome-192x192.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/android-chrome-512x512.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/apple-touch-icon.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/assets/app.tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer components { 6 | .code-toolbar { 7 | @apply max-w-lg; 8 | } 9 | 10 | .toc { 11 | h1 { 12 | @apply text-lg; 13 | } 14 | ul { 15 | @apply pl-0; 16 | @apply list-none; 17 | @apply mt-0; 18 | } 19 | li, 20 | li a { 21 | @apply m-0 p-0; 22 | @apply text-sm; 23 | } 24 | } 25 | pre { 26 | background-color: #282c34 !important; 27 | } 28 | 29 | .mockup-browser { 30 | .mockup-browser-toolbar { 31 | .input { 32 | @apply ml-0 text-left w-full; 33 | } 34 | } 35 | } 36 | } 37 | 38 | @media (pointer: coarse) { 39 | /* Styles for touch devices */ 40 | div.code-toolbar > .toolbar { 41 | opacity: initial; 42 | } 43 | } 44 | 45 | @media (pointer: fine) { 46 | /* Styles for non-touch devices */ 47 | } 48 | 49 | div.code-toolbar { 50 | @apply w-full; 51 | } 52 | div.code-toolbar > .toolbar > .toolbar-item > a, 53 | div.code-toolbar > .toolbar > .toolbar-item > button, 54 | div.code-toolbar > .toolbar > .toolbar-item > span { 55 | @apply text-neutral-content bg-neutral-700 lowercase p-0.5 pb-1; 56 | } 57 | 58 | div.code-toolbar > .toolbar > .toolbar-item > a:hover, 59 | div.code-toolbar > .toolbar > .toolbar-item > a:focus, 60 | div.code-toolbar > .toolbar > .toolbar-item > button:hover, 61 | div.code-toolbar > .toolbar > .toolbar-item > button:focus, 62 | div.code-toolbar > .toolbar > .toolbar-item > span:hover, 63 | div.code-toolbar > .toolbar > .toolbar-item > span:focus { 64 | @apply bg-neutral-600 text-neutral-content; 65 | } 66 | 67 | div.code-toolbar > .toolbar > .toolbar-item > a[data-copy-state='copy-success'], 68 | div.code-toolbar 69 | > .toolbar 70 | > .toolbar-item 71 | > button[data-copy-state='copy-success'], 72 | div.code-toolbar 73 | > .toolbar 74 | > .toolbar-item 75 | > span[data-copy-state='copy-success'] { 76 | @apply text-success; 77 | } 78 | 79 | blockquote p:first-of-type::before { 80 | content: ''; 81 | } 82 | blockquote p:last-of-type::after { 83 | content: ''; 84 | } 85 | 86 | .prose.toc > ul > li > p { 87 | @apply p-0 m-0; 88 | } 89 | 90 | .prose.toc :where(li ul) { 91 | @apply ms-1; 92 | } 93 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/favicon-16x16.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/favicon-32x32.png -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/site/pb_hooks/pages/favicon.ico -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/otp.pb.js: -------------------------------------------------------------------------------- 1 | require(`pocketbase-otp`) 2 | -------------------------------------------------------------------------------- /packages/site/pb_hooks/pages/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /packages/site/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | -------------------------------------------------------------------------------- /packages/site/postcss.config.js: -------------------------------------------------------------------------------- 1 | // postcss.config.js 2 | module.exports = { 3 | plugins: { 4 | 'postcss-import': {}, 5 | tailwindcss: {}, 6 | autoprefixer: {}, 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /packages/site/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./pb_hooks/pages/**/*.{ejs,md}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | daisyui: { 8 | themes: ['cupcake'], 9 | }, 10 | plugins: [require('@tailwindcss/typography'), require('daisyui')], 11 | } 12 | -------------------------------------------------------------------------------- /packages/starters/.gitignore: -------------------------------------------------------------------------------- 1 | pb_data 2 | !pb_hooks 3 | bun.lockb 4 | node_modules -------------------------------------------------------------------------------- /packages/starters/auth/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-starter-auth 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-js-sdk@0.0.2-rc.5 10 | - pocketpages-plugin-auth@0.0.2-rc.5 11 | - pocketpages-plugin-ejs@0.0.2-rc.5 12 | - pocketpages@0.14.0-rc.5 13 | 14 | ## 0.0.2-rc.4 15 | 16 | ### Patch Changes 17 | 18 | - Testing 19 | - Updated dependencies 20 | - pocketpages-plugin-js-sdk@0.0.2-rc.4 21 | - pocketpages-plugin-auth@0.0.2-rc.4 22 | - pocketpages-plugin-ejs@0.0.2-rc.4 23 | - pocketpages@0.14.0-rc.4 24 | 25 | ## 0.0.2-rc.3 26 | 27 | ### Patch Changes 28 | 29 | - Publish testing 30 | - Updated dependencies 31 | - pocketpages-plugin-js-sdk@0.0.2-rc.3 32 | - pocketpages-plugin-auth@0.0.2-rc.3 33 | - pocketpages-plugin-ejs@0.0.2-rc.3 34 | - pocketpages@0.14.0-rc.3 35 | 36 | ## 0.0.2-rc.2 37 | 38 | ### Patch Changes 39 | 40 | - Publish testing 41 | - Updated dependencies 42 | - pocketpages-plugin-js-sdk@0.0.2-rc.2 43 | - pocketpages-plugin-auth@0.0.2-rc.2 44 | - pocketpages-plugin-ejs@0.0.2-rc.2 45 | - pocketpages@0.14.0-rc.2 46 | 47 | ## 0.0.2-rc.1 48 | 49 | ### Patch Changes 50 | 51 | - Publish testing 52 | - Updated dependencies 53 | - pocketpages-plugin-js-sdk@0.0.2-rc.1 54 | - pocketpages-plugin-auth@0.0.2-rc.1 55 | - pocketpages-plugin-ejs@0.0.2-rc.1 56 | - pocketpages@0.14.0-rc.1 57 | 58 | ## 0.0.2-rc.0 59 | 60 | ### Patch Changes 61 | 62 | - Updated dependencies 63 | - pocketpages@0.14.0-rc.0 64 | - pocketpages-plugin-auth@0.0.2-rc.0 65 | - pocketpages-plugin-ejs@0.0.2-rc.0 66 | - pocketpages-plugin-js-sdk@0.0.2-rc.0 67 | -------------------------------------------------------------------------------- /packages/starters/auth/README.md: -------------------------------------------------------------------------------- 1 | # MPA Auth Demo 2 | 3 | This starter kit shows how to do Multi Page App (MPA) auth using PocketPages. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npx tiged benallfree/pocketpages/packages/starters/auth . 9 | cd auth 10 | npm i 11 | pocketbase --dir=pb_data --dev serve 12 | bunx maildev 13 | ``` 14 | 15 | ## Notes 16 | 17 | ### Anonymous Login 18 | 19 | Anonymous login only works if Password login is enabled. 20 | 21 | ### Password Login 22 | 23 | Password login is enabled by default in PocketBase. 24 | 25 | ### OTP Login 26 | 27 | OTP login requires a verified email address. 28 | 29 | ### Using Password Reset 30 | 31 | Password Reset requires PocketBase's mail to be configured. The simplest localhost test is as follows: 32 | 33 | ``` 34 | http://localhost:3000/reset-password 35 | ``` 36 | 37 | ## App Configuration 38 | 39 | > This starter kit is already configured. In your own app, you'll need to update these settings 40 | 41 | **Step 1: Configure Mail Settings** 42 | 43 | In the PocketBase admin panel, navigate to `Settings > Mail Settings` and set the mail provider info to: 44 | 45 | Host: `localhost` 46 | Port: `1025` 47 | User: `(blank)` 48 | Password: `(blank)` 49 | 50 | **Step 2: Update Mail Template URLs** 51 | 52 | In the PocketBase admin panel, navigate to `Collections > Users > Edit > Options > Mail Templates` and update the URLs as follows: 53 | 54 | 1. Verification template: `{APP_URL}/auth/confirm/{TOKEN}/verification` 55 | 2. Reset Password template: `{APP_URL}/auth/confirm/{TOKEN}/password-reset` 56 | 3. Confirm email reset template: `{APP_URL}/auth/confirm/{TOKEN}/email-change` 57 | -------------------------------------------------------------------------------- /packages/starters/auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-starter-auth", 3 | "private": true, 4 | "version": "0.0.2", 5 | "dependencies": { 6 | "pocketpages": "workspace:^0.17.0", 7 | "pocketpages-plugin-auth": "workspace:^0.2.0", 8 | "pocketpages-plugin-js-sdk": "workspace:^0.1.0" 9 | }, 10 | "files": [ 11 | "pb_hooks", 12 | "*.md" 13 | ], 14 | "description": "A starter project for PocketPages with authentication", 15 | "author": { 16 | "name": "Ben Allfree", 17 | "github": "benallfree" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/benallfree/pocketpages/tree/main/packages/starters/auth" 22 | }, 23 | "keywords": [ 24 | "pocketbase", 25 | "pockethost", 26 | "sqlite", 27 | "pocketpages", 28 | "starter", 29 | "auth" 30 | ], 31 | "license": "MIT" 32 | } 33 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/+config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'pocketpages-plugin-auth', 4 | 'pocketpages-plugin-js-sdk', 5 | 'pocketpages-plugin-ejs', 6 | ], 7 | debug: true, 8 | } 9 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/+layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PocketPages MPA Auth 7 | 8 | 9 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 50 | <% if(params.__flash) { %> 51 |
52 | <%= params.__flash %> 53 |
54 | <% } %> 55 | <% if (auth && !auth.verified()) { %> 56 |
57 | Account not verified Resend Verification Email 58 |
59 | <% } %> 60 |
61 |
62 |
63 | <%- slot %> 64 |
65 | 66 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/account/+middleware.js: -------------------------------------------------------------------------------- 1 | module.exports = (api, next) => { 2 | const { auth, redirect } = api 3 | if (!auth) { 4 | return redirect('/auth/login', { 5 | message: 'You must be logged in to access this page', 6 | }) 7 | } 8 | next() 9 | } 10 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/account/change-email/index.ejs: -------------------------------------------------------------------------------- 1 | 8 | 9 |

Change Email

10 | 11 |
12 | Current email: <%= auth.get('email') %> 13 |
14 | 15 | 16 |
17 | 18 | 19 |
-------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/account/index.ejs: -------------------------------------------------------------------------------- 1 |

Account

2 |

Welcome, <%= auth.get('email') %>

3 |

Status: <%= auth.verified() ? 'verified' : 'unverified' %>

4 |
Account tools
5 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/confirm/[token]/email-change.ejs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/starters/auth/pb_hooks/pages/auth/confirm/[token]/email-change.ejs -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/confirm/[token]/password-reset.ejs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benallfree/pocketpages/273886e5f7c1fa07346bb6927b050fe03d7a4930/packages/starters/auth/pb_hooks/pages/auth/confirm/[token]/password-reset.ejs -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/confirm/[token]/verification.ejs: -------------------------------------------------------------------------------- 1 | 11 | Your account has been verified. -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/forgot/index.ejs: -------------------------------------------------------------------------------- 1 |

Forgot Password

2 | <% if (data.error) { %> 3 | <%= data.error %> 4 | <% } %> 5 |
6 | 7 | 8 | 9 |
-------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/_private/anonymous.ejs: -------------------------------------------------------------------------------- 1 | 22 | 23 |

Anonymous Login

24 | <% if (error) { %> 25 | <%= error %> 26 | <% } %> 27 | 28 | <% if (!methods.password.enabled) { %> 29 | Anonymous login is disabled. See README.md for details. 30 | <% } else { %> 31 |
32 | 33 | 34 |
35 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/_private/mfa.ejs: -------------------------------------------------------------------------------- 1 | 8 | 9 |

MFA Login

10 | <% if (error) { %> 11 | <%= error %> 12 | <% } %> 13 | <% if (!methods.mfa.enabled) { %> 14 | MFA Login is disabled. See README.md for details. 15 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/_private/oauth2.ejs: -------------------------------------------------------------------------------- 1 | 33 | 34 | 35 |

OAuth2 Login

36 | <% if (error) { %> 37 | <%= error %> 38 | <% } %> 39 | 40 | <% if (!methods.oauth2.enabled) { %> 41 | OAuth2 login is disabled. See README.md for details. 42 | <% } else {%> 43 | <% providers.forEach(provider => { %> 44 |
45 | 46 | 47 |
48 | <% }) %> 49 | <% if (providers.length === 0) { %> 50 | No OAuth2 providers enabled. See README.md for details. 51 | <% } %> 52 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/_private/otp.ejs: -------------------------------------------------------------------------------- 1 | 8 |

OTP Login

9 | <% if (error) { %> 10 | <%= error %> 11 | <% } %> 12 | <% if (!methods.otp.enabled) { %> 13 | OTP login is disabled. See README.md for details. 14 | <% } else { %> 15 |
16 | 17 | 18 | 19 | 20 |
21 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/_private/password.ejs: -------------------------------------------------------------------------------- 1 | 27 |

Password Login

28 | <% if (error) { %> 29 | <%= error %> 30 | <% } %> 31 | <% if (!methods.password.enabled) { %> 32 | Password login is disabled. See README.md for details. 33 | <% } else { %> 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | Forgot Password 42 |
43 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/index.ejs: -------------------------------------------------------------------------------- 1 |

Login

2 | 3 |
4 | <%- include('anonymous.ejs', ) %> 5 | 6 |
7 | <%- include('password.ejs',) %> 8 | 9 |
10 | <%- include('otp.ejs',) %> 11 | 12 |
13 | <%- include('oauth2.ejs',) %> 14 | 15 |
16 | <%- include('mfa.ejs',) %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/login/otp.ejs: -------------------------------------------------------------------------------- 1 | 36 | 37 | <%=error%> 38 | <% if (error) { %> 39 | <%= error %> 40 | <% } %> 41 | 42 |

We have sent you an OTP code

43 |

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

44 |
45 | 46 | 47 | 48 | 49 | 50 |
51 |
52 | 53 | 54 | Didn't receive an OTP code? 55 |
-------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/logout/index.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/oauth/confirm.ejs: -------------------------------------------------------------------------------- 1 | 17 | <% if (error) { %> 18 | 19 | <%=error%> 20 | 21 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/oauth/login.ejs: -------------------------------------------------------------------------------- 1 | 13 | <% if (error) { %> 14 | 15 | <%=error%> 16 | 17 | <% } %> -------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/auth/register/index.ejs: -------------------------------------------------------------------------------- 1 | 16 |

Register

17 | <% if (error) { %> 18 |
<%= error %>
19 | <% } %> 20 |
21 | 22 | 23 | 24 | 25 | 26 |
-------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pages/index.ejs: -------------------------------------------------------------------------------- 1 |
2 |

Home

3 |

Welcome to the PocketPages MPA Auth Demo

4 |
-------------------------------------------------------------------------------- /packages/starters/auth/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_migrations/1738509036_init.js: -------------------------------------------------------------------------------- 1 | /// 2 | migrate( 3 | (app) => { 4 | const settings = app.settings() 5 | const smtp = settings.smtp 6 | smtp.enabled = true 7 | smtp.host = 'localhost' 8 | smtp.port = 1025 9 | 10 | app.save(settings) 11 | 12 | const users = app.findCollectionByNameOrId('users') 13 | users.oauth2.enabled = true 14 | users.oauth2.providers = [ 15 | { 16 | provider: 'google', 17 | clientId: 18 | '901325610877-vbketlq7gapo2d2m1b8dq21033mm6b5e.apps.googleusercontent.com', 19 | clientSecret: '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', 20 | name: 'google', 21 | }, 22 | ] 23 | app.save(users) 24 | }, 25 | (app) => { 26 | // add down queries... 27 | } 28 | ) 29 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_migrations/1738527865_updated_users.js: -------------------------------------------------------------------------------- 1 | /// 2 | migrate((app) => { 3 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 4 | 5 | // update collection data 6 | unmarshal({ 7 | "verificationTemplate": { 8 | "body": "

Hello,

\n

Thank you for joining us at {APP_NAME}.

\n

Click on the button below to verify your email address.

\n

\n Verify\n

\n

\n Thanks,
\n {APP_NAME} team\n

" 9 | } 10 | }, collection) 11 | 12 | return app.save(collection) 13 | }, (app) => { 14 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 15 | 16 | // update collection data 17 | unmarshal({ 18 | "verificationTemplate": { 19 | "body": "

Hello,

\n

Thank you for joining us at {APP_NAME}.

\n

Click on the button below to verify your email address.

\n

\n Verify\n

\n

\n Thanks,
\n {APP_NAME} team\n

" 20 | } 21 | }, collection) 22 | 23 | return app.save(collection) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_migrations/1738527881_updated_users.js: -------------------------------------------------------------------------------- 1 | /// 2 | migrate((app) => { 3 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 4 | 5 | // update collection data 6 | unmarshal({ 7 | "resetPasswordTemplate": { 8 | "body": "

Hello,

\n

Click on the button below to reset your password.

\n

\n Reset password\n

\n

If you didn't ask to reset your password, you can ignore this email.

\n

\n Thanks,
\n {APP_NAME} team\n

" 9 | } 10 | }, collection) 11 | 12 | return app.save(collection) 13 | }, (app) => { 14 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 15 | 16 | // update collection data 17 | unmarshal({ 18 | "resetPasswordTemplate": { 19 | "body": "

Hello,

\n

Click on the button below to reset your password.

\n

\n Reset password\n

\n

If you didn't ask to reset your password, you can ignore this email.

\n

\n Thanks,
\n {APP_NAME} team\n

" 20 | } 21 | }, collection) 22 | 23 | return app.save(collection) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_migrations/1738527895_updated_users.js: -------------------------------------------------------------------------------- 1 | /// 2 | migrate((app) => { 3 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 4 | 5 | // update collection data 6 | unmarshal({ 7 | "confirmEmailChangeTemplate": { 8 | "body": "

Hello,

\n

Click on the button below to confirm your new email address.

\n

\n Confirm new email\n

\n

If you didn't ask to change your email address, you can ignore this email.

\n

\n Thanks,
\n {APP_NAME} team\n

" 9 | } 10 | }, collection) 11 | 12 | return app.save(collection) 13 | }, (app) => { 14 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 15 | 16 | // update collection data 17 | unmarshal({ 18 | "confirmEmailChangeTemplate": { 19 | "body": "

Hello,

\n

Click on the button below to confirm your new email address.

\n

\n Confirm new email\n

\n

If you didn't ask to change your email address, you can ignore this email.

\n

\n Thanks,
\n {APP_NAME} team\n

" 20 | } 21 | }, collection) 22 | 23 | return app.save(collection) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_migrations/1738530766_updated_users.js: -------------------------------------------------------------------------------- 1 | /// 2 | migrate((app) => { 3 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 4 | 5 | // update collection data 6 | unmarshal({ 7 | "otp": { 8 | "enabled": true 9 | } 10 | }, collection) 11 | 12 | return app.save(collection) 13 | }, (app) => { 14 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 15 | 16 | // update collection data 17 | unmarshal({ 18 | "otp": { 19 | "enabled": false 20 | } 21 | }, collection) 22 | 23 | return app.save(collection) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/starters/auth/pb_migrations/1738981268_updated_users.js: -------------------------------------------------------------------------------- 1 | /// 2 | migrate((app) => { 3 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 4 | 5 | // update collection data 6 | unmarshal({ 7 | "oauth2": { 8 | "enabled": true 9 | } 10 | }, collection) 11 | 12 | return app.save(collection) 13 | }, (app) => { 14 | const collection = app.findCollectionByNameOrId("_pb_users_auth_") 15 | 16 | // update collection data 17 | unmarshal({ 18 | "oauth2": { 19 | "enabled": false 20 | } 21 | }, collection) 22 | 23 | return app.save(collection) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-starter-daisyui-docs 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-marked@0.0.2-rc.5 10 | - pocketpages-plugin-ejs@0.0.2-rc.5 11 | - pocketpages@0.14.0-rc.5 12 | 13 | ## 0.0.2-rc.4 14 | 15 | ### Patch Changes 16 | 17 | - Testing 18 | - Updated dependencies 19 | - pocketpages-plugin-marked@0.0.2-rc.4 20 | - pocketpages-plugin-ejs@0.0.2-rc.4 21 | - pocketpages@0.14.0-rc.4 22 | 23 | ## 0.0.2-rc.3 24 | 25 | ### Patch Changes 26 | 27 | - Publish testing 28 | - Updated dependencies 29 | - pocketpages-plugin-marked@0.0.2-rc.3 30 | - pocketpages-plugin-ejs@0.0.2-rc.3 31 | - pocketpages@0.14.0-rc.3 32 | 33 | ## 0.0.2-rc.2 34 | 35 | ### Patch Changes 36 | 37 | - Publish testing 38 | - Updated dependencies 39 | - pocketpages-plugin-marked@0.0.2-rc.2 40 | - pocketpages-plugin-ejs@0.0.2-rc.2 41 | - pocketpages@0.14.0-rc.2 42 | 43 | ## 0.0.2-rc.1 44 | 45 | ### Patch Changes 46 | 47 | - Publish testing 48 | - Updated dependencies 49 | - pocketpages-plugin-marked@0.0.2-rc.1 50 | - pocketpages-plugin-ejs@0.0.2-rc.1 51 | - pocketpages@0.14.0-rc.1 52 | 53 | ## 0.0.2-rc.0 54 | 55 | ### Patch Changes 56 | 57 | - Updated dependencies 58 | - pocketpages@0.14.0-rc.0 59 | - pocketpages-plugin-ejs@0.0.2-rc.0 60 | - pocketpages-plugin-marked@0.0.2-rc.0 61 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/README.md: -------------------------------------------------------------------------------- 1 | # DaisyUI + Docs Starter Kit 2 | 3 | Demonstrates how to use Markdown pages by creating a docs site. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npx tiged benallfree/pocketpages/starters/daisyui-docs . 9 | cd daisyui-docs 10 | npm i 11 | npm run dev 12 | pocketbase serve --dir=pb_data --dev 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-starter-daisyui-docs", 3 | "private": true, 4 | "version": "0.0.2", 5 | "scripts": { 6 | "dev:css": "tailwindcss -i ./pb_hooks/pages/app.tailwind.css -o ./pb_hooks/pages/app.css --watch" 7 | }, 8 | "description": "A starter project for PocketPages with DaisyUI and Docs", 9 | "author": { 10 | "name": "Ben Allfree", 11 | "github": "benallfree" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/benallfree/pocketpages/tree/main/packages/starters/daisyui-docs" 16 | }, 17 | "keywords": [ 18 | "pocketpages", 19 | "starter", 20 | "daisyui", 21 | "docs" 22 | ], 23 | "license": "MIT", 24 | "devDependencies": { 25 | "@tailwindcss/typography": "^0.5.16", 26 | "daisyui": "^4.12.23", 27 | "tailwindcss": "^3.4.17" 28 | }, 29 | "dependencies": { 30 | "pocketpages": "workspace:^0.16.0", 31 | "pocketpages-plugin-marked": "workspace:^0.1.0" 32 | }, 33 | "files": [ 34 | "pb_hooks", 35 | "*.md" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/(main)/+layout.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 21 | <%- slot %> 22 |
23 |
24 | 25 | 29 |
30 |
-------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/(main)/docs/+layout.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 10 |
<%- slot %>
11 | 12 | 13 |
14 |
15 | 20 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/(main)/docs/_private/toc.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | - [Overview](/docs/overview) 4 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/(main)/docs/overview.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Edit this in `./pb_hooks/pages/(main)/docs/overview.md` 4 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/(splash)/+layout.ejs: -------------------------------------------------------------------------------- 1 |
<%- slot %>
-------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/(splash)/index.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

PocketPages

5 | 6 | 7 | Read the Docs 8 |
9 |
10 |
-------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/+config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | { name: 'pocketpages-plugin-ejs', extensions: ['.ejs', '.md'] }, 4 | 'pocketpages-plugin-marked', 5 | ], 6 | debug: true, 7 | } 8 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/+layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | PocketPages 8 | 9 | 10 | 11 | 12 | <%- slot%> 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pages/assets/app.tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer components { 6 | .code-toolbar { 7 | @apply max-w-lg; 8 | } 9 | 10 | .toc { 11 | h1 { 12 | @apply text-lg; 13 | } 14 | ul { 15 | @apply pl-0; 16 | @apply list-none; 17 | @apply mt-0; 18 | } 19 | li { 20 | @apply m-0 p-0; 21 | } 22 | } 23 | pre { 24 | background-color: #282c34 !important; 25 | } 26 | } 27 | 28 | @media (pointer: coarse) { 29 | /* Styles for touch devices */ 30 | div.code-toolbar > .toolbar { 31 | opacity: initial; 32 | } 33 | } 34 | 35 | @media (pointer: fine) { 36 | /* Styles for non-touch devices */ 37 | } 38 | 39 | div.code-toolbar > .toolbar > .toolbar-item > a, 40 | div.code-toolbar > .toolbar > .toolbar-item > button, 41 | div.code-toolbar > .toolbar > .toolbar-item > span { 42 | @apply text-neutral-content bg-neutral-700 lowercase p-0.5 pb-1; 43 | } 44 | 45 | div.code-toolbar > .toolbar > .toolbar-item > a:hover, 46 | div.code-toolbar > .toolbar > .toolbar-item > a:focus, 47 | div.code-toolbar > .toolbar > .toolbar-item > button:hover, 48 | div.code-toolbar > .toolbar > .toolbar-item > button:focus, 49 | div.code-toolbar > .toolbar > .toolbar-item > span:hover, 50 | div.code-toolbar > .toolbar > .toolbar-item > span:focus { 51 | @apply bg-neutral-600 text-neutral-content; 52 | } 53 | 54 | div.code-toolbar > .toolbar > .toolbar-item > a[data-copy-state='copy-success'], 55 | div.code-toolbar 56 | > .toolbar 57 | > .toolbar-item 58 | > button[data-copy-state='copy-success'], 59 | div.code-toolbar 60 | > .toolbar 61 | > .toolbar-item 62 | > span[data-copy-state='copy-success'] { 63 | @apply text-success; 64 | } 65 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | -------------------------------------------------------------------------------- /packages/starters/daisyui-docs/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./pb_hooks/pages/**/*.{ejs,md}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | daisyui: { 8 | themes: ['cupcake'], 9 | }, 10 | plugins: [require('@tailwindcss/typography'), require('daisyui')], 11 | } 12 | -------------------------------------------------------------------------------- /packages/starters/daisyui/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-starter-daisyui 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-ejs@0.0.2-rc.5 10 | - pocketpages@0.14.0-rc.5 11 | 12 | ## 0.0.2-rc.4 13 | 14 | ### Patch Changes 15 | 16 | - Testing 17 | - Updated dependencies 18 | - pocketpages-plugin-ejs@0.0.2-rc.4 19 | - pocketpages@0.14.0-rc.4 20 | 21 | ## 0.0.2-rc.3 22 | 23 | ### Patch Changes 24 | 25 | - Publish testing 26 | - Updated dependencies 27 | - pocketpages-plugin-ejs@0.0.2-rc.3 28 | - pocketpages@0.14.0-rc.3 29 | 30 | ## 0.0.2-rc.2 31 | 32 | ### Patch Changes 33 | 34 | - Publish testing 35 | - Updated dependencies 36 | - pocketpages-plugin-ejs@0.0.2-rc.2 37 | - pocketpages@0.14.0-rc.2 38 | 39 | ## 0.0.2-rc.1 40 | 41 | ### Patch Changes 42 | 43 | - Publish testing 44 | - Updated dependencies 45 | - pocketpages-plugin-ejs@0.0.2-rc.1 46 | - pocketpages@0.14.0-rc.1 47 | 48 | ## 0.0.2-rc.0 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies 53 | - pocketpages@0.14.0-rc.0 54 | - pocketpages-plugin-ejs@0.0.2-rc.0 55 | -------------------------------------------------------------------------------- /packages/starters/daisyui/README.md: -------------------------------------------------------------------------------- 1 | # DaisyUI PocketPages Starter Kit 2 | 3 | This setup provides a minimal **PocketPages** app integrated with **Tailwind CSS** and **DaisyUI**. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npx tiged benallfree/pocketpages/packages/starters/daisyui . 9 | cd daisyui 10 | npm i 11 | npm run dev 12 | pocketbase serve --dir=pb_data --dev 13 | ``` 14 | -------------------------------------------------------------------------------- /packages/starters/daisyui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-starter-daisyui", 3 | "private": true, 4 | "version": "0.0.2", 5 | "scripts": { 6 | "dev:css": "tailwindcss -i ./pb_hooks/pages/app.tailwind.css -o ./pb_hooks/pages/app.css --watch" 7 | }, 8 | "description": "A starter project for PocketPages with DaisyUI", 9 | "author": { 10 | "name": "Ben Allfree", 11 | "github": "benallfree" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/benallfree/pocketpages/tree/main/packages/starters/daisyui" 16 | }, 17 | "keywords": [ 18 | "pocketpages", 19 | "starter", 20 | "daisyui" 21 | ], 22 | "devDependencies": { 23 | "@tailwindcss/typography": "^0.5.16", 24 | "daisyui": "^4.12.23", 25 | "tailwindcss": "^3.4.17" 26 | }, 27 | "dependencies": { 28 | "pocketpages": "workspace:^0.16.0" 29 | }, 30 | "files": [ 31 | "pb_hooks", 32 | "*.md" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /packages/starters/daisyui/pb_hooks/pages/+layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PocketPages 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 44 |
<%- slot %>
45 |
46 |
47 | 52 | 56 |
57 |
58 | 59 | 60 | -------------------------------------------------------------------------------- /packages/starters/daisyui/pb_hooks/pages/app.tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /packages/starters/daisyui/pb_hooks/pages/index.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Daisy UI

5 |

The official PocketPages starter kit.

6 |
7 |
code .
8 |
9 |
10 | Ready to rumble with: 11 |
    12 |
  • Daisy UI
  • 13 |
14 |
15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /packages/starters/daisyui/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | -------------------------------------------------------------------------------- /packages/starters/daisyui/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ['./pb_hooks/pages/**/*.{ejs,md}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | daisyui: { 8 | themes: ['cupcake'], 9 | }, 10 | plugins: [require('@tailwindcss/typography'), require('daisyui')], 11 | } 12 | -------------------------------------------------------------------------------- /packages/starters/deploy-fly-ga/.github/workflows/fly-deploy.yml: -------------------------------------------------------------------------------- 1 | # See https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/ 2 | 3 | name: Fly Deploy 4 | on: 5 | push: 6 | branches: 7 | - main 8 | jobs: 9 | deploy: 10 | name: Deploy app 11 | runs-on: ubuntu-latest 12 | concurrency: deploy-group # optional: ensure only one action runs at a time 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: superfly/flyctl-actions/setup-flyctl@master 16 | - run: flyctl deploy --remote-only 17 | env: 18 | FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} 19 | -------------------------------------------------------------------------------- /packages/starters/deploy-fly-manual/.dockerignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | 177 | 178 | .ftp-deploy-sync-state.json 179 | pb_data 180 | -------------------------------------------------------------------------------- /packages/starters/deploy-fly-manual/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1 2 | 3 | # Adjust BUN_VERSION as desired 4 | ARG BUN_VERSION=1.1.26 5 | ARG NODE_VERSION=20 6 | FROM imbios/bun-node:${BUN_VERSION}-${NODE_VERSION}-alpine 7 | 8 | RUN apk add ca-certificates 9 | 10 | LABEL fly_launch_runtime="Bun" 11 | 12 | # Set production environment 13 | ENV NODE_ENV="production" 14 | 15 | WORKDIR /app-home 16 | COPY --link package.json . 17 | COPY --link bun.lockb . 18 | RUN bun i --production --verbose 19 | COPY --link . . 20 | 21 | # Start the server by default, this can be overwritten at runtime 22 | EXPOSE 8090 23 | CMD [ "bun", "serve", "--dev", "--dir=/pb_data", "--hooksDir=app" ] 24 | -------------------------------------------------------------------------------- /packages/starters/deploy-fly-manual/fly.toml: -------------------------------------------------------------------------------- 1 | # fly.toml app configuration file generated for pocketpages on 2024-08-30T11:11:13-07:00 2 | # 3 | # See https://fly.io/docs/reference/configuration/ for information about how to use this file. 4 | # 5 | 6 | app = 'pocketpages' 7 | primary_region = 'sjc' 8 | 9 | [build] 10 | 11 | [http_service] 12 | internal_port = 8090 13 | force_https = true 14 | auto_stop_machines = 'stop' 15 | auto_start_machines = true 16 | min_machines_running = 0 17 | processes = ['app'] 18 | 19 | [[vm]] 20 | memory = '1gb' 21 | cpu_kind = 'shared' 22 | cpus = 1 23 | 24 | [mounts] 25 | source = "pb_data" 26 | destination = "/pb_data" -------------------------------------------------------------------------------- /packages/starters/deploy-pockethost-ga/.github/workflows/deploy-pockethost.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | push: 4 | branches: 5 | - main 6 | name: Deploy website on push 7 | jobs: 8 | deploy: 9 | name: Deploy 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Get latest code 13 | uses: actions/checkout@v4 14 | 15 | - name: Sync files 16 | uses: SamKirkland/FTP-Deploy-Action@v4.3.5 17 | with: 18 | security: strict 19 | protocol: ftps 20 | server: ${{ secrets.ftp_server }} 21 | port: ${{ secrets.ftp_port }} 22 | username: ${{ secrets.ftp_username }} 23 | password: ${{ secrets.ftp_password }} 24 | local-dir: ./pb_hooks/ 25 | server-dir: ./${{ secrets.app_name }}/ 26 | log-level: verbose 27 | state-name: pb_hooks/.ftp-deploy-sync-state.json 28 | exclude: | 29 | **/.git* 30 | **/.git*/** 31 | **/node_modules/** 32 | .gitignore 33 | LICENSE 34 | README.md 35 | -------------------------------------------------------------------------------- /packages/starters/deploy-pockethost-manual/.env-deploy-pockethost: -------------------------------------------------------------------------------- 1 | PH_USERNAME=your-pockethost-email 2 | PH_PASSWORD=your-pockethost-password 3 | APP_NAME=your-pockethost-instance-name -------------------------------------------------------------------------------- /packages/starters/deploy-pockethost-manual/deploy-pockethost.ts: -------------------------------------------------------------------------------- 1 | import { deploy, excludeDefaults } from '@samkirkland/ftp-deploy' 2 | import 'dotenv/config' 3 | import env from 'env-var' 4 | 5 | async function deployMyCode() { 6 | console.log('🚚 Deploy started') 7 | await deploy({ 8 | server: 'ftp.sfo-1.pockethost.io', 9 | username: env.get('PH_USERNAME').required().asString(), 10 | password: env.get('PH_PASSWORD').required().asString(), 11 | 'local-dir': 'pb_hooks/', 12 | 'server-dir': `${env.get('APP_NAME').required().asString()}/`, 13 | 'state-name': 'pb_hooks/.ftp-deploy-sync-state.json', 14 | exclude: [...excludeDefaults], 15 | 'log-level': 'verbose', 16 | }) 17 | console.log('🚀 Deploy done!') 18 | } 19 | 20 | deployMyCode() 21 | -------------------------------------------------------------------------------- /packages/starters/htmx/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # pocketpages-starter-htmx 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-ejs@0.0.2-rc.5 10 | - pocketpages-plugin-sse@0.0.2-rc.5 11 | - pocketpages@0.14.0-rc.5 12 | 13 | ## 0.0.2-rc.4 14 | 15 | ### Patch Changes 16 | 17 | - Testing 18 | - Updated dependencies 19 | - pocketpages-plugin-ejs@0.0.2-rc.4 20 | - pocketpages-plugin-sse@0.0.2-rc.4 21 | - pocketpages@0.14.0-rc.4 22 | 23 | ## 0.0.2-rc.3 24 | 25 | ### Patch Changes 26 | 27 | - Publish testing 28 | - Updated dependencies 29 | - pocketpages-plugin-ejs@0.0.2-rc.3 30 | - pocketpages-plugin-sse@0.0.2-rc.3 31 | - pocketpages@0.14.0-rc.3 32 | 33 | ## 0.0.2-rc.2 34 | 35 | ### Patch Changes 36 | 37 | - Publish testing 38 | - Updated dependencies 39 | - pocketpages-plugin-ejs@0.0.2-rc.2 40 | - pocketpages-plugin-sse@0.0.2-rc.2 41 | - pocketpages@0.14.0-rc.2 42 | 43 | ## 0.0.2-rc.1 44 | 45 | ### Patch Changes 46 | 47 | - Publish testing 48 | - Updated dependencies 49 | - pocketpages-plugin-ejs@0.0.2-rc.1 50 | - pocketpages-plugin-sse@0.0.2-rc.1 51 | - pocketpages@0.14.0-rc.1 52 | 53 | ## 0.0.2-rc.0 54 | 55 | ### Patch Changes 56 | 57 | - Updated dependencies 58 | - pocketpages@0.14.0-rc.0 59 | - pocketpages-plugin-ejs@0.0.2-rc.0 60 | - pocketpages-plugin-sse@0.0.2-rc.0 61 | -------------------------------------------------------------------------------- /packages/starters/htmx/README.md: -------------------------------------------------------------------------------- 1 | # htmx Starter Kit 2 | 3 | This starter kit is based on the [htmx](https://htmx.org/) project. It is designed to help you get started with a minimal, responsive, and mobile-friendly website using PocketPages. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npx tiged benallfree/pocketpages/packages/starters/htmx . 9 | cd htmx 10 | npm i 11 | pocketbase serve --dir=pb_data --dev 12 | ``` 13 | -------------------------------------------------------------------------------- /packages/starters/htmx/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-starter-htmx", 3 | "version": "0.0.2", 4 | "private": true, 5 | "dependencies": { 6 | "pocketpages": "workspace:^0.16.0", 7 | "pocketpages-plugin-sse": "workspace:^0.1.0" 8 | }, 9 | "files": [ 10 | "pb_hooks", 11 | "*.md" 12 | ], 13 | "description": "A starter project for PocketPages with htmx", 14 | "author": { 15 | "name": "Ben Allfree", 16 | "github": "benallfree" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/benallfree/pocketpages/tree/main/packages/starters/htmx" 21 | }, 22 | "keywords": [ 23 | "pocketpages", 24 | "starter", 25 | "htmx" 26 | ], 27 | "license": "MIT" 28 | } 29 | -------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pages/(site)/+layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%=meta('title') || 'htmx starter kit'%> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | <%- slots.head %> 18 | 19 | 20 | 21 |
<%-slots.body || slot%>
22 | 23 | 24 | -------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pages/(site)/index.ejs: -------------------------------------------------------------------------------- 1 |

htmx realtime demo

2 |

This is a demo shows you how to use htmx to build a realtime app.

3 | 4 |
5 | 13 | 21 |
22 | 23 |
24 |
25 | 26 | 27 |
28 |
29 | 30 | 31 |
32 | Counter 33 |
-------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pages/+config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['pocketpages-plugin-ejs', 'pocketpages-plugin-sse'], 3 | } 4 | -------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pages/_private/count.ejs: -------------------------------------------------------------------------------- 1 | <%= store('count')||1 %> 2 | -------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pages/api/chat.ejs: -------------------------------------------------------------------------------- 1 | 7 |
8 | <%= message %> 9 |
-------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pages/api/count.ejs: -------------------------------------------------------------------------------- 1 | 6 | <%- include('count.ejs') %> -------------------------------------------------------------------------------- /packages/starters/htmx/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | -------------------------------------------------------------------------------- /packages/starters/minimal/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # minimal 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-ejs@0.0.2-rc.5 10 | - pocketpages@0.14.0-rc.5 11 | 12 | ## 0.0.2-rc.4 13 | 14 | ### Patch Changes 15 | 16 | - Testing 17 | - Updated dependencies 18 | - pocketpages-plugin-ejs@0.0.2-rc.4 19 | - pocketpages@0.14.0-rc.4 20 | 21 | ## 0.0.2-rc.3 22 | 23 | ### Patch Changes 24 | 25 | - Publish testing 26 | - Updated dependencies 27 | - pocketpages-plugin-ejs@0.0.2-rc.3 28 | - pocketpages@0.14.0-rc.3 29 | 30 | ## 0.0.2-rc.2 31 | 32 | ### Patch Changes 33 | 34 | - Publish testing 35 | - Updated dependencies 36 | - pocketpages-plugin-ejs@0.0.2-rc.2 37 | - pocketpages@0.14.0-rc.2 38 | 39 | ## 0.0.2-rc.1 40 | 41 | ### Patch Changes 42 | 43 | - Publish testing 44 | - Updated dependencies 45 | - pocketpages-plugin-ejs@0.0.2-rc.1 46 | - pocketpages@0.14.0-rc.1 47 | 48 | ## 0.0.2-rc.0 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies 53 | - pocketpages@0.14.0-rc.0 54 | - pocketpages-plugin-ejs@0.0.2-rc.0 55 | -------------------------------------------------------------------------------- /packages/starters/minimal/README.md: -------------------------------------------------------------------------------- 1 | # Minimal PocketPages Starter Kit 2 | 3 | ## Installation 4 | 5 | ```bash 6 | npx tiged benallfree/pocketpages/starters/minimal . 7 | cd minimal 8 | pocketbase --dir=pb_data --dev serve 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/starters/minimal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-starter-minimal", 3 | "private": true, 4 | "version": "0.0.2", 5 | "dependencies": { 6 | "pocketpages": "workspace:^0.16.0" 7 | }, 8 | "pockethost": { 9 | "instanceId": "minimal" 10 | }, 11 | "files": [ 12 | "pb_hooks", 13 | "*.md" 14 | ], 15 | "description": "A minimal starter project for PocketPages", 16 | "author": { 17 | "name": "Ben Allfree", 18 | "github": "benallfree" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/benallfree/pocketpages/tree/main/packages/starters/minimal" 23 | }, 24 | "keywords": [ 25 | "pocketpages", 26 | "starter", 27 | "minimal" 28 | ], 29 | "license": "MIT" 30 | } 31 | -------------------------------------------------------------------------------- /packages/starters/minimal/pb_hooks/pages/index.ejs: -------------------------------------------------------------------------------- 1 | <%= `Hello, PocketPages` %> 2 | -------------------------------------------------------------------------------- /packages/starters/minimal/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | -------------------------------------------------------------------------------- /packages/starters/mvp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # mvp 2 | 3 | ## 0.0.2-rc.5 4 | 5 | ### Patch Changes 6 | 7 | - te4st 8 | - Updated dependencies 9 | - pocketpages-plugin-ejs@0.0.2-rc.5 10 | - pocketpages@0.14.0-rc.5 11 | 12 | ## 0.0.2-rc.4 13 | 14 | ### Patch Changes 15 | 16 | - Testing 17 | - Updated dependencies 18 | - pocketpages-plugin-ejs@0.0.2-rc.4 19 | - pocketpages@0.14.0-rc.4 20 | 21 | ## 0.0.2-rc.3 22 | 23 | ### Patch Changes 24 | 25 | - Publish testing 26 | - Updated dependencies 27 | - pocketpages-plugin-ejs@0.0.2-rc.3 28 | - pocketpages@0.14.0-rc.3 29 | 30 | ## 0.0.2-rc.2 31 | 32 | ### Patch Changes 33 | 34 | - Publish testing 35 | - Updated dependencies 36 | - pocketpages-plugin-ejs@0.0.2-rc.2 37 | - pocketpages@0.14.0-rc.2 38 | 39 | ## 0.0.2-rc.1 40 | 41 | ### Patch Changes 42 | 43 | - Publish testing 44 | - Updated dependencies 45 | - pocketpages-plugin-ejs@0.0.2-rc.1 46 | - pocketpages@0.14.0-rc.1 47 | 48 | ## 0.0.2-rc.0 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies 53 | - pocketpages@0.14.0-rc.0 54 | - pocketpages-plugin-ejs@0.0.2-rc.0 55 | -------------------------------------------------------------------------------- /packages/starters/mvp/README.md: -------------------------------------------------------------------------------- 1 | # PocketPages Starter Kit for MVPs 2 | 3 | This starter kit is based on the [MVP.css](https://andybrewer.github.io/mvp/) project. It is designed to help you get started with a minimal, responsive, and mobile-friendly website using PocketPages. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npx tiged benallfree/pocketpages/starters/mvp . 9 | cd mvp 10 | pocketbase --dir=pb_data --dev serve 11 | ``` 12 | -------------------------------------------------------------------------------- /packages/starters/mvp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pocketpages-starter-mvp", 3 | "version": "0.0.2", 4 | "private": true, 5 | "description": "A minimal PocketBase project using the MVP.css framework", 6 | "author": { 7 | "name": "Ben Allfree", 8 | "github": "benallfree" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/benallfree/pocketpages/packages/starters/mvp" 13 | }, 14 | "dependencies": { 15 | "pocketpages": "workspace:^0.16.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/starters/mvp/pb_hooks/pages/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | My MVP Page 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

Welcome to PocketPages

15 |

This is a starter page using MVP.css.

16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/starters/mvp/pb_hooks/pocketpages.pb.js: -------------------------------------------------------------------------------- 1 | require('pocketpages') 2 | --------------------------------------------------------------------------------