Skip to content
Developer docs

Prompts for building with AI

13 min read

Copy a prompt, replace the parts in [SQUARE BRACKETS], and paste it into your AI assistant. Each one tells the AI to follow the Basehim rules, state its assumptions, and finish with a checklist you can verify.

Before any of these, give your AI the AI context for Basehim development: paste it as your first message, put it in your coding agent's project instructions, or tell the AI to read that page. The prompts below assume it has. New to this? Read Build with AI first.

Tips that make every prompt work better

  • Be specific about people. "Editors can approve, subscribers can only see their own" gives the AI your capabilities and ownership rules.
  • Say what is stored and for how long. That decides tables, settings, permissions and what uninstall removes.
  • One feature per conversation. Build the core, test it, then ask for the next piece with the current files attached.
  • Paste real errors. The text from Apps → Report or Apps → Logs is worth more than a description of the problem.
  • Never paste secrets. No .env, passwords or API keys. The AI never needs them.

Start a session

Use this once, at the start, after pasting the context.

You are my Basehim development assistant. Follow the Basehim development context I gave you
(https://www.basehim.com/docs/ai-context) for everything you write. If something isn't covered
there, say so and point me to the right page under https://www.basehim.com/docs instead of guessing.

About me: [e.g. "I can edit files and upload ZIPs but I don't write PHP" / "I'm a PHP developer new to Basehim"].
My site runs Basehim [VERSION, from Admin → Updates] on [shared hosting / VPS / local].

Reply "Ready" and wait for my first request.

Build a new app

Build a Basehim app.

Name: [App name]
Slug: [app-slug]
Developer: [Your name], [https://your-site.example]

What it does, in plain words:
[2-5 sentences. Example: "Lets visitors book a 30-minute call. The site owner sets available
time slots. Visitors pick a slot and enter name and email. The owner sees bookings in the admin
and gets an email for each new one."]

Who uses it:
- Administrators: [what they can do]
- [Editors / members / visitors]: [what they can do, and what they must NOT see or change]

What it stores: [e.g. "bookings: name, email, slot, status; settings: slot length, notification email"]
Public pages or endpoints: [none / list them, e.g. "/book" page in the theme]
Background work: [none / e.g. "send a reminder 24 hours before each booking"]
Must work without: [e.g. "any outside service" / "a real cron job"]

Requirements:
- Follow every rule in the context: boot() registers only, $this->ajax() for browser calls,
  site() for public routes, bound SQL, escaped output, capability and ownership checks.
- Declare the minimum permissions, each with a plain reason.
- Admin screens use the bh-* components, bhConfirm and bhToast.
- Tables created in onActivate(), removed in onUninstall() with settings and private files.
- requires.basehim set to the lowest version that has every API you use.

Deliver: the folder tree, every file complete, how to ZIP and install it, how to test each
feature by hand, and the checklist from the context with each line confirmed or flagged.
Before writing code, list any assumptions you are making in one short list.

Add an admin screen and settings

Add an admin settings screen to my Basehim app. Current files are attached/pasted below.

Menu label: [e.g. "Bookings → Settings"]
Settings:
- [setting name]: [type: text / number / on-off / select (options) / email / URL], default [value], [help text]
- [...]
Who may change them: [administrators only / a capability, e.g. manage_options]

Requirements:
- Use adminGet() for the screen and an $this->ajax() action (with an input schema) to save,
  or adminPost() with a manual CSRF check. Explain which you chose and why.
- Store values with $this->setSetting(); validate each one on the server.
- Build the screen with bh-card, bh-label, bh-input / bh-select / bh-switch, bh-help and one
  bh-btn--primary "Save changes"; show the result with bhToast; busy state with bhBusy.
- Mask any API key field: never print a saved secret back in full.

Show only the files you change or add, complete, and the checklist lines that apply.

[PASTE CURRENT FILES]

Add an AJAX action

Add a browser action to my Basehim app.

What it does: [e.g. "marks a booking as confirmed when the admin clicks Confirm in the list"]
Called from: [admin screen / public page]
Who may call it: [capability] and only for [records they own / any record]
Input: [field: type and limits, e.g. booking_id: required int min 1]
Returns: [e.g. {confirmed: true, status: "confirmed"}]
Changes something? [yes / no]  Can it be double-clicked safely? [yes / needs idempotency]

Requirements:
- Register with $this->ajax() in boot(): capability, area (if it serves an admin screen),
  full input schema, a sensible rate_limit; methods GET only if it changes nothing.
- In the handler: load the record, check ownership, throw AjaxException::notFound() /
  forbidden() / invalid() for user-facing errors, return an array.
- JavaScript: Basehim.ajax.request(), bhBusy on the button, bhToast on success and error.

Show the PHP and JS changes complete, and how to test it, including calling it as a user
who should be refused.

[PASTE CURRENT FILES]

Add a public page or endpoint

Add a public page to my Basehim app.

URL: [e.g. /book or /events/{slug}]
Shows: [what the visitor sees]
Form or action on it: [none / describe; who may submit: anyone / signed-in users]
Should it look like the rest of the site? [yes: render it in the active theme]

Requirements:
- Register with $this->router()->site() in boot(), with 'where' constraints for parameters
  and a 'name'. Use 'auth' / 'can' if only some people may use it.
- Render with \App\Core\Http\SitePage::view() so the theme's header, footer and SEO apply.
- Form posts go to a site() POST route (CSRF on, 'rate' set) or a public AJAX action with a
  low rate limit; validate every field; escape everything printed.
- Don't use a path core reserves (/ajax, /api/v1, /mcp, /oauth, /uploads, /content, /storage).

Deliver the changed and new files complete, and how to test it signed out and signed in.

[PASTE CURRENT FILES]

Add a dashboard widget

Add a dashboard widget to my Basehim app.

Title: [e.g. "Bookings this week"]
Shows: [numbers / a list / a table / a chart / a status], e.g. [describe]
Who should see it: [people who can use the app (default) / every signed-in user / a capability]
How fresh: [cached for N minutes / refreshed every N minutes / on load only]
When there's nothing to show: [empty message and optional button]
When a needed service isn't set up: [message]

Requirements:
- registerWidget() with 'surfaces' => ['dashboard'] and a native view (stat, list, table,
  chart, feed or status), not html.
- The data provider does one cheap query (no N+1) and throws WidgetUnavailable for expected
  "not set up" states.
- Set 'capability' explicitly and a 'cache' if the query is expensive.

Deliver the changed files complete.

[PASTE CURRENT FILES]

Add a scheduled task or import

Add background work to my Basehim app.

What it does: [e.g. "imports items from https://example.com/feed.json into posts, tagging them 'Imported'"]
How often: [every N minutes / hourly / daily]
How much per run: [e.g. "at most 20 items"]
If the same item arrives twice: [skip / update]
If the remote service is down: [skip this run and log a warning]

Requirements:
- Register with $this->api()->schedule() in boot(); the handler works in a small batch,
  saves a cursor with autoload=false, and is safe to run twice (no duplicate posts or emails).
- Outbound HTTP through $this->api()->http() with timeout(); create content through
  $this->api(), never raw SQL on core tables.
- Declare the permissions it needs (e.g. schedule, http.outbound, posts.write) with reasons.
- Explain that tasks run after page visits unless a real cron job is set (Admin → System).

Deliver the changed files complete, and how to trigger and check a run.

[PASTE CURRENT FILES]

Accept file uploads

Let users upload files in my Basehim app (Basehim 1.2.87 or later).

What is uploaded: [e.g. "a CSV of contacts" / "product photos"]
Allowed types and size: [e.g. csv, up to 5 MB / jpg and png, up to 10 MB]
Who may upload: [capability]
Where it goes: [private storage for processing / the media library]
What happens next: [e.g. "parse rows and show a preview before importing"]

Requirements:
- An AJAX action with 'files' (narrowest types, real max_size, mimes), not a custom route.
- Private files: $ctx->file('file')->moveTo($this->appStorageDir('[folder]'), [a name you choose]).
  Media: $this->api()->media()->fromUpload(...) and show lastError() when it returns null.
- Never build a path from the uploaded file's name; never execute or include uploaded content.
- Browser: Basehim.ajax.upload() with a progress bar; errors with bhToast.
- Remove anything stored in appStorageDir() on uninstall.

Deliver the changed files complete.

[PASTE CURRENT FILES]

Give your app an MCP tool

Give my Basehim app a tool that AI assistants can call through the site's MCP server.

Tool name: [app_slug_with_underscores_action]
What it does: [e.g. "lists upcoming bookings between two dates"]
Read-only or does it change data? [read-only / changes: describe]
Inputs: [name: type, limits]
Which API key scope should be required: [e.g. posts:read]

Requirements:
- Add it with the mcp.tools filter and answer on mcp.call.{name}; pass the argument count
  (addFilter(..., 10, 2)) because both callbacks take two arguments.
- Validate every argument in the call handler; return an array.
- Reuse the same service method the admin screen uses.
- Write the description for a model: what it does, what it returns, whether it changes anything.

Deliver the changed files complete and an example request an assistant would make.

[PASTE CURRENT FILES]

Build a theme

Build a Basehim theme.

Name: [Theme name]   Slug: [theme-slug]   Author: [Your name]
Style: [e.g. "clean magazine layout, white background, one accent colour, large serif headings"]
Home page: [e.g. "featured post on top, then a 3-column grid of recent posts"]
Single post: [e.g. "centered column, author box, comments"]
Menus: [e.g. primary in the header, footer menu]
Sidebar / widget areas: [none / list]
Customizer options: [e.g. accent colour, content width, show author on posts (on/off), logo]

Requirements:
- All six templates (index, single, page, archive, search, 404) plus partials; theme.json
  with menu_locations, widget_areas and customizer.
- bh_head() and bh_footer() both present; no SEO or social tags of my own (core prints them).
- Colour/size options used as CSS variables with fallbacks (var(--bh-accent, #...)).
- Dates with bh_date() / bh_time_tag(), never date(strtotime()).
- Pagination from $meta with ?page=N links that keep other query parameters.
- Responsive, accessible (labels, focus states, contrast), no build step, no CDN required.

Deliver the folder tree, every file complete, how to ZIP and install it, and the theme lines
of the checklist from the context.

Turn an HTML design into a theme

Turn this static HTML design into a Basehim theme.

Name: [Theme name]   Slug: [theme-slug]
Which page in the design is: home = [file], post = [file], page = [file] (others: derive from these)
Keep: [e.g. "the exact header and footer, colours and fonts"]
Make editable in the Customizer: [e.g. "accent colour, hero heading, footer text"]

Requirements:
- Split the design into templates and partials; replace sample content with the real template
  variables ($posts, $post, $meta, $primary_menu ...); menus via menu_html().
- Move CSS and JS into assets/; load them with versioned URLs.
- Remove any <meta name="description">, canonical, og:* or JSON-LD from the design (core prints them).
- Keep every template variable escaped except $post['content'].

[PASTE THE HTML, CSS AND JS]

Review an app or theme

Use this on anything an AI wrote for you, or on your own code, before you install it on a real site.

Review this Basehim [app / theme] as a strict senior reviewer. Use the Basehim development
context (https://www.basehim.com/docs/ai-context) as the rulebook.

Check, and for each problem give the file, the line, why it matters, and the fix:
1. Will it load? Reserved base-class method names, syntax, namespace not App\, slug = folder,
   no code that runs on include, hook callbacks with more than one parameter pass the count.
2. Security: capability and ownership on every route/action/widget; CSRF; input validation;
   output escaping; SQL injection; paths built from input; uploads; secrets in code, logs or
   responses; outbound HTTP timeouts; anything the scanner would flag.
3. Permissions: everything used is declared, nothing extra, reasons given, degrades if refused.
4. Data and lifecycle: tables via $this->table(), indexes, idempotent onActivate/onUpgrade,
   complete onUninstall, transactions, race conditions.
5. Performance: work in boot(), N+1 queries, unbounded loops, autoloaded large settings.
6. Basehim conventions: ajax() not custom JSON routes, site() not get()/post(), api() not raw
   SQL on core tables, bh-* components, bhConfirm/bhToast. (Themes: six templates, bh_head and
   bh_footer, no SEO tags, bh_date.)

List problems by severity (must fix / should fix / nice to have), then give corrected files for
every "must fix". Don't rewrite things that are already fine.

[PASTE ALL FILES]

Fix an app that was switched off

My Basehim app was switched off. Here is the report from Apps → [app] → Report and the last
lines from Apps → Logs:

[PASTE THE REPORT AND LOG LINES]

Explain in plain words what went wrong, then give the smallest fix (complete changed files).
Tell me how to confirm it: Apps → Report → "Check and reactivate", and what to test after.

[PASTE THE APP'S FILES, OR AT LEAST THE FILES NAMED IN THE REPORT]

Write an upgrade and migration

I'm releasing version [NEW] of my Basehim app (sites have [OLD] or earlier).

What changed in the data: [e.g. "bookings get a 'status' column; the setting 'notify' becomes
'notify_email'"]
New permissions needed: [none / list with reasons]

Requirements:
- onUpgrade($from, $to) with one version_compare block per version, each checking before
  changing so it can run twice; large data changes moved to a batched scheduled task.
- Bump version in app.json and requires.basehim if new APIs are used.
- Write release notes for site owners (what's new, anything they must do, any new permission and why).

[PASTE CURRENT FILES]

Write release notes

Write release notes for version [VERSION] of my Basehim app "[NAME]" for site owners (not
developers). Plain language, short. Sections: New, Improved, Fixed, and "Before you update"
only if they must do something. Mention every new permission and why it's needed.

Changes:
[PASTE YOUR LIST OF CHANGES OR THE DIFF]

After the AI answers

  1. Read its assumptions. If one is wrong, correct it before testing anything.
  2. Install on a test site, never your live site first. Upload the ZIP, then Apps → your app → Report → Check again.
  3. Test as different people: an administrator, an editor, a subscriber, signed out.
  4. Run the review prompt in a fresh conversation. A second pass catches what the first missed.
  5. Read the permission window when you activate it. If the app asks for something you didn't expect, ask the AI why.

More in Build with AI and App development best practices.

Discussion

Leave a comment