AI Code Generation: Lovable and Copilot Free

Published: Jan 7, 2025 by Isaac Johnson

Let’s talk about another hot AI Code Generation tool, Lovable. This is a relatively new tool using AI to build out full solutions with push-button deploys. I’m interested to compare this with other tools like Vercel’s V0 and CursorAI. Let’s dig in and see what it can do.

History

Founded in Stockhold Sweden, Lovable is basically a relaunch of gptengineer.app. It’s now, as of two weeks ago, officially branded after the URL and called Lovable.dev (read more on LinkedIn)

Anton Osika and Fabian Hedin are the co-founders of Lovable likely met at Depict where Fabien was a Frontend Lead and Anton was the CTO and Co-founder.

Lovable setup and pricing

We can create an account or sign in from the main page of Lovable.dev

/content/images/2025/01/lovable-01.png

For IdPs, I can create a unique account or use Google or Github

/content/images/2025/01/lovable-02.png

For the free or trial plan, we can see we get five messages a day

/content/images/2025/01/lovable-03.png

The starter plan, which is US$20/mo gives use 100 messages a month. But I’m confused by this as I get 5 a day with free. So does that mean 5 free a day (31x5=165 + 100 for 265?) or is it instead I get 100 but i could use 50 in a day?

/content/images/2025/01/lovable-04.png

I’m not thumbing my nose at this - I’m just saying the pricing is confusing to me.

Copilot setup

With “Copilot for free”, I get 2000 code completions and 50 chat messages per month

/content/images/2025/01/lovable-05.png

And as we see, for $10/month we move that to unlimited.

I’m not saying the two are equal - it’s just interesting in pricing compared to offering.

Again, let’s compare to Cursor which is 2000 completions (?ever ?month) and 50 “slow” requests but moving to US$20/month and we are at unlimited completions and 50 fast requests (and unlimited “slow”).

/content/images/2025/01/lovable-06.png

And lastly, best I can tell, v0 only limits me on total projects (which I can delete) - so ?unlimited.

/content/images/2025/01/lovable-07.png

And I can go to faster higher limits and attachments (actually that attachment size would be nice) with Premium at US$20/month

/content/images/2025/01/lovable-08.png

Now, we must consider a bit of motivations - Vercel would likely give some good prices on v0 since they really want me to host on Vercel which, if you build a full featured app, would prompt that.

Usage

Let’s try and build on our last app by asking Lovable to make a Timeline view

Here we can see the image I’ll feed it for a basic wireframe of what i want

/content/images/2025/01/Notes_241230_111347.jpg

My hope was to feed it the JSON files we already had to make it easier to migrate to our existing structure, but sadly the attachments only allow JPG and PNG files

/content/images/2025/01/lovable-09.png

I really want to enable this to succeed with the fewest prompts possible. Here is what I ended up with for a prompt:

Create and implement a user interface for a Resume app that is as similar as possible to the attached image. This screenshot shows a layout issue on mobile. Adjust margins and padding to make it responsive while maintaining the same design structure. The data for the app should come from experiences in a JSON format with fields companyName, companyLogo, location, startDate, title, categories, description and user details in a JSON format with fields firstName, lastName, title. email, phone, addres, photo. The values are all strings. The values in companyLogo and photo are URLs to images. Include a Dockerfile that can build and expose the app on port 3000.

/content/images/2025/01/lovable-10.png

Let’s see how it handles it

While I keep getting errors, I don’t want to neccessarily attribute that to Lovable. I’m in a spotty wifi area as I write presently and it could be me at fault here

/content/images/2025/01/lovable-11.png

I tried other orgs but they also errored.

Deploy

Let’s see where we can get with “Deploy. In the free tier, we can only publish to Public

/content/images/2025/01/lovable-12.png

This built into https://cv-optimizer.lovable.app/

/content/images/2025/01/lovable-13.png

Firefox also errored. I moved to Google since that rarely has issues, at least for an IdP.

That suggested a malformed request

/content/images/2025/01/lovable-14.png

Being stuck

Here is where I am just stuck. I can view some of the files

/content/images/2025/01/lovable-15.png

But I cannot view just the code, or download it. There is no editor from what I can see. Everything about Edit requires Github and if that is down, we are stuck.

/content/images/2025/01/lovable-16.png

What if I am in a slow location? What if I chose to use Gitlab, or Forgejo or Gitea or Codeberg. I might even want to build and edit in Azure DevOps with Azure Repos or just use my own local git with GIT SSH.

The assumption that it’s Github (or nothing) is a real limiter for something that, at least at a first pass, looks really nice.

Try again

You’ll note that even if I could connect to Github, that App looked nothing like my image and certainly was not a timeline view.

Let’s try a simpler prompt

/content/images/2025/01/lovable-17.png

This did use Pins for icons, so I can see how that is similar but it is not what I wanted

/content/images/2025/01/lovable-18.png

I tried a new user, new Github Identity and the public wifi to take my hotspot out of the equation and it still errored on me

/content/images/2025/01/lovable-19.png

Now when I check Github Status it would appear things have gone to poo there at the moment

/content/images/2025/01/lovable-20.png

So this could just be bad timing on my part - but still, locking us in to only one provider and giving no editor or zip download really blocks us for doing anything about it.

I should say that coming back to ask about making it horizontal did seem to update the view a bit

/content/images/2025/01/lovable-21.png

Github

After a lot of tries and after Github Status showed all green, I finally got it to connect

/content/images/2025/01/lovable-22.png

I did a “Create in” my own area

/content/images/2025/01/lovable-23.png

which now has a URL to clone

/content/images/2025/01/lovable-24.png

Code

We can see the Tech stack from Readme.md

This project is built with .

  • Vite
  • TypeScript
  • React
  • shadcn-ui
  • Tailwind CSS

By default, it is private, but I can change it to public so you can view it here.

I can see the files:

/content/images/2025/01/lovable-25.png

I cloned and built it locally

/content/images/2025/01/lovable-26.png

Let’s now test a local run

/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/01/09 03:07:28 [notice] 1#1: using the "epoll" event method
2025/01/09 03:07:28 [notice] 1#1: nginx/1.27.3
2025/01/09 03:07:28 [notice] 1#1: built by gcc 13.2.1 20240309 (Alpine 13.2.1_git20240309)
2025/01/09 03:07:28 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
2025/01/09 03:07:28 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/01/09 03:07:28 [notice] 1#1: start worker processes
2025/01/09 03:07:28 [notice] 1#1: start worker process 29
2025/01/09 03:07:28 [notice] 1#1: start worker process 30
2025/01/09 03:07:28 [notice] 1#1: start worker process 31
2025/01/09 03:07:28 [notice] 1#1: start worker process 32
2025/01/09 03:07:28 [notice] 1#1: start worker process 33
2025/01/09 03:07:28 [notice] 1#1: start worker process 34
2025/01/09 03:07:28 [notice] 1#1: start worker process 35
2025/01/09 03:07:28 [notice] 1#1: start worker process 36
2025/01/09 03:07:28 [notice] 1#1: start worker process 37
2025/01/09 03:07:28 [notice] 1#1: start worker process 38
2025/01/09 03:07:28 [notice] 1#1: start worker process 39
2025/01/09 03:07:28 [notice] 1#1: start worker process 40
2025/01/09 03:07:28 [notice] 1#1: start worker process 41
2025/01/09 03:07:28 [notice] 1#1: start worker process 42
2025/01/09 03:07:28 [notice] 1#1: start worker process 43
2025/01/09 03:07:28 [notice] 1#1: start worker process 44
172.17.0.1 - - [09/Jan/2025:03:07:30 +0000] "GET / HTTP/1.1" 200 647 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
172.17.0.1 - - [09/Jan/2025:03:07:30 +0000] "GET /assets/index-Cc8Na4BH.js HTTP/1.1" 200 306841 "http://localhost:3033/"

which works great

/content/images/2025/01/lovable-27.png

Exposing in Kubernetes

Let’s first to dockerhub

builder@DESKTOP-QADGF36:~/Workspaces/cv-optimizer$ docker tag  cv-optimizer:0.1 idjohnson/cv-optimizer:0.1
builder@DESKTOP-QADGF36:~/Workspaces/cv-optimizer$ docker push idjohnson/cv-optimizer:0.1
The push refers to repository [docker.io/idjohnson/cv-optimizer]
4cb6588057e6: Pushed
5ea0c9f16ce9: Pushed
5a760029e979: Mounted from library/nginx
23625999797d: Mounted from library/nginx
9aa22afcf27f: Mounted from library/nginx
59a5cb944b91: Mounted from library/nginx
598e577f3a23: Mounted from library/nginx
fd5f65a144ef: Mounted from library/nginx
a8903c9578e9: Mounted from library/nginx
ce5a8cde9eee: Mounted from library/nginx
0.1: digest: sha256:7252de46872656ff39da89a724c4f1ad488e5ce1ef0f8dde1c75fd44824190fe size: 2406

I’m going to use the Mistral LLM on a local Ollama to create a kubernetes manifest (i replaced the markdown backticks with dashes)

builder@bosgamerz9:~$ ollama run mistral
>>> create a kubernetes YAML manifest with a deployment of the image idjohnson/cv-optimizer:0.1 that exposes port 3000 and a service that exposes port
...  80 using ClusterIP
 Here's a simple Kubernetes YAML manifest for a Deployment and Service to run the `idjohnson/cv-optimizer:0.1` image, exposing port 3000 on the
pod and creating a ClusterIP service to expose port 80.

'''yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cv-optimizer-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: cv-optimizer
  template:
    metadata:
      labels:
        app: cv-optimizer
    spec:
      containers:
      - name: cv-optimizer
        image: idjohnson/cv-optimizer:0.1
        ports:
        - containerPort: 3000
          name: http
---
apiVersion: v1
kind: Service
metadata:
  name: cv-optimizer-service
spec:
  selector:
    app: cv-optimizer
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
'''

This YAML file contains two resources, a Deployment and Service. The Deployment will create three pods with the `idjohnson/cv-optimizer:0.1`
image, listening on port 3000 within each pod. The Service, of type ClusterIP, routes traffic to these pods via port 80, allowing communication
between them only within the cluster.

You can apply this YAML file using `kubectl apply -f <filename>` in your terminal.

I can now test it locally

builder@DESKTOP-QADGF36:~$ kubectl apply -f ./test.yaml
deployment.apps/cv-optimizer-deployment created
service/cv-optimizer-service created

I can now test

builder@DESKTOP-QADGF36:~$ kubectl port-forward svc/cv-optimizer-service 3034:80
Forwarding from 127.0.0.1:3034 -> 3000
Forwarding from [::1]:3034 -> 3000
Handling connection for 3034
Handling connection for 3034

/content/images/2025/01/lovable-28.png

Exposing with Ingress and TLS

I’ll create an A Record in Azure DNS

$ az account set --subscription "Pay-As-You-Go" && az network dns record-set a add-record -g idjdnsrg -z tpk.pw -a 75.73.224.240 -n cv-optimizer
{
  "ARecords": [
    {
      "ipv4Address": "75.73.224.240"
    }
  ],
  "TTL": 3600,
  "etag": "b079c063-ad3d-49d2-9270-c47b73a68448",
  "fqdn": "cv-optimizer.tpk.pw.",
  "id": "/subscriptions/d955c0ba-13dc-44cf-a29a-8fed74cbb22d/resourceGroups/idjdnsrg/providers/Microsoft.Network/dnszones/tpk.pw/A/cv-optimizer",
  "name": "cv-optimizer",
  "provisioningState": "Succeeded",
  "resourceGroup": "idjdnsrg",
  "targetResource": {},
  "trafficManagementProfile": {},
  "type": "Microsoft.Network/dnszones/A"
}

Now let’s expose it

$ cat test.ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: azuredns-tpkpw
    ingress.kubernetes.io/ssl-redirect: "true"
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
  name: cv-optimizeringress
spec:
  rules:
  - host: cv-optimizer.tpk.pw
    http:
      paths:
      - backend:
          service:
            name: cv-optimizer-service
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - cv-optimizer.tpk.pw
    secretName: cv-optimizer-tls

$ kubectl apply -f ./test.ingress.yaml
ingress.networking.k8s.io/cv-optimizeringress created

When the cert is ready

$ kubectl get cert cv-optimizer-tls
NAME               READY   SECRET             AGE
cv-optimizer-tls   True    cv-optimizer-tls   88s

We can now test at https://cv-optimizer.tpk.pw/

/content/images/2025/01/lovable-29.png

Using Copilot Free

I’ll next pull the code down locally and launch VS Code

builder@LuiGi:~/Workspaces$ git clone https://github.com/idjohnson/cv-optimizer
Cloning into 'cv-optimizer'...
remote: Enumerating objects: 106, done.
remote: Counting objects: 100% (106/106), done.
remote: Compressing objects: 100% (83/83), done.
remote: Total 106 (delta 16), reused 106 (delta 16), pack-reused 0 (from 0)
Receiving objects: 100% (106/106), 381.72 KiB | 3.15 MiB/s, done.
Resolving deltas: 100% (16/16), done.
builder@LuiGi:~/Workspaces$ cd cv-optimizer/
builder@LuiGi:~/Workspaces/cv-optimizer$ code .

The older VS Code’s had you install an extension to use Copilot but if you launched a current version, you’ll now see the Copilot icon up near the middle top. Clicking the drop-down will show “Use AI Features with Copilot for Free”.

/content/images/2025/01/lovable-30.png

I can then enable by clicking the button

/content/images/2025/01/lovable-31.png

In one case I had VS Code prompt me to continue

/content/images/2025/01/lovable-32.png

and in another it just prompted me to sign-in (with full MFA of course)

/content/images/2025/01/lovable-33.png

Updating

One of the issues I see right away is that this Dockerfile builds a static Vite app

/content/images/2025/01/lovable-34.png

If I hop on a pod, for instance we can see its just a basic index.html hosted by Nginx and some very large Javascript files

/usr/share/nginx/html/assets # ls
index-C_nyZYQl.css  index-Cc8Na4BH.js
/usr/share/nginx/html/assets # cd ..
/usr/share/nginx/html # cat index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>cv-optimizer</title>
    <meta name="description" content="Lovable Generated Project" />
    <meta name="author" content="Lovable" />
    <meta property="og:image" content="/og-image.png" />
    <script type="module" crossorigin src="/assets/index-Cc8Na4BH.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/index-C_nyZYQl.css">
  </head>

  <body>
    <div id="root"></div>
    <script src="https://cdn.gpteng.co/gptengineer.js" type="module"></script>
  </body>
</html>
/usr/share/nginx/html # cat assets/index-C
index-C_nyZYQl.css  index-Cc8Na4BH.js
/usr/share/nginx/html # cat assets/index-C
index-C_nyZYQl.css  index-Cc8Na4BH.js
/usr/share/nginx/html # cat assets/index-Cc8Na4BH.js
var ac=e=>{throw TypeError(e)};var qs=(e,t,n)=>t.has(e)||ac("Cannot "+n);var N=(e,t,n)=>(qs(e,t,"read from private field"),n?n.call(e):t.get(e)),q=(e,t,n)=>t.has(e)?ac("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),W=(e,t,n,r)=>(qs(e,t,"write to private field"),r?r.call(e,n):t.set(e,n),n),Te=(e,t,n)=>(qs(e,t,"access private method"),n);var ni=(e,t,n,r)=>({set _(o){W(e,t,o,n)},get _(){return N(e,t,r)}});function hv(e,t){for(var n=0;n<t.length;n++){const r=t[n];if(typeof r!="string"&&!Array.isArray(r)){for(const o in r)if(o!=="default"&&!(o in e)){const i=Object.getOwnPropertyDescriptor(r,o);i&&Object.defineProperty(e,o,i.get?i:{enumerable:!0,get:()=>r[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const s of i.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(o){if(o.ep)return;o.ep=!0;const i=n(o);fetch(o.href,i)}})();function af(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var uf={exports:{}},ys={},cf={exports:{}},Y={};/**
 * @license React
 * react.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.

...

If we scroll near the bottom of them we can see some of our address and work history details buried in there

/content/images/2025/01/lovable-35.png

The question becomes - can Copilot pull that out to runtime instead of compile time?

Let’s try together:

It was interesting there at the end that when I was about to nudge it to update the tsx file for the Dockerfile path, upon accepting the proposed change, it corrected it automatically

I tried to build and test

builder@LuiGi:~/Workspaces/cv-optimizer$ docker run -p 8034:3000 cv-optimizer:0.2
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/01/10 00:30:05 [notice] 1#1: using the "epoll" event method
2025/01/10 00:30:05 [notice] 1#1: nginx/1.27.3
2025/01/10 00:30:05 [notice] 1#1: built by gcc 13.2.1 20240309 (Alpine 13.2.1_git20240309)
2025/01/10 00:30:05 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
2025/01/10 00:30:05 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/01/10 00:30:05 [notice] 1#1: start worker processes
2025/01/10 00:30:05 [notice] 1#1: start worker process 29
2025/01/10 00:30:05 [notice] 1#1: start worker process 30
2025/01/10 00:30:05 [notice] 1#1: start worker process 31
2025/01/10 00:30:05 [notice] 1#1: start worker process 32
2025/01/10 00:30:05 [notice] 1#1: start worker process 33
2025/01/10 00:30:05 [notice] 1#1: start worker process 34
2025/01/10 00:30:05 [notice] 1#1: start worker process 35
2025/01/10 00:30:05 [notice] 1#1: start worker process 36
2025/01/10 00:30:05 [notice] 1#1: start worker process 37
2025/01/10 00:30:05 [notice] 1#1: start worker process 38
2025/01/10 00:30:05 [notice] 1#1: start worker process 39
2025/01/10 00:30:05 [notice] 1#1: start worker process 40
2025/01/10 00:30:05 [notice] 1#1: start worker process 41
2025/01/10 00:30:05 [notice] 1#1: start worker process 42
2025/01/10 00:30:05 [notice] 1#1: start worker process 43
2025/01/10 00:30:05 [notice] 1#1: start worker process 44
172.17.0.1 - - [10/Jan/2025:00:30:18 +0000] "GET / HTTP/1.1" 200 647 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
172.17.0.1 - - [10/Jan/2025:00:30:19 +0000] "GET /assets/index-TkCKc56C.js HTTP/1.1" 200 307027 "http://localhost:8034/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
172.17.0.1 - - [10/Jan/2025:00:30:19 +0000] "GET /assets/index-C_nyZYQl.css HTTP/1.1" 200 56963 "http://localhost:8034/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
172.17.0.1 - - [10/Jan/2025:00:30:19 +0000] "GET /usr/share/nginx/html/experiences.json HTTP/1.1" 200 647 "http://localhost:8034/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
172.17.0.1 - - [10/Jan/2025:00:30:19 +0000] "GET /favicon.ico HTTP/1.1" 200 15086 "http://localhost:8034/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"
172.17.0.1 - - [10/Jan/2025:00:30:35 +0000] "GET /assets/index-C_nyZYQl.css HTTP/1.1" 304 0 "http://localhost:8034/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" "-"

But clearly it is trying to pull from local path as a URL in the browser

/content/images/2025/01/lovable-36.png

I don’t need an AI to show me how that is off and what it should be

/content/images/2025/01/lovable-37.png

I fixed the line and built again

/content/images/2025/01/lovable-38.png

This now gives me a whole new errored

/content/images/2025/01/lovable-39.png

Copilot had some more suggestions

/content/images/2025/01/lovable-40.png

I worked this for a while, but in the end, the gptengineer.js file, even when copied locally, has way to many hardcoded network paths

Try agian

/content/images/2025/01/lovable-41.png

I went back to Lovable.dev to ask for another report, but this time I wanted to be exacting

I first uploaded some example files to a shared UR

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-42.png

Create a resume app with a horizontally displayed timeline. It should consume the users details from a public endpoint (https://freshbrewed.science/user.json) and user resume entries from a public endpoint (https://freshbrewed.science/experiences.json). There should be a Dockerfile to host the app that sets those endpoint URLs so that they are configurable with a passed in environment variable. However, for this example those values can be hardcoded in the Dockerfile for now. Thank you.

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-43.png

Interestingly, this fired up but showed a bit error in Lovable

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-44.png

I asked it to automatically correct the error

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-45.png

still no go…

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-46.png

I tried again..

Let’s try locally. I’ll copy over to Github (this time it worked so perhaps that first night was indeed Github’s fault)

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-47.png

I pulled it down but I didn’t see seperate URLs for the JSON, but I did see a root API url in the Dockerfile

builder@LuiGi:~/Workspaces/timeline-resume-masterpiece$ ls
Dockerfile  components.json   nginx.conf         postcss.config.js  tailwind.config.ts  tsconfig.node.json
README.md   eslint.config.js  package-lock.json  public             tsconfig.app.json   vite.config.ts
bun.lockb   index.html        package.json       src                tsconfig.json
builder@LuiGi:~/Workspaces/timeline-resume-masterpiece$ cat Dockerfile
FROM node:18-alpine as builder

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

ENV API_URL=https://freshbrewed.science

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]b

But it seems it does not actually use that var

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-48.png

In fact, what it appears to have done is just use a Proxy Pass in the NGinx config to make the app “see” them on /user.json and /experiences.json

\wsl.localhost\Ubuntu\home\builder\Workspaces\jekyll-blog\content\images\2025\01\lovable-49.png

Lovable Copilot AI Docker Kubernetes VSCode

Have something to add? Feedback? You can use the feedback form

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes