AI-coding can get a little crazy.
Vibe coding has taken on a life of its own, and as a company that builds a lot of stuff with human-written code, we have some thoughts.
We think AI is an excellent tool and one that’s definitely part of the new zeitgeist. That said, we think there’s a difference between using AI to extend human thinking and outsourcing it entirely.
This new series will share our experiments taking our human-written code and building AI-generated code through LLM (Large Language Model) prompting on top of it.
The Goal: to explore how far AI can support real development conditions and to understand where human oversight remains essential for accuracy and reliability.
In these posts, we’re breaking down the process step by step and sharing what we prompted, what worked, what didn’t, and how we kept product integrity and performance at the center of it all.
What We Built
In this experiment we integrated a personal google calendar into Ruoom’s native calendar application.
Since the core open source code of Ruoom is a CRM, this kind of integration tests how flexible the system can be when connecting to external data sources.
Meetings, time blocks, and personal obligations affect availability, but a CRM usually has no visibility into that. By syncing a Google Calendar, the system can reference a more complete view of time before creating events or assigning tasks, which is especially useful if the feature is being built for a small business or freelancer.
From a developer’s perspective, aside from creating something your client would definitely find useful, building this integration is a practical exercise in interoperability. Many client projects will require connecting to existing ecosystems—Google Workspace, Microsoft, Notion, Slack, etc.—rather than reinventing them. Syncing calendars is a way to test how your CRM handles external APIs, authentication flows, and data normalization when the source of truth lives somewhere else.
What You’ll Need
If you plan to follow what we did as you go through this blog, here are the tools you’ll need:
- Our core open source code. It’s free and you can download it here.
- Python, Django, PostgreSQL, and the other code dependencies. We provide a tutorial for our basic install here.
- The Windsurf editor.
How to Install and Run Our Core Code
As a pre-requisite to vibe-coding on top of our core code, you should get our core code up and running. We provide an introduction to Django using our core code as an example in this YouTube video. In the video, we outline cloning our repository, building a PostgreSQL database for the application, and starting the application for the first time.
You’re ready for the next step when you can see the home page in a browser window.

Open the AI-driven development tool
Once you’ve downloaded Windsurf or a similar AI-driven development tool, open the parent folder of the code:

You’ll want to configure it with the LLM you’d like to use.
For this blog, we used GPT-5 (low reasoning). Some models can be more or less expensive to use, per token. One reason we like Windsurf is because their subscription model includes a bundle of tokens each month to use against various models, and we’ve never had to re-fill our token balance during a heavy session.

Let’s Begin By Defining the Feature Request
Any time you are building a product, you must start with a well-defined scope and set of requirements.
Our objective is to evaluate LLM prompting (“vibe coding”) for its ability to build a feature on its own with minimal guidance. For this task, we will ask the LLM to integrate a personal Google Calendar into our application’s native calendar page.
The base Ruoom CRM includes a blank calendar designed to be extended through plugins or custom development.

For a Google Calendar integration, we will define the following scope:
- The user must be able to connect their personal Google Calendar account
- The “Schedule” page in our application must display the user’s Google Calendar events (no need to publish events back to Google Calendar)
Understanding the nature of the problem
The scope is simple, but it’s important to understand the complexity of what we are asking the LLM to do. For instance, is it going to navigate authentication with Google? We believe it’s important to always have an understanding of what the LLM is building while you vibe-code. For this reason, the very first prompt is a request to understand the scope of the challenge:
Prompt:
I have a calendar page in my app, displayed within schedule.html. I want to populate this calendar with events that are in my personal Google calendar. What steps would I take to import & sync my Google calendar into the calendar of my app?
Response:
To pull personal Google Calendar events (private), use OAuth on the backend and expose a JSON endpoint that your FullCalendar page can call.
Below are two approaches. Option A is quick if your calendar is public; Option B is the robust solution for private/personal calendars.
Option A (fast, public calendar only)
Use ICS feed: In Google Calendar, make the calendar public and copy the “Secret address in iCal format”. Add it as an event source in FullCalendar (FullCalendar can ingest ICS if you parse it on the server, or via a 3rd-party ICS converter endpoint you control).
If you need private access, use Option B.
Option B (recommended: OAuth2, private read)
1) Google Cloud setup
Create project in Google Cloud Console.
Enable API: “Google Calendar API”.
OAuth consent screen: External, add scope https://www.googleapis.com/auth/calendar.readonly.
Create OAuth client: Type “Web application”.
Authorized redirect URI: e.g. https://your-domain.com/google/oauth/callback (and your local dev URL).
Capture Client ID and Client Secret.
Note: We’ll explain this in the next section.2) Add dependencies
…
(Author’s Note: we’ll use “…” to indicate where the LLM provided instructions, but we haven’t included them in this blog. To download the full transcript you can do so here.)
3) Store user credentials
…
4) OAuth endpoints for Google Cloud
URLs:
GET /google/oauth/start — starts the OAuth flow.
GET /google/oauth/callback — receives code, exchanges for tokens, stores credentials on request.user.profile.
…
5) Backend events endpoint for FullCalendar
Endpoint: GET /administration/schedule/google-events
Logic: …
Response: JSON list of events in FullCalendar’s format.
6) Frontend changes in schedule.js
Keep your existing events_list for internal items.
Add an additional event source that points to your new endpoint.
…
This preserves internal events and overlays Google events.
7) UI/UX on schedule.html
Connect/Disconnect button:
If profile.google_sync_enabled is false, show “Connect Google Calendar” button linking to /google/oauth/start.
If connected, show status and a “Disconnect” action (clears stored credentials).
Optional filter toggle to show/hide Google events.
8) Edge cases and testing
…
[End Response]
Ok, so we have a good understanding of what the LLM is intending to build.
However, we have a few concerns about whether it’ll truly be able to authenticate with a personal Google Calendar.
What if Google requires my app to be running on an internet-facing HTTPS connection instead of my local development server? Let’s investigate:
Prompt:
Earlier, you had specified that I create my Google Clout OAuth app, and in doing so to add “Authorized redirect URI: e.g. https://your-domain.com/google/oauth/callback (and your local dev URL).” I am going to be testing this locally with url localhost. Is this going to be an issue? Does this need to be running in the cloud for it to work?
Response:
No, it doesn’t need to run in the cloud. You can develop and test entirely on localhost.
Google allows http for localhost. However, your Django settings prevent cookies from being set over plain HTTP, which can break login/OAuth on localhost.
You have two options:
Run HTTPS locally using django-sslserver
Or
Temporarily set SESSION_COOKIE_SECURE = False and CSRF_COOKIE_SECURE = False for local development only.
[End Response]
We’re going to go with the second option, and we’ll tell it so in the response
To begin, we will need to build the Google Cloud app while the LLM adapts the codebase. A fair(ish) way to divide the work, we’d say. Sometimes the LLM needs quite a bit of time to code and that’ll give us time to work. The next prompt:
Prompt:
Great! Now I understand. We will do Option B with a private calendar, and I will create the Oauth app. Can you go ahead and make all of the project file edits required to build this feature?
Response:
I will update multiple parts of your Django project to implement Google Calendar OAuth and event syncing:
…
Changes implemented:
…
What you still need to configure:
…
How to apply and test:
…
Notes and considerations:
…
[End Response]
At this point, the LLM has made all the changes it thinks it needs to make. But before you test, you’ll need to configure the Google Cloud OAuth app to enable access to our calendar.
Configuring Google Cloud
As the LLM said earlier, we’ll need to enable and configure the Google Calendar API in Google Cloud. First, create a new app within the Google Cloud console:
First, create a new app within the Google Cloud console:

Next, enable the Google Calendar API:

Then, configure OAuth to be External:
Note: For this exercise, you’ll have to use the “Test Mode” in Google Cloud to avoid going through Google’s external app review process. Simply provide the target Google Calendar account as the designated test account.

Next, you’ll need to add Scope “https://www.googleapis.com/auth/calendar.readonly” to OAuth

Then create the OAuth client as “Web Application”

And then configure the JavaScript origin (http://localhost:8000) and redirect URI (http://localhost:8000/administration/google/oauth/callback) in the client:

That’s everything the LLM told us to do.
Testing the Changes
Now it’s time to test the changes the LLM made to the app.
First, run a Django migration to update the database with the new properties added by the LLM:
python manage.py migrate
Then restart the server and navigate back to the Schedule page and you should see this:

You should notice a new button at the top which the LLM has added for us to connect the Google Calendar.
Click the button and…
… no change.
Did we fail? Let’s ask the LLM what’s happening:
Prompt:
This is great, and the button appears as desired. However, I don’t think we have correctly connected ourselves to my new Google Cloud app. Where do I go to configure this connection?
Response:
Here’s exactly where and how to configure your Google Cloud connection.
Where to configure:
[Google Cloud Console]
…
[Project settings file]
- In ruoom/settings.py
- Find GOOGLE_OAUTH_CLIENT_CONFIG.
- Replace placeholders:
- “client_id”: “YOUR_CLIENT_ID”
- “client_secret”: “YOUR_CLIENT_SECRET”
- Optional: Use environment variables instead of hardcoding
- $env:GOOGLE_CLIENT_ID=”…”; $env:GOOGLE_CLIENT_SECRET=”…”;
- We already read these in ruoom/settings.py
After configuring
- Restart the Django server.
- Go to /administration/schedule/.
- Click “Connect Google Calendar.”
[End Response]
Okay, so it looks like we never actually configured the Google Cloud API keys in the Django App. Human Error. That’s one win for the machine.
One thing we’ll go over in another blog is evaluating how we can use LLM prompting to better handle errors like this one. We would want the application to tell us that there were no API credentials configured.
Anyway, after configuring the API keys, we again click “Connect Google Calendar”. If the OAuth app is configured correctly, you are taken to the Google Authentication page:

Click “Allow”.
We should automatically be taken back to the Schedule page.
What do we see?

Still nothing.
One point against the machine and we’re now tied. Let’s figure this out by going back and forth with the LLM:
Prompt:
It looks like google_sync_enabled is not being set to true, so the button never says “Google Calendar Connected”
Response:
I’ve hardened the OAuth handlers so the “Connected” badge should now reflect correctly.
What I changed
…
[End Response]
Frustratingly, it still doesn’t work.
The machine is losing now, with 2 mistakes to our 1.
Prompt:
I get the error at gcal.py line 90: oauthlib.oauth2.rfc6749.errors.InsecureTransportError: (insecure_transport) OAuth 2 MUST utilize https.
Response:
You’re hitting oauthlib’s HTTPS requirement for OAuth. Two ways to fix it locally:
Recommended options
Option A (quickest): allow HTTP in dev
Set an env var before running the server:
PowerShell (current session):
$env:OAUTHLIB_INSECURE_TRANSPORT = “1”
Option B (more “proper”): run HTTPS locally
…
[End Response]
Okay, so it wasn’t a code error but another configuration error. 2-2, tie game.
No we’ll run the PowerShell command it suggests to tell our server to allow insecure HTTP endpoints, before attempting another “Connect Google Calendar”:

Holy $h!t!
In all honesty, we didn’t expect it to work on the first (or really fourth) try.
Despite the configuration issues that were really our own fault, the LLM created a working feature by seamlessly integrating into our existing human-built application. That impressed us, but with one big caveat:
At this stage we have done no review of the code to make sure it conforms to our conventions and standards within the project, or is able to handle edge cases or failures.
An why would we care about doing this?
It seems simple to ask an LLM to build out all the features you want in your project. However, without a human guiding the design conventions and central architecture, it’s easy for your project to become a mess of spaghetti code as each feature is added on top of the last one. Your application will start to fail as features clash and the LLM is unlikely to build a comprehensive test suite.
We found this to be a common issue online, as summarized by Reddit user u/Sad_Impact9312:

So in the next blog, we’ll review the AI-generated code we just built into this project. See you in the next one.