---
title: Make monthly videos for a dentist, gym, restaurant or home service
description: Set up one branded template per local business, then make each month's short videos from a brief, in vertical and square.
---
Make a monthly set of short social videos, or promo reels, for a local business: a dental clinic, a gym, a restaurant, a plumber or a cleaner. You set up a template once with the business's brand. Each month, a brief lists the four videos, and your agent makes each one from the template with the business's own photos, stock b-roll, a voiceover and captions, in vertical and square.

Use invideo for this when you run videos for one business or many every month: the template, the brand kit and the brief live in the project, so next month starts where this month stopped.

The agent never posts to Instagram, Facebook, TikTok or Google. The business owner, or you, posts.

## Quickest path

Set up your agent first with [invideo for AI agents](/agents). Then give it this prompt.

```text
Set up a monthly video project for Bright Smile Dental: a brand kit from
the logo and colors in ./brand, and a 20-second vertical template with a
voiceover, captions and an end card with the phone number. Then make
November's four videos from the brief below, using the photos in
./november. Vertical and square. Price everything first.
```

In a chat app, you drag the photos into the project. In a terminal, the agent names the folders.

## What you need

These are the inputs the agent asks for.

- The business's logo, colors and font, or permission to pick a clean font.
- The contact line for the end card: phone, address or booking link.
- This month's four topics. Common ones by trade are below.
- Photos and phone clips from the business: the team, the space, the work.
- A voice, or captions with music only.
- The shapes: 9:16 for Reels, Shorts and TikTok, 1:1 for the feed.

Topics that work each month:

- **Dentist:** meet the team, a patient question answered, the month's offer, a tour of the clinic.
- **Gym:** a class of the week, a member story, a trainer's tip, the schedule.
- **Restaurant:** the dish of the month, behind the kitchen door, an event night, the opening hours.
- **Home service:** a before and after, a seasonal tip, a team intro, a customer review read out.

## Steps

The agent sets up the business once, then repeats the last four steps each month.

<Steps>
<Step title="Write the brand kit">
The agent writes a context entry at `context/brands/bright-smile.md` with `write`: colors, font, logo position and the contact line. It uploads the logo and the font with `start_upload` and `add_media` on the timeline URL. Expected result: an entry URL, and the logo and font in the media bin.
</Step>
<Step title="Build the template">
The agent makes a 1080 by 1920 timeline with `new_timeline` and creates a `vertical` branch with `timeline_history`. It adds a title card and an end card with `add_text`, styled with `set_text_style`, and the logo with `place_media`. Expected result: a template the agent shows you with `capture`.
</Step>
<Step title="Write the monthly brief">
The agent makes a brief with `new_brief`, named for the month. It adds one note per video: the topic, the script line, the photos to use, and the offer. You approve the brief before anything is made. Expected result: a brief URL with four notes.
</Step>
<Step title="Make each video from the template">
For each note, the agent runs `duplicate_timeline`, reads the copy with `get_timeline`, and changes the cards with `set_text`. It brings in the business's photos with `add_media` and fills gaps with stock from `search_library` in `stock_video`. Expected result: four timelines, one per video.
</Step>
<Step title="Voice and caption each video">
The agent runs `find_models` with the job in words, picks one, and reads its inputs with `get_model`. A good pick is `elevenlabs_text_to_speech.elevenlabs_tts_v4`, with a `voice_id` from `search_library` in `elevenlabs_text_to_speech_voices`. For each script, it calls `generate` with `dry_run: true`, the script as `prompt` and that `voice_id`, and tells you the price. Then it calls `generate` with `max_credits` set to that price and its own `idempotency_key` per video, and reads each sequence URL it gets back with `read`. It prices `audio.transcript` on each voice with `dry_run`, starts it, and calls again after `retry_after_s` for the words. Then it sends `add_captions`. Expected result: a voice sequence URL and a caption clip for every video.
</Step>
<Step title="Make the square versions">
The agent creates a `square` branch from `vertical` with `timeline_history`. On it, it sets each timeline to 1080 by 1080 with `set_timeline_settings`, then re-centers each shot with `fill_frame` or `set_position`. Expected result: square versions with no face or text cut off.
</Step>
<Step title="Check, then export">
The agent runs `capture` on every video on both branches, and `check_timeline`. It reads the phone number and the offer on each end card. Then it runs `export` per timeline with `timeline_id`. It marks the brief's status as ready. Expected result: eight export cards with status `completed`.
</Step>
</Steps>

The terminal version, for one month:

```bash
invideo project new --title "Bright Smile Dental videos"
invideo agent register <project-url> --name <name>
export INVIDEO_AS=<name>
invideo context write <project-url>/context/brands/bright-smile.md \
  --markdown @bright-smile.md
invideo context new-brief <project-url> --name "November" \
  --description "Four videos: team, FAQ, whitening offer, clinic tour"
invideo edit new <project-url> --name "Template" \
  --width 1080 --height 1920
invideo asset upload <edit-url> ./november/*.jpg
invideo gen models <project-url> --query "voiceover from a script"
invideo gen model <project-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  --dry-run -i prompt=@nov-team.txt -i voice_id=<voice-id>
invideo gen run <page-url> \
  --model elevenlabs_text_to_speech.elevenlabs_tts_v4 \
  --max-credits <price> --idempotency-key nov-team-voice \
  -i prompt=@nov-team.txt -i voice_id=<voice-id>
invideo media audio.transcript <sequence-url> --dry-run
invideo media audio.transcript <sequence-url> --max-credits <price>
invideo edit show <edit-url> --json
invideo branch new <edit-url> --name vertical --token <state_token>
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T1 --token <state_token> \
  --operations @copy.json
invideo edit show <branch-url> --json
invideo edit change <branch-url> --timeline T2 --token <state_token> \
  --operations @november.json
invideo edit capture <branch-url> --timeline T2 --at 1,8,18 --out ./frames
invideo edit check <branch-url>
invideo edit export <branch-url> --format video --timeline T2 --json
invideo status <card-url> --wait
invideo notebook show <card-url> --out ./nov
mv ./nov/export.mp4 ./nov/nov-team-9x16.mp4
invideo context show <brief-url>
invideo context edit <brief-url> --old "status: <brief-status>" \
  --new "status: ready"
```

Where the values come from:

- `<project-url>` comes from `invideo project new`, and `<edit-url>` from `invideo edit new`. `<name>` is the name you choose in `invideo agent register`. `<page-url>` is a notebook page from `invideo notebook show <project-url>`.
- `<voice-id>` comes from a search in `elevenlabs_text_to_speech_voices`. Each `<price>` is the dry run right before it.
- `<sequence-url>` is the voice's sequence URL, which the paid voice run returns.
- `<state_token>` comes from the `invideo edit show` right before each command: on `<edit-url>` for the branch, then on `<branch-url>` before each change. The main token is stale on the branch. `<branch-url>` is the `.branch_url` that `invideo branch new` returns for `vertical`.
- `T2` is the copy's id, from the `invideo edit show <branch-url>` after the copy landed.
- `<card-url>` is `.sequences[0]` of what the export returns. `invideo status` waits and does not download; `invideo notebook show` saves `./nov/export.mp4`.
- `<brief-url>` comes from `invideo context new-brief`, and `<brief-status>` is the status text that `invideo context show` prints.

The square branch repeats the copy, size and export lines on its own `.branch_url`, from `invideo branch new <edit-url> --name square --token <state_token>`, with a fresh token from `invideo edit show` on that branch.

The key edits copy the template for one video, then set its title card and place a photo. These are two calls, because the copy's ids come from a read in between. Each file holds a bare list of operations; on the MCP path, the same list goes in the `operations` field of `edit_timeline`. The file `./copy.json`:

```json
[
  { "op": "duplicate_timeline", "timeline": "T1",
    "name": "Nov 1: Meet the team" }
]
```

The file `./november.json`, with the copy's clip id `c31` and the photo's bin id `m7` from `invideo edit show`. At 30 fps, frame 90 is 3 seconds.

```json
[
  { "op": "set_text", "clip": "c31", "text": "Meet Dr. Lee's team" },
  { "op": "place_media", "asset": "m7", "track": "V1", "at_f": 90,
    "source_start_seconds": 0, "source_end_seconds": 3,
    "mode": "overwrite", "linked_audio": false }
]
```

## Cost and time

Edits and exports are free. Generation and transcripts cost credits. Paid stock costs a small credit charge, or one of your workspace's iStock licenses. Your agent runs a dry run first and tells you the price before it spends anything.

- Free: the brand kit, the brief, every copy and edit, the square branch, `capture`, every `export`.
- Costs credits: the TTS voice, `audio.transcript` on each voice, and each stock shot.

The first month takes a few hours with the setup. Later months take about an hour for four videos. For many businesses, run them in parts, one business at a time. See [Credits](/account/credits) for prices.

## If something goes wrong

Most problems are a copy with the wrong ids, or a square crop that cuts a face.

| Symptom | Fix |
| --- | --- |
| `get_model` or `generate` refuses the model as not found | Models retire. Run `find_models` with the job in words, use the best match, and tell the person which model you used. |
| Exit code 6, or `status` is `held` | A safety review, not a refusal. Wait, then run `invideo status <url> --wait` again. Do not resend. If it ends `failed`, change the input the review flagged. |
| `set_text` changed the template, not the copy | Read the copy with `get_timeline` and its `timeline_id`, then use its clip ids. |
| The square version cuts off a face or the phone number | Move the clip with `set_position`, or move the text up with `set_text_style` and `set_position`. Capture again. |
| A photo looks stretched | Use `fill_frame` on the clip. It scales evenly and crops the extra. |
| The brief edit is refused | The text in `old_text` must match the brief once, as `read` shows it. Read the brief again. |
| `timeout` on `export` | Do not export again. `read` the thread or call `status`. |
| CLI exit 3 | The edit changed since your read, or the token is from main. Run `invideo edit show <branch-url>` and use its new `state_token`. |
| The saved file is called `./nov/export.mp4` | `notebook show` always saves `./nov/export.mp4`. Rename it per video. |
| CLI exit 5 | Credits ran out. Stop and tell the person. |
| Avoid: health or result claims in a script | Instead: the owner approves every script line, and the agent writes no claims of its own. |
| Avoid: posting the videos | Instead: hand over the files with a caption line for each. The person posts. |

## Prompts to try

Each prompt is a real variation of this job.

```text
Make December's four videos for Iron Peak Gym from the brief. No
voiceover: captions and upbeat music only.
```

```text
I run videos for six restaurants. Set up a project per restaurant with
its own brand kit and template, then make this month's dish videos.
```

```text
Turn this five-star Google review into a 15-second video for the
plumbing company, with the reviewer's first name only.
```

## When to use something else

invideo does not schedule or post to social accounts or Google Business Profile, and it does not shoot the footage. Use a social scheduler such as Buffer or Later to post, and a phone to film at the business. For a stock-only commercial with no business photos, see the stock-footage commercial page.

## Related

- [Make a stock-footage commercial for your business, in short and long cuts](/how-to/marketing/stock-footage-commercial)
- [Turn listing photos into a vertical real-estate reel](/how-to/marketing/real-estate-reel)
- [Resize one master ad for every placement, with safe zones](/how-to/marketing/every-placement-from-one-master)
- [Add music and sound effects that clear rights](/how-to/creators/music-and-sound-effects)
- [Check your video before you say it is done](/how-to/check-your-video)
- [Know the cost before you spend](/how-to/cost-before-you-spend)