Jump to content

Recommended Posts

Posted

Hi all,

I would like to propose a different format for https://processwire.com/api/ref/

The PW docs should be provided as markdown.

Reasons:

  • much easier to parse for machines
  • easier to feed as context to AI assistants

Most of popular modern frameworks / libraries (laravel, whole node ecosystem, etc.) have their docs in markdown nowadays. And I think it is exactly for the reasons mentioned.

Me and also others here like @wbmnfktr are having a hard time providing meaningful context to AI assistants in IDEs like Cursor, Windsurf etc. Once those assistants have good context, they do an excellent job with PW specific code. But currently there is a lot of manual effort required to provide this context.

ProcessWire would be more accessible to a wider range of users if development could be assisted by AI in an efficient way. 

I created markdown docs with python mkdocs at https://gebeer.github.io/mkdocs-processwire/ 
WARNING: this is in it's early stages and far from complete/perfect. It is merely for demonstration purposes atm and needs a lot of polish regarding structure, index pages for each class etc.

I am using a separate local repo for scraping the API docs and parsing them to markdown.

The whole process of scraping/parsing/deploying still involves manual steps (though those could be automated). And it needs to be repeated at least for every master release of PW.

So I would prefer if @ryan could produce the API docs in markdown in the first place.

Your feedback / opinions would be much appreciated.

Cheers

 

 

  • Like 9
  • Thanks 1
Posted

+1

Docs in markdown have been working great for me. All my module docs are markdown, so they are part of the repo (could be another repo as well, as images for example bloat the module code, which is not ideal).

I'm using RockFrontend's dom tools to enhance the markdown docs with some special features. That makes it possible to have working forms on my docs for RockForms, for example:

https://www.baumrock.com/en/processwire/modules/rockforms/docs/

## Working Example

In this example we will build the following form.

[rockforms=Quickstart]

Or another example is rendering code blocks and showing copy buttons. In markdown it's just a plain code example, on the HTML page it's an interactive element with nice labels etc:

qwtbBm6.png

## Example

This example shows how you can make every required field's label bold and add the note `optional` to every field that is not required. Note that NetteForms uses the terms `label` and `caption` for field labels.

[rockforms=Optional]

`label: /site/ready.php`
```php
$wire->addHookBefore(
  "RockForms::renderField",
  function (HookEvent $event) {
    // get the field that is rendered
    // in netteforms its called "control"
    $control = $event->arguments(1);

    // make required fields bold
    if ($control->isRequired()) {
      $control->getLabelPrototype()->addClass('uk-text-bold');
    }
    // add optional note if not required
    else {
      $renderer = $event->arguments(0);
      $label = $control->label->getText() . " <small>(optional)</small>";
      $control->setCaption($renderer->html($label));
    }
  }
);
```

 

  • Like 2
Posted

I think this is a good idea. While the docs are not in markdown, you could use https://context7.com/?q=processwire as an MCP Server for your coding assistant (like RooCode, Cline, Windsurf, Cursor, etc) for context. Context7 pulls up-to-date, version-specific documentation and code examples directly from the source. Paste accurate, relevant documentation directly into tools like Cursor, Claude, or any LLM.

Posted
5 hours ago, dotnetic said:

I think this is a good idea. While the docs are not in markdown, you could use https://context7.com/?q=processwire as an MCP Server for your coding assistant (like RooCode, Cline, Windsurf, Cursor, etc) for context. Context7 pulls up-to-date, version-specific documentation and code examples directly from the source. Paste accurate, relevant documentation directly into tools like Cursor, Claude, or any LLM.

Actually, Context7 was what made me start this thread. Someone has already submitted the PW repo to their scraper. But the resulting snippets are mostly garbage: https://context7.com/processwire/processwire

Now why is that?

image.png.8cf397f6b016ffbad9e51e7b328eb595.png

They do not scrape the very well documented PHP source files. If docs were in markdown, they would.

I tried the MCP and it didn't have context for simple things like WireHttp.

Does anyone know what tooling is currently used to create the PW API docs, phpDocumentor, phpDox, ApiGen or something different? 

  • Like 1
Posted
1 hour ago, interrobang said:

I think the docs are generated with a custom module: https://processwire.com/blog/posts/processwire-3.0.41-and-a-look-at-api-explorer/

Yup. From https://processwire.com/store/pro-dev-tools/api-explorer/

Could check and see what methods are hookable to potentially generate markdown instead of HTML. Current licensing seems to indicate that using it is solely for the purpose of the license holder though, so generating Markdown from it would be usable by the developer, but not shareable. Until or unless Ryan can consider if he would also not mind generating Markdown with the official docs, it may be a more practical option for those looking to do it now.

image.png.8e9a35292ec72d9d9c40a23667604d6e.png

  • Like 1
  • 8 months later...
Posted

I spent a few hours this morning making an MCP module for ProcessWire similar to Laravel Boost.  I'm going to call it Octopus.

In just 2-3 hours with Opus 4.5, I'm already what feels like being done with 90% of it.  I'm going to finish the remaining 90% (heh) as I work on various projects to actually test it.

I will have to figure out the best way on how to provide ProcessWire documentation to the MCP (hence why I'm on this thread), but even without it, Opus 4.5 is insanely good in following ProcessWire conventions, even with little context!  The hype is real.

Let me know if you have any questions or suggestions.

Screenshot attached.

octopus.png

  • Like 3
  • Thanks 1
Posted
11 hours ago, Jonathan Lahijani said:

I spent a few hours this morning making an MCP module for ProcessWire similar to Laravel Boost.  I'm going to call it Octopus.

In just 2-3 hours with Opus 4.5, I'm already what feels like being done with 90% of it.  I'm going to finish the remaining 90% (heh) as I work on various projects to actually test it.

I will have to figure out the best way on how to provide ProcessWire documentation to the MCP (hence why I'm on this thread), but even without it, Opus 4.5 is insanely good in following ProcessWire conventions, even with little context!  The hype is real.

Let me know if you have any questions or suggestions.

Screenshot attached.

 

Awesome! Yes, Opus 4.5 is really good now with PW. It also helps a lot that they have implemented the LSP in Claude Code directly. Honestly, at this stage I don't think we even need to feed docs to it anymore. Just instructions to explore the relevant API methods for a task itself  itself in the codebase.
Is there a specific reason why you implemented that as MCP and not as Skill? MCPs eat a lot of context. Depends on the implementation, of course. So dunno about how much context Octopus occupies.

ATM I have some basic instructions in CLAUDE.md that explain how to bootstrap PW and use the CLI through ddev for exploration, debugging, DB queries. That makes a big difference already. Opus is great at exploring stuff through the PHP CLI, either as one-liners or as script files for more complex stuff.
Here's my current instructions:

## PHP CLI Usage (ddev)

All PHP CLI commands **must run through ddev** to use the web container's PHP interpreter.

### Basic Commands
```bash
# Run PHP directly
ddev php script.php

# Check PHP version
ddev php --version

# Execute arbitrary command in web container
ddev exec php script.php

# Interactive shell in web container
ddev ssh
```

### ProcessWire Bootstrap

Bootstrap ProcessWire by including `./index.php` from project root. After include, full PW API is available (`$pages`, `$page`, `$config`, `$sanitizer`, etc.).

**All CLI script files must be placed in `./cli_scripts/`.**

**Inline script execution:**
```bash
ddev exec php -r "namespace ProcessWire; include('./index.php'); echo \$pages->count('template=product');"
```

**Run a PHP script:**
```bash
ddev php cli_scripts/myscript.php
```

**Example CLI script** (`cli_scripts/example.php`):
```php
<?php namespace ProcessWire;
include(__DIR__ . '/../index.php');

// PW API now available
$products = $pages->find('template=product');
foreach ($products as $p) {
    echo "{$p->id}: {$p->title}\n";
}
```

### PHP CLI Usage for Debugging & Information Gathering Examples

**One-liners** — use `ddev php -r` with functions API (`pages()`, `templates()`, `modules()`) to avoid bash `$` variable expansion. Local variables still need escaping (`\$t`). Prefix output with `PHP_EOL` to separate from RockMigrations log noise:
```bash
# Count pages by template
ddev php -r "namespace ProcessWire; include('./index.php'); echo PHP_EOL.'Products: '.pages()->count('template=product');"

# Check module status
ddev php -r "namespace ProcessWire; include('./index.php'); echo PHP_EOL.(modules()->isInstalled('ProcessShop') ? 'yes' : 'no');"

# List all templates (note \$t escaping for local var)
ddev php -r "namespace ProcessWire; include('./index.php'); foreach(templates() as \$t) echo \$t->name.PHP_EOL;"
```

**Script files** — preferred for complex queries, place in `./cli_scripts/`:
```php
// cli_scripts/inspect_fields.php
<?php namespace ProcessWire;
include(__DIR__ . '/../index.php');

$p = pages()->get('/');
print_r($p->getFields()->each('name'));
```
```bash
ddev php cli_scripts/inspect_fields.php
```

### TracyDebugger in CLI

**Works in CLI:**
- `d($var, $title)` — dumps to terminal using `print_r()` for arrays/objects
- `TD::dump()` / `TD::dumpBig()` — same behavior

**Does NOT work in CLI:**
- `bd()` / `barDump()` — requires browser debug bar

**Example:**
```php
<?php namespace ProcessWire;
include(__DIR__ . '/../index.php');

$page = pages()->get('/');
d($page, 'Home page');  // outputs to terminal
d($page->getFields()->each('name'), 'Fields');
```

### Direct Database Queries

Use `database()` (returns `WireDatabasePDO`, a PDO wrapper) for raw SQL queries:

```php
<?php namespace ProcessWire;
include(__DIR__ . '/../index.php');

// Prepared statement with named parameter
$query = database()->prepare("SELECT * FROM pages WHERE template = :tpl LIMIT 5");
$query->execute(['tpl' => 'product']);
$rows = $query->fetchAll(\PDO::FETCH_ASSOC);

// Simple query
$result = database()->query("SELECT COUNT(*) FROM pages");
echo $result->fetchColumn();
```

**Key methods:**
- `database()->prepare($sql)` — prepared statement, use `:param` placeholders
- `database()->query($sql)` — direct query (no params)
- `$query->execute(['param' => $value])` — bind and execute
- `$query->fetch(\PDO::FETCH_ASSOC)` — single row
- `$query->fetchAll(\PDO::FETCH_ASSOC)` — all rows
- `$query->fetchColumn()` — single value

**Example** (`cli_scripts/query_module_data.php`):
```php
<?php namespace ProcessWire;
include(__DIR__ . '/../index.php');

$query = database()->prepare("SELECT data FROM modules WHERE class = :class");
$query->execute(['class' => 'ProcessPageListerPro']);
$row = $query->fetch(\PDO::FETCH_ASSOC);
print_r(json_decode($row['data'], true));
```

### ddev Exec Options
- `ddev exec --dir /var/www/html/site <cmd>` — run from specific directory
- `ddev exec -s db <cmd>` — run in database container
- `ddev mysql` — MySQL client access

 

  • Like 3
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...