Skip to content

Instantly share code, notes, and snippets.

@VictorioBerra
Last active May 20, 2026 19:19
Show Gist options
  • Select an option

  • Save VictorioBerra/2a9fb22ce762be5728f8e00ed2e9b97f to your computer and use it in GitHub Desktop.

Select an option

Save VictorioBerra/2a9fb22ce762be5728f8e00ed2e9b97f to your computer and use it in GitHub Desktop.
Pocetbase and Pocketpages Instructions File

This project uses PocketBase, and a lesser known UI project called PocketPages.

Pocketbase has a way to extend it with the JSVM which runs inside GoJA. This lets us register endpoints, event hooks, cron jobs all in JS running inside Pocketbase managed GoJA (JSVM).

PocketPages builds on this by having a folder/file based routing system, and allows us to run JS in the JSVM in server-side html blocks in the pocketpages pages.

For example, PB lets you create JSVM scripts in pb_hooks, just name it whatever.pb.js. PP lets us create a page like index.ejs, gives us a <script server> block, and that code will run in the JSVM when the page is rendered. We have full access to the PB API, and a set of PP helpers.

IE for PB you can do $app.findRecordsByFilter where $app is the main interface to interact with your database.

Another example: for PB you can do request.event.findUploadedFiles() which is on the core requestEvent as seen here https://pocketbase.io/jsvm/interfaces/core.RequestEvent.html#findUploadedFiles this is a good example because it shows a combo of PP and PB working together, for example event is exposed by PP as a helper.

See detailed Pocketbase docs here if needed https://pocketbase.io/docs/llms-full.txt

Conventions

  • For new fields, try and always use daisyui fieldsets:

    <fieldset class="fieldset">
      <legend class="fieldset-legend">What is your name?</legend>
      <input type="text" class="input" placeholder="Type here" />
      <p class="label">Optional</p>
    </fieldset>
  • If the project has a _private/pocketbase-client.js make sure you always build clients and send requests using this tool. This fixes a major rate limit issue where server-side http calls come from localhost. You should see example usage of this helper in the projects README most likely, or in existing pages that have forms like login/register.
  • For server side logging, like in <script server> tags (or server-side .js files like middleware and pocketpages api files), you need to do info("blah") you cant do console.log server-side.
  • Dont use time.Now().UTC() always use types.NowDateTime() found in "github.com/pocketbase/pocketbase/tools/types" make sure to check for other time related functions in that package as well. This ensures we are using the same time source as the rest of PB and avoids issues with server timezone changes, DST, etc.
  • For EJS dont await pocketbase calls. The library was modified to be sync for server-side.
  • When suggesting names of relations in PocketPages, Do not suffix the column name with "id" unless you know you need to. If you do author.id = 'abc' in a PB rule or filter, it will trigger a join to the table. If you do author = 'abc' it simply compared the key directly.
  • For filters in PocketBase API calls, use the client.filter() helper to construct filters with parameters. This ensures proper escaping and avoids syntax errors. For example:
    client.collection('posts').getList(1, 10, {
      filter: client.filter('author.id = {:authorId} && published = true', { authorId: someAuthorId })
    })
  • When including a partial, you dont need to prefix with the _private folder. IE const config = resolve('config') Uses root /_private/config.js.
  • When using PB JSD server side (like in EJS <script server> ... or <% %> blocks, dont use .get when accessing members of the returned PB data from the client. Ie this is wrong form = client.collection('user_forms').getOne(params.id); form.get("form_name") that is because the data is serialized to JSON over the wire. Now if you're using $app in PocketPages or you are in golang, you need to unmarshal stuff and will have to use .get() or .getBool/String/Whatever() make sure to peek at the docs if you need this.
  • Include NPM packages from node_modules with require(), include _private JS helpers with resolve().
  • Very imports: avoid using $app in PocketPages server blocks if you can. We want to make sure we are triggering PocketBase API filters and hooks properly. Not only this but we do not want to couple PocketPages to Pocketbase internals if we can. This would allow for a much simpler UI port to a SPA or another framework if desired.
    <script server>
      // Get an authenticated client for the current request
      const client = pb({ request })
    
      // Use any PocketBase SDK method with the authenticated context
      const records = client.collection('posts').getFullList({
        sort: '-created',
        expand: 'author',
      })
    </script>
  • Dont use js hooks, always use GoLang hooks. The JSVM is not designed for high performance or long-running processes, so its best to use it for request handling and page rendering, and use Go hooks for things like cron jobs, event hooks, etc.
  • Do NOT use client.files.getURL() to build file/thumbnail URLs. The PB JS SDK's getURL relies on URLSearchParams (not fully supported in GoJA) and returns URLs with the server-side localhost origin. Instead, construct file URLs manually:
    <img src="/api/files/<%= record.collectionId %>/<%= record.id %>/<%= record.file %>?thumb=150x150" />
    For a helper function pattern:
    function thumbUrl(record, thumb) {
      return '/api/files/' + record.collectionId + '/' + record.id + '/' + record.file + '?thumb=' + thumb
    }
  • Cron expressions are evaluated in UTC by PocketBase's scheduler (robfig/cron).
    • 5:05 UTC = 00:05 CDT (UTC-5) / 23:05 CST (UTC-6 previous day).
    • Adjust this value if the server timezone changes.
  • PocketPages has a global url() function. This is powered by https://www.npmjs.com/package/url-parse under the hood, the parse() function of that lib is called, which returns the common Node.js interface. These properties are available to you (via url-parse docs):

    function of that lib is called, which returns the common Node.js interface. These properties are available to you:
    protocol: The protocol scheme of the URL (e.g. http:).
    slashes: A boolean which indicates whether the protocol is followed by two forward slashes (//).
    auth: Authentication information portion (e.g. username:password).
    username: Username of basic authentication.
    password: Password of basic authentication.
    host: Host name with port number. The hostname might be invalid.
    hostname: Host name without port number. This might be an invalid hostname.
    port: Optional port number.
    pathname: URL path.
    query: Parsed object containing query string, unless parsing is set to false.
    hash: The "fragment" portion of the URL including the pound-sign (#).
    href: The full URL.
    origin: The origin of the URL.
    
    • One major thing to note is that PocketPages attempots to JSON.parsew every single property value in query. So passing JSON in query strings becomes easier to process downstream.

PocketPages

See PocketPages LLM docs here: https://github.com/benallfree/pocketpages/blob/main/llms.txt

@benallfree

Copy link
Copy Markdown

I think there is a new SKILLS.md format that all the AI agents are using. Can you check into it further?

https://www.youtube.com/watch?v=5G8xUYXdWFs&t=3s

@VictorioBerra

Copy link
Copy Markdown
Author

I have built skills for Github Copilot CLI, this could be converted to a skill quite easily.

But the thing to remember is a skill is used to give the agent some sort of ability to perform a task. They can contain scripts and things like that.

For this to be a skill, id almost have to re-write it to gear towards creating a new PocketPage page, or partial or something.

Right now, this more serves as both a PP and PB list of gotchas and issues I have seen my LLM run into while asking for simple things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment