Tips and tricks for better prompts and consistent image generation

Picture by Gemini Nano Banana + Ommi

If you use LLMs, you’ve probably heard about the importance of a good prompt to get a good result. The “prompt engineering” concept was hype in 2023.

But it still has meaning, though not the same importance as 3 years ago, when everything lay on the prompt. It is still important, but now we have other techniques to improve or enrich the prompt the LLM receives — for example, prompt augmentation (or enrichment), which takes your prompt and adds: context, structural rules, domain knowledge, etc.

The goal of this post is simply to understand the basics and to show you a very simple, but useful, technique to get better results for one-shot prompts.

What is prompt expansion?

Prompt expansion is an AI technique that uses an LLM to generate prompts which are:

  • detailed
  • less ambiguous
  • complete

In other words, prompts generated by an LLM from a human prompt (or no prompt at all), that are more complete for the task at hand than the original one.

Let’s see it with an example: You want to init or bootstrap a frontend project. There are a lot of small things to do and decide: the tech stack, the linter, the linter’s rules, the formatter, the package manager, the runtime, TypeScript or not, testing tools and strategy, etc. A lot, but it’s probably not the first time you bootstrap a similar project, so instead of doing a detailed list of that, you can create a simple prompt:

“I want to create a prompt to bootstrap a Home Assistant frontend card addon. Use https://github.com/sergiocarracedo/sc-custom-cards as base for the tech stack and the coding decisions. We should ask the user for the addon name and for the cards to create.

Ask me any gap or doubt you have to generate a very detailed description of the tasks to do and ask to the user for this bootstrap and provide a check list of the expected outcome”

This part is very important: “Ask me any gap or doubt …”. It forces the LLM to not provide the final prompt inferring or hallucinating the missing parts, and to ask you for them

🤖

1. Card Architecture Structure: * sc-custom-cards packages multiple cards (e.g., Room Card, History Bars Card) together. Do you want this new addon to support a multi-card structure under one bundle from day one (as the repo does), or should it scaffold a repository dedicated to just a single standalone card?

2. Build System Preference: * The repo uses a custom pnpm dev / pnpm build workflow (typically powered by Rollup or Vite to bundle the TypeScript elements and lit-html templates). Should the generated bootstrap prompt explicitly mandate a specific bundler (e.g., Vite or Rollup), or let the generator choose the best modern setup that matches the asset output (dist/[addon-name].js)?

3. Visual Editor & Localization Configuration: * sc-custom-cards includes rich visual editors (with drag-and-drop, inline editing) and localization strings. Should the bootstrap prompt force the creation of a boilerplate *-editor.ts and a localize/ JSON translation structure for every card the user specifies?

4. CI/CD and Release Automation: * The reference repo utilizes release-please and automated GitHub workflows for both stable and beta channels. Do you want the bootstrap prompt to include setting up these GitHub Action .github/workflows/ files automatically?

👨 Me:

1. Yes
2. use vite. NOTE remember to include the formaters, lints, etc
3. yes
4. ask user if we want to add it

And the LLM 🤖 generates this prompt

You are an expert Frontend Developer and Home Assistant Addon Architect. Your task is to generate a comprehensive, production-ready workspace blueprint and the initial codebase boilerplate for a Home Assistant custom frontend card bundle. 

The architecture is a **multi-card monobundle** powered by **TypeScript**, **Lit**, and **Vite**.

First, ask the user for the following inputs before generating the files:
1. **Addon Name** (e.g., "my-custom-cards")
2. **List of Cards to Create** (e.g., "Room Card, Battery Status Card")
3. **CI/CD Integration**: Ask if they want GitHub Actions workflows configured for release automation.

Once the user provides this information, generate a complete workspace matching the specifications below.

---

## 🛠️ Architecture & Tech Stack Rules

* **Package Manager:** `pnpm`
* **Build Tool:** `Vite` configured to bundle all components, logic, and assets into a single distribution file (`dist/[addon-name].js`) suitable for Home Assistant Lovelace resource loading.
* **UI Framework:** `Lit` (using lit-element and lit-html decorators).
* **Language:** Strict TypeScript.
* **Formatting/Linting:** Biome or ESLint + Prettier (choose a modern, fast setup).

---

## 📂 Project Structure Blueprint

Generate the files according to this exact folder layout:

[addon-name]/
├── .github/                  # (Only if user opted into CI/CD)
│   └── workflows/
│       └── release.yml
├── dist/                     # Target build output
├── src/
│   ├── types/
│   │   └── homeassistant.ts  # Generic Home Assistant/HASS types
│   ├── utils/
│   │   └── localize.ts       # Translation helper
│   ├── localize/
│   │   └── en.json           # Default English translations
│   ├── cards/                # Dedicated folder per card
│   │   ├── [card-1]/
│   │   │   ├── [card-1].ts         # Main Lovelace card component
│   │   │   ├── [card-1]-editor.ts  # Visual UI Editor component
│   │   │   └── types.ts            # Card-specific configuration types
│   │   └── [card-2]/
│   │       ├── [card-2].ts
│   │       ├── [card-2]-editor.ts
│   │       └── types.ts
│   └── main.ts               # Core entrypoint registering all cards to window.customCards
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.md

## 📝 Implementation Details per File
1. package.json
Configure tasks: "dev": "vite build --watch", "build": "vite build", and lint/format scripts.

Dependencies: Include lit and custom-card-helpers.

DevDependencies: Include typescript, vite, vite-plugin-css-in-js (or similar to bundle styles into the JS), and your formatting/linting tooling.

2. vite.config.ts
Configure Vite to build in library mode.

Output a single bundle file named [addon-name].js inside the dist folder.

Ensure minification is turned on for production builds but keeps code readable enough for debugging in dev mode.

3. src/main.ts (The Registry Entrypoint)
Must hook into window.customCards to register every generated card so they appear natively in the Home Assistant visual card picker dashboard.

Example schema to inject:

TypeScript
window.customCards = window.customCards || [];
window.customCards.push({
  type: 'card-1-tag-name',
  name: 'Card 1 Name',
  preview: true,
  description: 'Description of Card 1',
});
4. src/cards/[card-name]/[card-name].ts (Main Card Boilerplate)
Extends LitElement.

Implements the mandatory Home Assistant Card Interface: setConfig(config) and the set hass(hass) setter.

Includes basic error handling if the config is invalid.

Links to its companion visual editor using a static getConfigElement() method.

5. src/cards/[card-name]/[card-name]-editor.ts (Visual Editor Boilerplate)
Extends LitElement.

Implements setConfig(config) and fires config-changed custom events back to the Lovelace dashboard when fields are mutated.

Renders an example configuration form (e.g., a text input for a card title or an entity selector dropdown).

6. src/utils/localize.ts & src/localize/en.json
A clean translation function that reads keys from the JSON structure depending on the current hass.language or defaults to en.

## 🎯 Verification Checklist
At the end of your generation, provide a checklist for the user detailing how to test and run their newly bootstrapped environment, including:

Running pnpm install.

Running pnpm dev to start the reactive build.

Adding the dist/[addon-name].js file as a /local/ Lovelace resource in Home Assistant.

Verifying the cards show up properly in the dashboard UI editor.

As you can see, it is very detailed and it can work very well for your next Home Assistant Card. Anyway, you don’t need to use it as-is — you can change whatever you need, or continue iterating with the LLM

Tips and tricks

  • Ask the LLM to not fill the gaps by assuming things and to ask you: “Ask me any gap or doubt you have”
  • Give it context: For example, a reference: e.g. “I want to generate a prompt to do text correction based on the following text style: [REFERENCE TEXT]”
  • Ask the LLM to behave as a specific role if needed: e.g. “You are a Literature Nobel Prize winner writer…”. It forces the LLM to ask questions and solve problems with domain-specific context
  • Read the results carefully to ensure they fit what you expect and to detect missing elements
  • Don’t settle for just one result. As LLMs are not deterministic, every time you ask for a prompt you will get a different output. Generate at least 2 and get the better parts or ideas from both to create one.

Image to prompt

Did you see an image you liked and you want to generate your version using an AI? You can just paste the image and tell the LLM the changes you made, but you can also do something smarter, reusable and repeatable:

Describe image style from an image

Imagine you want to create images with the same visual style as the “Steamboat Willie” movie (as it is a public domain movie now)

We can ask an LLM to generate a base prompt:

From the images, generate a prompt which distills the visual style of the images, be detailed with respect to generic styles, not about the items or specific characters in the images. In the prompt, reserve a placeholder for the user to describe the image they want to generate with this style

In my case the generated prompt was:

🤖

A black and white traditional hand-drawn 2D animation still, evoking the style of late 1920s cartoons. The aesthetic features high-contrast, grainy film quality with visible scratches and flicker. The artwork consists of thick, wobbly ink lines and simple, rounded shapes. Backgrounds are soft, hand-painted grayscale watercolor washes on textured paper, often with a blurred, distorted perspective. There is no smooth in-betweening; the animation has a jerky, energetic, and slightly imprecise feel, with a noticeable film grain overlay. Characters and objects have a simplistic, rubber-hose quality.

[INSERT YOUR DESCRIPTION OF THE IMAGE TO GENERATE HERE]

And now I can store this prompt (without the images — we don’t need them anymore), and just use it when I need it, generating images like these:

Each image was generated in a different session, meaning the model had no previous image as reference. It is pure prompting.

I encourage you to try it yourself and see the results. I used Gemini Flash for all the prompts (except for image generation, which uses nano banana).

Summary

This is an “old”, very simple and basic technique to improve LLM results, with no effort, but still important when you work with models.

If you add to the equation skills in both ways — skills to help you generate the prompts you need (for example, using brainstorming), and skill generation instead of a “classic” prompt — you have a powerful tool.

Select Sergio Carracedo as a preferred source on Google