Prototype: Create a Website from a Screenshot and Refine It, All in the Browser

I’ve been working on this experiment, combining OpenAI’s gpt-4-vision-preview with WordPress Playground to create a website based on a screenshot.

This follows on the heels of Matt Mullenweg’s announcement at the 2023 State of the Word that in 2024, the WordPress project wants to work on Data Liberation.

While the typical approach to migrating data is to build importers for specific services, a truely universal migration could happen through screenshots. With AI vision this might now be in reach.

So I built this prototype that combines a OpenAI-powered chat interface with WordPress Playground. First a screenshot, a screen recording further down.

So this is only a start. The website somewhat resembles the screenshot but it’s far from being pixel perfect.

My idea is that you’ll work together with the assistant in refining the site. It can help you update, you can ask it questions. An import is rarely perfect from the start but you can see and test the result right away in the browser and refine it.

I imagine that when done, you can then transfer the site to a web hoster who from then on can host your website for everyone.

You can try this yourself here, you “just” need an OpenAI API key that will be stored in your local storage:

Source (very unpolished) at

Some notes on this first implementation:

  • Every message is a new conversation. Modifying a website can be token intense, so for now it cannot refer to previous messages.
  • It’s using function calling to allow OpenAI to gather more information to fulfil the request.
  • Chosing the right functions to provide can be tricky.
  • It uses different models depending on the task. gpt4-vision-preview for the screenshot, gpt-3.5-turbo for the rest. I need to experiment more with gpt-4 for the latter tasks.

Finally, a screen recording of an early iteration, I have since moved the chat to the right side.

As I’ve been working on the prototype, it has shown to be interesting to have the bot be there just for customizing sites, it can create and modify pages, update settings of the website. Maybe install plugins.

So starting with a basis from screenshots and imported data, it might just be able to assist you to arrive at a comparable WordPress website, and all with the ease and effortless setup of WordPress Playground. I wonder where we can take this!


Some screenshots from a recent version:

chat-cli: renamed and added Ollama support

I have added support for Ollama to my chat-cli tool (formerly named cli-chatgpt, see previous posts). Ollama is a very easy way to run llama2 locally; it runs a local HTTP server and this will be used.

Depending on whether an OpenAI key or Ollama are available, the models will be made available and you can see this in cgt -h. (Using cgt as a command here is based on my recommendation of using an alias in your shell.)

When you’re offline, OpenAI is deemed unavailable, thus–if it is installed and active–Ollama/llama2 will be used automatically. While it currently doesn’t switch between models during a conversation (because of your online state), you can simply exit and re-continue the conversation with another model using cgt -l.

Both models show their responses in a streaming way.

❯ cgt where is gerolstein
Model: gpt-3.5-turbo
> where is gerolstein

Gerolstein is a town in the Bitburg-Prüm district in Rhineland-Palatinate, Germany. It is located in the Eifel mountain range, approximately 15 kilometers southeast of Bitburg.
> ^c

### Went offline here.
❯ cgt where is gerolstein
Model: llama2:latest
> where is gerolstein

 Gerolstein is a town located in the state of Rhineland-Palatinate, Germany. It is situated in the northern part of the state, approximately 20 kilometers (12 miles) northwest of the city of Mainz. The exact address of Gerolstein is:

Gerolstein, Germany

If you are planning to visit Gerolstein or need more detailed information, please let me know and I will be happy to help.

While there is no config available, you can change the priority of models in the source.

Resuming ChatGPT chats in CLI

I have issued an update to my CLI ChatGPT Client (see when I first announced it) so that you can now resume conversations. Here is the new --help output (I personally have an alias cgt=path/to/chat.php to have it quickly available):

Usage: chat.php [-l] [-r [number]] [-s system_prompt] [conversation_input]

  -l                 Resume last conversation.
  -r [number]        Resume a previous conversation and list 'number' conversations (default: 10).
  -s [system_prompt] Specify a system prompt preceeding the conversation.

  conversation_input  Input for the first conversation.

  - To input multiline messages, send an empty message.
  - To end the conversation, enter "bye".

Example usage:
  chat.php -l
    Resumes the last conversation.

  chat.php -r 5
    Resume a conversation and list the last 5 to choose from.

  chat.php -s "Only respond in emojis"
    Have an interesting conversation 🙂

  chat.php Tell me a joke
    Starts a new conversation with the given message.

The CLI client uses a streaming response, so you can watch as it generates your answer.

The resuming functionaliy also changed re-arranges the history in the chat cli folder to a structure chats/%Y/%M/history.%U.txt (with %Y being a 4-digit year, %M a two-digit month and %U the unix timestamp when it was started). The prompt is readline compatibly with a history file so that you can quickly reuse previous questions. You can avoid something to be added to history by prepending it with whitespace.

chat.php -l will quickly resume the last conversation but you can also resume other ones:

$ cgt -r 3                                                                                                                                                     Resuming a conversation. Please choose one: 

1) is there an alternative to the logwatch program that can send daily e-mails with reports on log file (1 answer, 248 words)

2) please give me javascript that restarts a video when i click on it (2 answers, 237 words)

3) does a one-letter domain like (specifically) cost more than other .org domains? (3 answers, 253 words)

Please enter the number of the conversation you want to resume (m for more):

To me, it is very powerful to have ChatGPT available in the CLI since I always have a terminal open. Keeping searchable local history is also something that I like for later (offline) reference.

Letting ChatGPT Access the Internet

With the new Completions function calling API you can actually enable ChatGPT to access the internet. I did a few quick experiments where I provided it with a function called get_extracted_url_contents. See how it made use of it:

Get News


$ php get-news.php

Prompt: Get some news from a random US news website on the internet.
Fetching by request of ChatGPT.
AI (239 tokens used):
According to CNN, the breaking news is that the former US president has been arraigned on 37 federal charges involving the alleged mishandling of highly classified military documents. This is a historic first.

Or from a German website:

Prompt: Get some news from a random German news website on the internet. Please only respond in English.
Fetching by request of ChatGPT.
AI (1363 tokens used):
Here are some news headlines from SPIEGEL International:

  1. “Ukraine’s President Calls on NATO to Set Clear ‘Red Lines’ for Russia” – Ukrainian President Volodymyr Zelensky has urged NATO to establish clear “red lines” to deter further aggression from Russia. Zelensky made these remarks during a visit to Brussels.
  2. “German Cabinet Approves New COVID-19 Restrictions, Including Nationwide Vaccination Mandate” – The German government has approved new measures to combat the spread of COVID-19, including a nationwide vaccination mandate for certain groups of people. These measures come as Germany faces a surge in COVID-19 cases.
  3. “Turkey Summons German Ambassador Over ‘AfD-Led’ Turkish Ship Inspection” – Turkey has summoned the German ambassador to protest against the inspection of a Turkish ship by a German frigate in the Mediterranean Sea. The inspection was led by a member of the far-right Alternative for Germany (AfD) party.
  4. “European Court of Justice Rules Hungary’s NGO Law Violates EU Law” – The European Court of Justice has ruled that Hungary’s controversial law that restricts the activities of non-governmental organizations (NGOs) violates EU law. The law required NGOs that receive funding from abroad to register as “foreign-funded organizations.”

Please note that these are just a few selected headlines. For more information, you can visit the SPIEGEL International website.

One more try for a specific site:

Prompt: Get some news from ORF. Please only respond in English.
Fetching by request of ChatGPT.
AI (1286 tokens used):
Here are some news headlines from ORF:

  1. Document affair: Trump declares “not guilty”
  2. Babler presents his new team
  3. Johnson vs. Sunak: Insults keeping the British on edge
  4. Slovenia wants to keep borders with Croatia open
  5. WKStA secures data in the Chancellor’s Office
  6. Alaba is about to reach the next milestone
  7. Alpine climate in winter is significantly too mild
  8. IAEA “very concerned” about fighting near Zaporizhia nuclear power plant
  9. NATO hopes Ukrainian successes will force Moscow to negotiate

Please note that these are only the headlines and more details can be found on the ORF website.

Summarize URLs


$ php summarize-url.php
Fetching by request of ChatGPT.
AI (1340 tokens used):
Matrix is an open-source internet-based chat system that operates on a federated model similar to email. It allows users to send and receive messages through homeservers, which maintain up-to-date copies of chat rooms. Matrix rooms can be either unencrypted and openly discoverable or end-to-end encrypted and invite-only, with encryption keys shared between users’ client software. There is a wide selection of Matrix clients available for different platforms, and a WordPress plugin called Chatrix has been developed to embed Matrix into WordPress posts or pages.



Here it required several runs to get the right response since it tried to access a lot of invalid URLs. But it eventually managed.

$ php research.php
Prompt: Research on the internet who won the ATP French Open 2023 but don’t use a search engine.
Fetching by request of ChatGPT.
AI (1085 tokens used):
According to the information on the Wikipedia page for the 2023 French Open, Novak Djokovic won the ATP Men’s Singles championship.

Things also worked out in the end when I gave it the ability to do multipel requests:

$ php research.php
Prompt: Research on wikipedia who won the (both men’s and women’s) ATP French Open 2023. If you cannot find a result, ask for a subsequent a function call.
Fetching by request of ChatGPT.PHP Warning: file_get_contents( Failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found

Fetching by request of ChatGPT.PHP Warning: file_get_contents( Failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
Fetching by request of ChatGPT.
AI (1630 tokens used):
The winner of the men’s singles ATP French Open 2023 is Novak Djokovic, and the winner of the women’s singles ATP French Open 2023 is Iga Świątek.

This has been just a quick exploration following OpenAI’s announcement. Curious how we’ll leverage this better in future!

CLI ChatGPT Client in PHP

For my personal use, I created a CLI ChatGPT client a few months ago. It has been very useful for me to have it available in the CLI quickly whenever I needed it (caveat, you need an API key!).

Unfortunately, for larger responses it can feel very slow, whereas the web version feels quite fast. But this is perceived speed because it shows you each word as it arrives and not just the whole response when finished (after all it is a completion AI that generates the response word by word).

So now, I have added streaming support to it. It now feels almost too fast :) The CLI has a few nice things such as readline support (i.e. you can go back to old queries with the up key) and it keeps all of your conversation in a text file. All of this in only 100 lines of PHP.