Build my widget

Home / Prompt generator

PROMPT GENERATOR

Make a pixel art widget with your own AI assistant

Describe it, pick the look, copy the prompt. It carries the rules that keep the result pixel art instead of flat design with a thick border.

One sentence, the way you would say it to a person. Left empty, the prompt asks for the example above.

Palette

What this site uses. Blocky labels, terminal body text.

The grid everything snaps to.

The widget's own background, not your page's.

Smooth easing is the giveaway.

Include

Your prompt

Build me a countdown to a date I set, with a message that shows once it hits zero, as a single file Fugte widget.

VISUAL STYLE: pixel art, not "chunky UI". These are hard rules.
- Everything sits on a 4px grid: sizes, padding, gaps, outline widths, icon cells.
- No border-radius anywhere. No blurred shadows. No smooth gradient used as a surface.
- No clamp() on font sizes: pixel type at a fractional size stops being pixel type.
- Frames get notched corners. Draw the outline with four offset box-shadows (-4px 0, 4px 0, 0 -4px, 0 4px) instead of a border, so the corner is left empty and the outline steps. Give those elements a matching margin, because the shadows take no layout space and will otherwise overlap whatever sits next to them. This one change is most of the difference between pixel art and flat design with a thick outline.
- Icons are hand drawn pixel grids rendered as SVG rects with shape-rendering="crispEdges". Never an icon font, never emoji. Write each icon as an array of strings and render it as merged horizontal runs. 9x9 is enough for a playback control, 16x16 for anything with detail. Use fill="currentColor" so the pressed and disabled states need no second copy of the art.
- image-rendering: pixelated on every img, svg and canvas.
- -webkit-font-smoothing: none, so the type is not antialiased back into softness.
- Buttons press physically: a hard inset highlight along the top, shade underneath, and translateY on :active with no transition.
- The widget's own surface is the darkest colour in the palette, with light text. Give the widget its own opaque background: it will be embedded on a page whose colour it cannot know, so nothing may depend on what is behind it.
- Animation is stepped, never smooth. Use steps() timing on every transition, and drive JS animation with setInterval at 70 to 80ms rather than requestAnimationFrame. A low frame rate is period correct, not a compromise. Honour prefers-reduced-motion by ending in the finished state instead of animating to it.

PALETTE: Arcade Violet. Use these exactly, and no colours outside this list.
  #0d0722  page, the darkest tone
  #241546  raised surfaces and cards
  #f4ecd8  text, warm cream
  #6ee7ff  primary, anything you can act on
  #ffc447  accent and highlights
  #ff6b8a  alerts and the live indicator
  #08040f  outline, near black
Text goes in the tone marked for text. A tone marked primary, accent or mid is for
fills, outlines and icons: check the contrast ratio before setting text in it, because
several of these fall below 3:1 on their own page colour and are unreadable as type.
Expose every one as a Fugte colour setting so the look can be retuned without code.

TYPE: Press Start 2P for labels, buttons and headings. VT323 for body text.
Load both rather than only naming them, and expose both as font_picker settings.
VT323 has a small x-height, so set the body size around 18 to 21px, not 16px.

FEATURES
- Surfaces carry a checkerboard dither on the grid size above, built with a repeating conic-gradient rather than an image. Screens get scanlines on a 2px pitch from a repeating-linear-gradient. Both are ::before or ::after overlays with pointer-events: none, so the parent needs position: relative and the real children need a z-index above them.
- Any image the owner supplies is converted rather than framed: draw it to a canvas at about 40px on its longest side with imageSmoothingEnabled = false, posterise to 4 levels per channel (64 colours, which lands in the right era), then scale it back up with image-rendering: pixelated. Wrap the posterise step in try/catch, because getImageData throws on a cross-origin image, and let the downscale alone survive that failure.
- Sliders, ratings, meters and progress bars are rows of discrete blocks that fill one cell at a time, not smooth ranges. Each block is clickable and the row is keyboard operable with the arrow keys, with the current value exposed through aria-valuenow on a role=slider or role=progressbar element.
- The repeating content (list rows, cards, entries) is a Fugte block type rather than a fixed number of settings, so the owner can add, remove and reorder rows in the editor. Ship a preset containing 2 or 3 starter blocks so the widget is never empty on first load.

FUGTE RULES: read https://fugte.com/llms-build.txt and follow it exactly.
- One file, in this order: the markup fragment, an inline style block, an inline script block, then the schema in a hidden div. No doctype, html, head, body or link tags.
- Never style body, and never use vh or vw units. The embed measures body.scrollHeight, and a viewport unit makes it report the wrong height.
- Bind every setting as an inline CSS custom property on the root element.
- Every setting needs a default and must actually be used in the markup.
- Guard text-like settings with `!= blank` or a `| default:` filter.
- Repeating content uses blocks, with a preset holding 2 or 3 starter blocks.
- Add a fallback in the script: if the Liquid arrives unrendered (test the markup for `{{` or `{%`), swap in the schema defaults, so the file also previews correctly when it is opened directly in a browser.

VALIDATE your own output before you hand it over, and fix anything that fails:
- no border-radius, no blurred box-shadow, no clamp() on a font size
- no vh or vw units, and nothing styles body
- every icon is SVG rects, not a glyph and not an emoji
- every schema setting has a default and appears in the markup
- the script parses, and the widget renders when the file is opened directly

Then paste it into

These open the assistant, they do not carry the prompt. Every one of them cuts a long query string short, and a truncated rule list is how you get a flat widget back.

WHY THESE RULES

The four that do the work

Notched corners are the whole trick

A border follows the corner around. Four offset box-shadows do not, so the corner is left empty and the outline steps. Ask for "a pixel style border" and you get a 4px solid line, which reads as flat design. Ask for the four shadows and you get pixel art. The elements need a matching margin, because shadows take no layout space and will otherwise sit on top of whatever is beside them.

Icons are grids, rendered as rects

An icon font or an emoji is antialiased, sits on its own baseline, and ignores the grid. Writing each icon as rows of characters and rendering it as SVG rects with shape-rendering="crispEdges" keeps it on the same grid as everything else. Filling with currentColor means the pressed and disabled states inherit the button's colour rather than needing a second copy of the art.

Stepped motion, low frame rate

Smooth easing is the giveaway. steps() on transitions, and setInterval around 70 to 80ms for anything animated in script, rather than requestAnimationFrame. Twelve frames a second is period correct, not a compromise, and it costs less battery on a page that leaves a widget running.

Photos have to be converted, not framed

An unprocessed photo inside a pixel frame looks like a mistake. Downscaling it to about 40px on a canvas with smoothing off, posterising to four levels per channel, then scaling it back up turns it into real pixel art. The posterise step needs a try/catch, because reading pixels back from a cross-origin image throws and would otherwise take the whole widget down with it.

And one about the palette

Left to itself an assistant reaches for Game Boy green or NES primary blue, which is why every AI-made pixel widget looks like every other one. Naming the colours is the fix. The five above are picked to avoid both, and the prompt asks for them to be exposed as settings so the look can be retuned in the editor rather than in code.

AFTER THE ASSISTANT ANSWERS

Three steps to a widget you can still edit

01

Check it against the list

The prompt ends with a checklist, so ask the assistant to run it. No border-radius, no blurred shadows, no viewport units, nothing styling body, and every schema setting actually used in the markup.

02

Paste the code into Fugte

Start a widget from existing code. Fugte splits the file, reads the schema the prompt asked for, and turns the marked parts into form controls: text, dates, colours, images.

03

Publish and paste one line

The embed line works anywhere an iframe is allowed. Editing the widget later updates it everywhere it sits, with no change to the host page.

QUESTIONS

About the prompt

Which AI assistant does this prompt work with?

Any of them. The prompt is plain text with no assistant-specific syntax, and it has been written to state the mechanism rather than the adjective, which is what makes the result consistent between ChatGPT, Claude, Gemini and Copilot. Paste it into whichever one you already pay for or already have open.

Why does the prompt tell the assistant to read fugte.com/llms-build.txt?

That file is the format contract for a Fugte widget: one file, an inline style block, an inline script block, and a schema that declares which parts stay editable. Following it is what turns a block of HTML into a widget whose text, dates, colours and images can be changed later from form controls instead of by editing code.

What do I do with the code the assistant gives me?

Open the Fugte editor, start a widget from existing code, and paste it in. Fugte splits it into files, reads the schema, and gives you the editable controls the prompt asked for. From there you publish it and paste one line of HTML into your site.

Why not paste the assistant's HTML straight into my site?

You can, and it will work until the first thing you want to change. Code pasted out of a chat is frozen at the moment it lands: changing a date or a colour means going back to the chat, regenerating, and re-pasting into every page it sits on. A widget carrying a Fugte schema keeps those parts as controls, and editing one updates the widget everywhere it is embedded.

Can I change the rules in the prompt?

Yes. It is text, and every line in it is there for a reason you can read on this page. The two worth keeping whatever else you cut are the notched corners (four offset box-shadows instead of a border) and the stepped timing, because those two are most of the difference between pixel art and flat design with a thick outline.