# Project export: vly.ai: the bubble.io killer

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: Generate Full-Stack SaaS Apps with just 1 click using AI.
- Devpost: https://devpost.com/software/vly-ai-the-bubble-io-killer
- GitHub: https://github.com/victorxheng/treehacks
- Result: winner (Reflex: Best Use of Reflex ($2k Cash))
- Team: 2 GitHub contributor(s) — Mehul-Gandhi (7 commits), Victor Cheng (2 commits)

## Devpost submission (written by the team)

### Overview

We generate full-stack web apps optimized for SaaS use cases (front end, back end, integrations such as stripe, email, texting, and more) completely using AI, without the need for any programming knowledge. going for: best use of AI Agents / AI project, best use of Reflex, most viable startup / most commercially viable startup (YC, pear, etc) This is a no-code system that converts our very own natural language programming framework into full-stack reflex-based code, allowing us to achieve unparallel performance from raw code without the tradeoffs of a no-code system. This means unlimited flexibility and scalability on enterprise-grade software all generated using AI. We quite literally replace the need to hire a web developer. built by stanford, berkeley, uw cs students. majority first hackathon project (beginner hack) THE PROBLEM: Building a SaaS web application is hard. If you were trying to build one, here are your options: Hiring a developer or agency: a. $10,000-$100,000, 2-6 months b. Expensive to iterate, prone to miscommunication Hiring a developer or agency: a. $10,000-$100,000, 2-6 months b. Expensive to iterate, prone to miscommunication Developing an app on your own: a. Free + Software costs, 2-12 months b. Requires significant amounts of personal time, not many people can do it Developing an app on your own: a. Free + Software costs, 2-12 months b. Requires significant amounts of personal time, not many people can do it Using a no-code tool like bubble.io: a. Free + Software costs, 1-6 months b. Highly restrictive and limited, and learning curve requiring lots of time Using a no-code tool like bubble.io: a. Free + Software costs, 1-6 months b. Highly restrictive and limited, and learning curve requiring lots of time Hiring a no-code developer or agency: a. $5,000-$50,000, 1-4 months b. Still highly restrictive and limited, prone to miscommunication Hiring a no-code developer or agency: a. $5,000-$50,000, 1-4 months b. Still highly restrictive and limited, prone to miscommunication THE SOLUTION: vly.ai A component-based natural language framework that takes specific saas project ideas and turns them into code. Through our framework, we are able to laser focus on specific features exactly the way the user wants it to be. These features can be produced reliably through our component-based system. Essentially: we abstract layer by layer. This allows us to not rely on AI to produce bottom-level code (it can be inaccurate). Finally: our abstractions and context system makes it very easy for AI to understand the code base and locate edits. What sets us apart Here is how we stand compared to other tools out there trying to solve the same thing. Reliable and robust without the technical issues Scales effectively in size and complexity Significantly faster load times and optimizations not possible in no-code More flexibility and complexity in terms of what can be produced Faster integration of external APIs and capabilities Automatic generation of front end and back end code not possible in no-code Ownership of code and the ability to export and expand Our solution also maintains the benefits of a no-code system: Automatic deployment and hosting on the web for both front and back end Automatic scaling and optimization User-friendly environment for interacting with data Ability to make changes quickly and re-deploy instantly Our solution builds what a no-code tool can build, but in hours instead of months: You can build enterprise-grade software with unlimited features custom to exactly what you need: CRM systems Custom Internal Tools Niche platforms Dashboards and client portals Interfaces on data GPT integrations and wrappers on custom data Marketplaces, web apps, and more SaaS applications for founders to launch and make money We also allow business owners to create custom software at dirt cheap costs. So instead of paying for 5 subscriptions to manage your business, you can now combine everything into 1 super-app, such as the following: Managing Employee Payroll Tracking hours POS and inventory tracking Front site and processing orders Here is how our treehacks project operates differently attention is all you need We mean context. You can't just say: "build me a full stack blogging site" and expect the AI to produce the next Medium. You need to be specific. As specific as possible. You need to describe every page, feature, and component, or else it may not give you what you want, and most of the times, the AI doesn't have the capacity to build out this much logic on its own. So, here's the process: User enters a broader prompt The AI conversationally details the prompt and reviews it with the user This cycle repeats for a description and a list of features & user flow Then, the AI helps build out in natural language the database schema Process continues to write descriptions for each page, then all the way down to a component level Eventually, you create one giant configuration file split up from the top (being more context related) to the bottom (being more specific to exact operations). What you have at the bottom isn't too far off from just using Reflux and calling pre-built components with pre-defined parameters. This form of abstraction makes it much more straightforward for the AI. The .vly programming language We standardized the format of this config file and optimized its AI-friendliness to where it's pretty much become it's own language. It's now called the vly programming language (with .vly file extensions) that uses natural language arranged in an intuitive format. This allows people with no programming knowledge to write out what they want in immense detail for our AI to implement. This specificity is required to ensure that the level of depth and complexity desired is reached; something current AI code generators lack. This also is how we seperate ourselves in comprehensiveness. AI-Agent specific capabilities Due to the specificity of the reflex framework, we need to prompt engineer different AI agents for each step of the process to specifically produce what we need. For example, we have one agent for configuring specifically the database based on the .vly framework. We have others for different parts of the process, from selecting and implementing components in our library. Also, the limited component library requires the generation of the vly language to choose from the existing library, fed through directly into the system message. The AI then knows the exact way to implement each library, which is in the form of a function with parameters. Component Library The limitation is that we rely on pre-built components rather than components built on the fly. We chose this route because we didn't want to rely on AI to write bottom-level code; you definitely don't want the AI to be writing your stripe payments scripts. Integrated SaaS Specific Technologies We reliably integrate Stripe, email, text, and more into our tech stack. The vertical approach we take allows us to ensure correctness in our work and creates reliability albeit sacrificing flexibility in the short term. Use of Reflex and language abstraction Our full-stack web app uses reflex to allow for simple intuitive abstraction of web applications. Rather than verbose systems seen in next.js, reflex abstracts all of it for us already so that the AI can have a lot more focus on the higher level operations rather than the specific syntax. We are highly committed to turning this venture into a startup company. We have contacted clients already to build projects for to raise funds and expand our component library. We hope to someday be able to generate software cheaper, faster, and more reliable than other companies to bring consumers technologies fit for their needs that don't cost large sums of money. Expanding library of components We are actively working on expanding the capabilities of the AI to be able to tackle more and more components and external specific features based on demand from clients. This could mean instant implementation of large-level features that often replace existing tools. All potential prize money will go towards funding this project and the extension.

## README (from the GitHub repository)

# treehacks





# THE PLAN


- Parse a list of actions that replicate the twitter interface



Checklist:
- Project Setup
- Page Definitions
- Basic UI Setup
- States setup for user auth
- Create context for documentation and actions


# top level interface

- Defines all the pages
- README that defines the pages, purposes, etc
- High level breakdown
- calls functions and renders objects on components further down


# second level components
- Functions: implements the functions called by the top level, as well as necessary fetching of data
- defines components being used
- Comes with ReadME defining all the functions available and its uses
- Defines each page's states???





# process:

Requires:

python3 -m venv .venv
source .venv/bin/activate
pip install reflex
reflex init


then run and deploy






Notes:

rx.config.py file defines the app name and ports. can be replaced by .env file


Generation:
Starts with UI components
Adds dependencies to a stack (abstractions that need to be implemented in the second pass)
Implements abstractions





Checklist:

1. GPT To write the schema from a config description of the schema
2. To get GPT to define the pages from the config layout through reflex syntax
3. Get GPT to define the necessary UI components it needs for each page based off of an existing list of pre-built UI components passed through as context

Goes page by page from the configuration file



4. Actions, data, user auth, events, conditions

## Detected evidence (automated analysis)

Indexed codebase: 45 recognized source files, 61 KB.
- Express (technology) — detected in the code
- JavaScript (language) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- Tailwind CSS (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (53 of 53)

```
compiler_agents.py
embeddings.ipynb
language.md
prompt_agents.py
README.md
server/data/frontend.json
server/data/prompt1.txt
server/data/server.json
server/functions/addFrontendFiles.js
server/functions/addServerFiles.js
server/functions/create-structure.js
server/index.js
server/package.json
server/server_example/controllers/authController.js
server/server_example/controllers/commentController.js
server/server_example/controllers/postController.js
server/server_example/middlewares/authMiddleware.js
server/server_example/models/commentModel.js
server/server_example/models/postModel.js
server/server_example/models/userModel.js
server/server_example/routes/authRoutes.js
server/server_example/routes/commentRoutes.js
server/server_example/routes/postRoutes.js
server/server_example/services/authService.js
server/server_example/services/commentService.js
server/server_example/services/postService.js
server/server_example/utils/database.js
server/src_example/components/CommentList.js
server/src_example/components/PostList.js
server/src_example/components/SignInButton.js
server/src_example/features/auth/api/authAPI.js
server/src_example/features/auth/components/LoginForm.js
server/src_example/features/auth/components/SignUpForm.js
server/src_example/features/auth/hooks/useAuth.js
server/src_example/features/auth/routes/AuthRoutes.js
server/src_example/features/auth/stores/authStore.js
server/src_example/providers/AuthProvider.js
server/src_example/routes/AppRoutes.js
stack/.gitignore
stack/requirements.txt
stack/rxconfig.py
stack/stack/__init__.py
stack/stack/colors.py
stack/stack/db_model.py
stack/stack/email.py
stack/stack/fonts.py
stack/stack/stack.py
stack/stack/state.py
stack/stack/stripe.py
stack/stack/styles.py
stack/stack/twilio.py
stack/stack/ui.py
vly_site.vly
```

### Dependencies

- server/package.json: cors@^2.8.5, express@^4.18.2, openai@^4.28.0
- stack/requirements.txt: reflex@==0.4.0

### Recent commits (newest first)

- Merge branch 'main' of https://github.com/victorxheng/treehacks
- stuff
- Update server
- Replace workflow.png
- Add workflow image
- Add Reflex introduction pdf for vector embedding testing
- Rename files
- Add file structure functions for initializing projects
- Add embeddings notebook
- first commit
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### language.md

```markdown
A .vly file contains the following:

```
[DESCRIPTION] (requires description of the company and the purpose of the site)

Company information: (insert)
Website Description: (insert)

[FEATURES] (requires breakdown of each feature on the site specifically)
The website features the following user flow: (insert)

[DATA STRUCTURES] (requires database schema that covers the features and purpose)
(example:)
blog: title (str), content (str), image (img), views (int), author (user)
user: email (str), password (str), name, list of blogs


[PAGES] (requires page breakdown and description that covers the features, purpose, and data structure)

(example:)
Home (root): Main landing page where the user can view the company information, details, vision, marketing, and more. The user can also read most recent blog articles and most viewed articles written by other users. When logged in, the user can view their drafted blogs as well as published blogs, and click on them to edit them.

Auth: The authentication page, where the user can log in or sign up. Logging in requires just an email and password, while signing up requires an email and password confirmation.

Write (blog id): The page where the user can write and edit their blog articles. The blog articles save to the database after the user clicks off and if the value of the text is different. The blog articles can then be published, deleted, or viewed for the reading page. The blog id is the database id of the blog article. The user must be verified to be the author in order to edit, save, publish, etc.

Read (blog id): The page where the user can read blog articles. If the user is the author, they can also press a edit button that appears. At the bottom, recommended articles include most recent as well as top viewed articles.


[SHARED UI COMPONENTS] (requires breakdown of re-usable ui components shared across pages)
Nav Bar: When logged out, it contains a discord link to the discord server, and when logged in, it contains the discord link,
log out link, and share link.


[PAGE: home]
States:
Events:

UI:
Template { (example of what goes inside a component)
    Conditionals: 
    Text Parameters: 
    Actions: 
}
Nav Bar
Hero {
    Hidden when the user is logged in
    Title displays "Create a full stack web app in 1 click" and the subtitle displays "Ship 100x faster and cheaper"
    Call to action adds their email to a waitlist and the button says "Join"
}


[PAGE: auth]


[PAGE: write/[id]]


[PAGE: read/[id]]

etc


```
```

### stack/requirements.txt

```
reflex==0.4.0

```

### server/package.json

```
{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "openai": "^4.28.0"
  }
}

```

### server/index.js

```javascript
const express = require('express');
const { exec } = require('child_process');
const app = express();
const cors = require('cors');

app.use(cors());
const port = 3001; // Ensure this port is different from your React app's port

app.use(express.json());
require('dotenv').config();
const { Configuration, OpenAI } = require("openai");

const openai = new OpenAI(process.env.OPENAI_API_KEY);


app.post('/create-structure', (req, res) => {
  exec('node create-structure.js', (error, stdout, stderr) => {
    if (error) {
      console.error(`exec error: ${error}`);
      return res.status(500).send('Failed to create structure');
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
    res.send('Project structure created successfully');
  });
});


app.post('/addServerFiles', (req, res) => {
  exec('node functions/addServerFiles.js', (error, stdout, stderr) => {
    if (error) {
      console.error(`exec error: ${error}`);
      return res.status(500).send('Failed to create structure');
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
    res.send('Project structure created successfully');
  });
});

app.post('/addFrontendFiles', (req, res) => {
  exec('node functions/addFrontendFiles.js', (error, stdout, stderr) => {
    if (error) {
      console.error(`exec error: ${error}`);
      return res.status(500).send('Failed to create structure');
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
    res.send('Project structure created successfully');
  });
});

// generateDescriptionsForProjectStructure(projectStructure)
//   .then(fileList => console.log(fileList))
//   .catch(error => console.error(error));

// GET route to fetch description
// look at prompt1.txt for a prompt example
app.get('/generate-description', async (req, res) => {
  try {
    // Extracting query parameters from the GET request
    const { prompt } = req.query;

    if (!prompt) {
      return res.status(400).json({ error: "Prompt is required" });
    }

    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: prompt,
      max_tokens: 1024,
      temperature: 0.5,
    });

    const description = response.data.choices[0].text.trim();

    // Sending back the generated description as JSON
    res.json({ description });
  } catch (error) {
    console.error("Error generating description:", error);
    res.status(500).json({ error: "Failed to generate description" });
  }
});

app.listen(port, () => {
  console.log(`Backend server listening at http://localhost:${port}`);
});

```

### compiler_agents.py

```python
from openai import OpenAI
import sys

import shutil
import os

client = OpenAI(api_key = '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')

path_name = input("Type in directory of the .vly file to process without the extension\n")

file = open(path_name+".vly", "r")

if file is None:
    sys.exit("file empty, abort")

prompt = file.read()

# duplicates the starter code
shutil.copytree("stack", 'generated/'+path_name)

# make sure API key is set correctly
# agent starts by writing the database schema
response = client.chat.completions.create(
  model="gpt-4-0125-preview",
  messages=[
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": prompt.split('[PAGES]')[0]},
  ]
)

# edit the db_model.py file from the path with the response


# replace and then start writing the stack

# initialize and deploy
```

### stack/rxconfig.py

```python
import reflex as rx

config = rx.Config(
    app_name="stack",
    tailwind={},
)
```

### stack/stack/fonts.py

```python
font_weights = {
    "bold": "800",
    "heading": "700",
    "subheading": "600",
    "section": "600",
}

```

### stack/stack/twilio.py

```python
from twilio.rest import Client

# Your Account SID and Auth Token from console.twilio.com
account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
auth_token  = "your_auth_token"

client = Client(account_sid, auth_token)

def send_test(number, content):
    message = client.messages.create(
        to=number, #replace
        from_="+15017250604", #replace
        body=content)

```

### stack/stack/db_model.py

```python
from sqlmodel import Field

import reflex as rx


class Follows(rx.Model, table=True):
    followed_username: str = Field(primary_key=True)
    follower_username: str = Field(primary_key=True)


class User(rx.Model, table=True):
    """A table of Users."""

    username: str
    password: str


class Tweet(rx.Model, table=True):
    """A table of Tweets."""

    content: str
    created_at: str

    author: str
```

### stack/stack/email.py

```python
import requests

# mailgun integration

def send_simple_message(name, email, subject, content):
        key = "e731cf91e15411c36572b70df8fbc11f-8c8e5529-963570cb"
        response = requests.post(
            "https://api.mailgun.net/v3/sandboxd408dd7a420a425e974ff6f3a50413d0.mailgun.org/messages",
            auth=("api", key),
            data={"from": "Mailgun Sandbox <postmaster@sandboxd408dd7a420a425e974ff6f3a50413d0.mailgun.org>",
            "to": name + "<" + email + ">",
            "subject": subject,
            "text": content})
```

[34 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]