# Source: https://docs.together.ai/docs/how-to-build-a-lovable-clone-with-kimi-k2.md

# How to build a Lovable clone with Kimi K2

> Learn how to build a full-stack Next.js app that can generate React apps with a single prompt.

[LlamaCoder](https://llamacoder.together.ai/) is a Lovable-inspired app that shows off how easy it is to use Together AI’s hosted LLM endpoints to build AI applications.

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=3b9b258e4c650436c4d23d7aaff5b353" alt="" data-og-width="3376" width="3376" data-og-height="2540" height="2540" data-path="images/guides/15.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=905423269b6f7e4306aa553b4a12f57a 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=4c3ce7093f84a9654ed00b2505190ed0 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=9e38e79a45f690f712fb7496f62346ef 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=a46451f89eecf67d8baf39a1327860df 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=cd8515f6e993aef6d73b0d179b406653 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/15.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=dd47ab385e02accc9abd75eb226ec202 2500w" /></Frame>

In this post, we’re going to learn how to build the core parts of the app. LlamaCoder is a Next.js app, but Together’s APIs can be used with any web framework or language!

## Scaffolding the initial UI

The core interaction of LlamaCoder is a text field where the user can enter a prompt for an app they’d like to build. So to start, we need that text field:

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=f04cf018c8b1314eedcbd166ba252a78" alt="" data-og-width="2000" width="2000" data-og-height="383" height="383" data-path="images/guides/16.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=26f25c6234027a94051904f4a76a864b 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=65dbb32b01f68aec98515d5b33d112f1 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=83162a8f5385e1e608bdc5f0c1803e20 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=6b435353883cb0bd7772e576422b10fd 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=88c163011541a34e75fd2e4b56bdcd5f 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/16.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=b477727dd46b647ebe3793d782b1ed58 2500w" /></Frame>

We’ll render a text input inside of a form, and use some new React state to control the input’s value:

```jsx JSX theme={null}
function Page() {
  let [prompt, setPrompt] = useState('');

  return (
    <form>
      <input
        value={prompt}
        onChange={(e) => setPrompt(e.target.value)}
        placeholder='Build me a calculator app...'
        required
      />

      <button type='submit'>
        <ArrowLongRightIcon />
      </button>
    </form>
  );
}
```

Next, let’s wire up a submit handler to the form. We’ll call it `createApp`, since it’s going to take the user’s prompt and generate the corresponding app code:

```jsx JSX theme={null}
function Page() {
  let [prompt, setPrompt] = useState('');

  function createApp(e) {
    e.preventDefault();

    // TODO:
    // 1. Generate the code
    // 2. Render the app
  }

  return <form onSubmit={createApp}>{/* ... */}</form>;
}
```

To generate the code, we’ll have our React app query a new API endpoint. Let’s put it at `/api/generateCode` , and we’ll make it a POST endpoint so we can send along the `prompt` in the request body:

```jsx JSX theme={null}
async function createApp(e) {
  e.preventDefault();

  // TODO:
  // 1. Generate the code
  await fetch('/api/generateCode', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt }),
  });

  // 2. Render the app
}
```

Looks good – let’s go implement it!

## Generating code in an API route

To create an API route in the Next.js 14 app directory, we can make a new `route.js` file:

```jsx JSX theme={null}
// app/api/generateCode/route.js
export async function POST(req) {
  let json = await req.json();

  console.log(json.prompt);
}
```

If we submit the form, we’ll see the user’s prompt logged to the console. Now we’re ready to send it off to our LLM and ask it to generate our user’s app! We tested many open source LLMs and found that Kimi K2 was the only one that did a good job at generating small apps, so that’s what we decided to use for the app.

We’ll install Together’s node SDK:

```bash Shell theme={null}
npm i together-ai
```

and use it to kick off a chat with Kimi K2.

Here’s what it looks like:

```jsx JSX theme={null}
// app/api/generateCode/route.js
import Together from 'together-ai';

let together = new Together();

export async function POST(req) {
  let json = await req.json();

  let completion = await together.chat.completions.create({
    model: 'moonshotai/Kimi-K2-Instruct-0905',
    messages: [
      {
        role: 'system',
        content: 'You are an expert frontend React engineer.',
      },
      {
        role: 'user',
        content: json.prompt,
      },
    ],
  });

  return Response.json(completion);
}
```

We call `together.chat.completions.create` to get a new response from the LLM. We’ve supplied it with a “system” message telling the LLM that it should behave as if it’s an expert React engineer. Finally, we provide it with the user’s prompt as the second message.

Since we return a JSON object, let’s update our React code to read the JSON from the response:

```jsx JSX theme={null}
async function createApp(e) {
  e.preventDefault();

  // 1. Generate the code
  let res = await fetch('/api/generateCode', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt }),
  });
  let json = await res.json();

  console.log(json);

  // 2. Render the app
}
```

And now let’s give it a shot!

We’ll use something simple for our prompt like “Build me a counter”:

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=ff79766604b0ecdf613528a6409e0736" alt="" data-og-width="1720" width="1720" data-og-height="305" height="305" data-path="images/guides/17.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=8b151e6cca96d4f2e47a3df190700cdc 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=54794fd845d0c953bec237e67a7c89ad 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=5e40a57ddd5d77a77eaa3cc66586a499 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=580fa4fc21f9a0f60359540893afc9be 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=abdba72d62968901ce00699ed9c06802 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/17.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=6d3218731f4f3ffdb9cf3ab9558d16be 2500w" /></Frame>

When we submit the form, our API response takes several seconds, but then sends our React app the response.

If you take a look at your logs, you should see something like this:

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=aecf6247f32c6431afe963569c44f898" alt="" data-og-width="1720" width="1720" data-og-height="1800" height="1800" data-path="images/guides/18.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=7accc4c3d05db2e182692f3104aeb848 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=5d77c5e86c4143c85f677a67d71dea18 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=88d849973cffa20dfe9bf77e45d42009 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=b386cc1ca484905abdd2f1bf330b469d 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=324b5f21f1df81cb8411997c326c86c6 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/18.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=492b5d936cc82ff8c589871cd7036675 2500w" /></Frame>

Not bad – Kimi K2 has generated some code that looks pretty good and matches our user’s prompt!

However, for this app, we’re only interested in the code, since we’re going to be actually running it in our user’s browser. So we need to do some prompt engineering to get Llama to only return the code in a format we expect.

## Engineering the system message to only return code

We spent some time tweaking the system message to make sure it output the best code possible – here’s what we ended up with for LlamaCoder:

```jsx JSX theme={null}
// app/api/generateCode/route.js
import Together from 'together-ai';

let together = new Together();

export async function POST(req) {
  let json = await req.json();

   let res = await together.chat.completions.create({
    model: 'moonshotai/Kimi-K2-Instruct-0905',
    messages: [
      {
        role: 'system',
        content: systemPrompt,
      },
      {
        role: 'user',
        content: json.prompt,
      },
    ],
    stream: true,
  });

  return new Response(res.toReadableStream(), {
    headers: new Headers({
      'Cache-Control': 'no-cache',
    }),
  });
}

let systemPrompt = `
  You are an expert frontend React engineer who is also a great UI/UX designer. Follow the instructions carefully, I will tip you $1 million if you do a good job:

  - Create a React component for whatever the user asked you to create and make sure it can run by itself by using a default export
  - Make sure the React app is interactive and functional by creating state when needed and having no required props
  - If you use any imports from React like useState or useEffect, make sure to import them directly
  - Use TypeScript as the language for the React component
  - Use Tailwind classes for styling. DO NOT USE ARBITRARY VALUES (e.g. \`h-[600px]\`). Make sure to use a consistent color palette.
  - Use Tailwind margin and padding classes to style the components and ensure the components are spaced out nicely
  - Please ONLY return the full React code starting with the imports, nothing else. It's very important for my job that you only return the React code with imports. DO NOT START WITH \`\`\`typescript or \`\`\`javascript or \`\`\`tsx or \`\`\`.

  NO LIBRARIES (e.g. zod, hookform) ARE INSTALLED OR ABLE TO BE IMPORTED.
`;
```

Now if we try again, we’ll see something like this:

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=f1d16f71f2ca2fa446da7b90498350fa" alt="" data-og-width="1720" width="1720" data-og-height="1714" height="1714" data-path="images/guides/19.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=676fe6d759e3b106d7e80e99efeb40c6 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=1ef69aad734b972e522e44d91a27c065 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=4e677495d33b5b996d75440d8d543181 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=13e1a373a9da4824702a1e8620460e55 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=82a8c790748083631447c1702b716392 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/19.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=d9301c7cdfde07d1fea3e9d15ccf1417 2500w" /></Frame>

Much better –this is something we can work with!

## Running the generated code in the browser

Now that we’ve got a pure code response from our LLM, how can we actually execute it in the browser for our user?

This is where the phenomenal [Sandpack](https://sandpack.codesandbox.io/) library comes in.

Once we install it:

```bash Shell theme={null}
npm i @codesandbox/sandpack-react
```

we now can use the `<Sandpack>` component to render and execute any code we want!

Let’s give it a shot with some hard-coded sample code:

```jsx JSX theme={null}
<Sandpack
  template='react-ts'
  files={{
    'App.tsx': `export default function App() { return <p>Hello, world!</p> }`,
  }}
/>
```

If we save this and look in the browser, we’ll see that it works!

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=c6a9fec2cfc230edbb74d74604b97a22" alt="" data-og-width="1720" width="1720" data-og-height="1180" height="1180" data-path="images/guides/20.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=bc0393627d946b795ac5ad6f0ef44d46 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=8c1db2a93b3625eba3c527c2a070df9c 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=1f0cb64032a4a1c6a9db54ae0313fdaf 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=bac010968d019e4eb0d0c2ef5207a12f 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=d2e26c93f30af40354488158f5c1348a 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/20.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=19fcf021a04807fde1414575958ed1ed 2500w" /></Frame>

All that’s left is to swap out our sample code with the code from our API route instead.

Let’s start by storing the LLM’s response in some new React state called `generatedCode`:

```jsx JSX theme={null}
function Page() {
  let [prompt, setPrompt] = useState('');
  let [generatedCode, setGeneratedCode] = useState('');

  async function createApp(e) {
    e.preventDefault();

    let res = await fetch('/api/generateCode', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ prompt }),
    });
    let json = await res.json();

    setGeneratedCode(json.choices[0].message.content);
  }

  return (
    <div>
      <form onSubmit={createApp}>{/* ... */}</form>
    </div>
  );
}
```

Now, if `generatedCode` is not empty, we can render `<Sandpack>` and pass it in:

```jsx JSX theme={null}
function Page() {
  let [prompt, setPrompt] = useState('');
  let [generatedCode, setGeneratedCode] = useState('');

  async function createApp(e) {
    // ...
  }

  return (
    <div>
      <form onSubmit={createApp}>{/* ... */}</form>

      {generatedCode && (
        <Sandpack
          template='react-ts'
          files={{
            'App.tsx': generatedCode,
          }}
        />
      )}
    </div>
  );
}
```

Let’s give it a shot! We’ll try “Build me a calculator app” as the prompt, and submit the form.

Once our API endpoint responds, `<Sandpack>` renders our generated app!

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=4e47962545fab91b857856e5c92c45db" alt="" data-og-width="1720" width="1720" data-og-height="1085" height="1085" data-path="images/guides/21.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=4c398c3d3a4b3fc0d2a39843aa6763d2 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=c37d3896bc9375074770efb19dfbc1bb 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=dceeab1b4725d90850b43c4ca9f5446b 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=d71e5afd3726c523532b2dcd4ca5d546 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=c04f42f9ddc29f6d3c3cf123ded012a4 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/21.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=347a422de6a94c6f29d36f8d302c6f0e 2500w" /></Frame>

The basic functionality is working great! Together AI (with Kimi K2) + Sandpack have made it a breeze to run generated code right in our user’s browser.

## Streaming the code for immediate UI feedback

Our app is working well –but we’re not showing our user any feedback while the LLM is generating the code. This makes our app feel broken and unresponsive, especially for more complex prompts.

To fix this, we can use Together AI’s support for streaming. With a streamed response, we can start displaying partial updates of the generated code as soon as the LLM responds with the first token.

To enable streaming, there’s two changes we need to make:

1. Update our API route to respond with a stream
2. Update our React app to read the stream

Let’s start with the API route.

To get Together to stream back a response, we need to pass the `stream: true` option into `together.chat.completions.create()` . We also need to update our response to call `res.toReadableStream()`, which turns the raw Together stream into a newline-separated ReadableStream of JSON stringified values.

Here’s what that looks like:

```jsx JSX theme={null}
// app/api/generateCode/route.js
import Together from 'together-ai';

let together = new Together();

export async function POST(req) {
  let json = await req.json();

  let res = await together.chat.completions.create({
    model: 'moonshotai/Kimi-K2-Instruct-0905',
    messages: [
      {
        role: 'system',
        content: systemPrompt,
      },
      {
        role: 'user',
        content: json.prompt,
      },
    ],
    stream: true,
  });

  return new Response(res.toReadableStream(), {
    headers: new Headers({
      'Cache-Control': 'no-cache',
    }),
  });
}
```

That’s it for the API route! Now, let’s update our React submit handler.

Currently, it looks like this:

```jsx JSX theme={null}
async function createApp(e) {
  e.preventDefault();

  let res = await fetch('/api/generateCode', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt }),
  });
  let json = await res.json();

  setGeneratedCode(json.choices[0].message.content);
}
```

Now that our response is a stream, we can’t just `res.json()` it. We need a small helper function to read the text from the actual bytes that are being streamed over from our API route.

Here’s the helper function. It uses an [AsyncGenerator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator) to yield out each chunk of the stream as it comes over the network. It also uses a TextDecoder to turn the stream’s data from the type Uint8Array (which is the default type used by streams for their chunks, since it’s more efficient and streams have broad applications) into text, which we then parse into a JSON object.

So let’s copy this function to the bottom of our page:

```jsx JSX theme={null}
async function* readStream(response) {
  let decoder = new TextDecoder();
  let reader = response.getReader();

  while (true) {
    let { done, value } = await reader.read();
    if (done) {
      break;
    }
    let text = decoder.decode(value, { stream: true });
    let parts = text.split('\\n');

    for (let part of parts) {
      if (part) {
        yield JSON.parse(part);
      }
    }
  }

  reader.releaseLock();
}
```

Now, we can update our `createApp` function to iterate over `readStream(res.body)`:

```jsx JSX theme={null}
async function createApp(e) {
  e.preventDefault();

  let res = await fetch('/api/generateCode', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt }),
  });

  for await (let result of readStream(res.body)) {
    setGeneratedCode(
      (prev) => prev + result.choices.map((c) => c.text ?? '').join('')
    );
  }
}
```

This is the cool thing about Async Generators –we can use `for...of` to iterate over each chunk right in our submit handler!

By setting `generatedCode` to the current text concatenated with the new chunk’s text, React automatically re-renders our app as the LLM’s response streams in, and we see `<Sandpack>` updating its UI as the generated app takes shape.

<Frame><img src="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=3b1cc77e62ae3caedb66c23dd6976460" alt="" data-og-width="1720" width="1720" data-og-height="1450" height="1450" data-path="images/guides/22.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?w=280&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=5207bb61c14cd5b68db8ff05719cfdbd 280w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?w=560&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=cec467f8f423b6583cfd29a57189c747 560w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?w=840&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=396ca8897ad1246ffec27b7dd57d541b 840w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?w=1100&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=1c42b7a7b93d279c93d40d55f99ae204 1100w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?w=1650&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=c073ae539f1cbea0c449c43c25eea923 1650w, https://mintcdn.com/togetherai-52386018/msWWavplJrEZR36N/images/guides/22.png?w=2500&fit=max&auto=format&n=msWWavplJrEZR36N&q=85&s=29acec1c6fbf4dfdb19725b6ee9a6cd2 2500w" /></Frame>

Pretty nifty, and now our app is feeling much more responsive!

## Digging deeper

And with that, you now know how to build the core functionality of Llama Coder!

There’s plenty more tricks in the production app including animated loading states, the ability to update an existing app, and the ability to share a public version of your generated app using a Neon Postgres database.

The application is open-source, so check it out here to learn more: **[https://github.com/Nutlope/llamacoder](https://github.com/Nutlope/llamacoder)**

And if you’re ready to start querying LLMs in your own apps to add powerful AI features just like the kind we saw in this post, [sign up for Together AI](https://api.together.ai/) today and make your first query in minutes!


---

> To find navigation and other pages in this documentation, fetch the llms.txt file at: https://docs.together.ai/llms.txt