RushDB
Give your agent a memory.
Push any JSON. Get graph relationships and vector search instantly — no schema, no pipeline, no setup.
Start building free →FAQ
RushDB
Push any JSON. Get graph relationships and vector search instantly — no schema, no pipeline, no setup.
Start building free →FAQ
Embeddings rank similarity but ignore joins, cardinality, and constraints. Learn how RushDB combines semantic retrieval with explicit graph relationships and live schema discovery.
LLM applications naturally fragment into ETL, embedding, graph sync, search indexing, and metadata pipelines. Learn why this happens and how a single ingestion layer can replace.
TL;DR: This example shows how to build a full-stack application using React Hook Form + RushDB with zero schema setup, backend efforts or data normalization. View the complete source code.
In modern web development, we often spend more time dealing with data modeling, normalization, and database migrations than on the actual business logic that drives our applications. What if we could skip all of that and focus solely on the shape of our data and the user experience?
This article explores how combining React Hook Form with RushDB creates a powerful, backendless approach to fullstack development that eliminates the traditional complexity of working with form data.
Let's consider what typically happens when building a form in a web application:
This approach requires maintaining multiple data representations across your stack, writing repetitive boilerplate code, and continuously synchronizing changes between layers. Even with ORMs and other tools, the complexity remains significant.
RushDB offers a radically different approach by providing a graph database that:
This means you can take your form data exactly as it is structured in your frontend and store it directly without any transformation or normalization.
Let's examine a comprehensive form implementation using React Hook Form with Zod validation and RushDB for storage.
First, we initialize the RushDB client:
// db.ts
import { RushDB } from "@rushdb/javascript-sdk";
// Initialize RushDB
export const db = new RushDB(env.RUSHDB_API_TOKEN);
That's it! No schema definitions, no models, no complex setup.
You can get a free API token by signing up at app.rushdb.com. For more information on getting started, see the official documentation.
We use Zod to define the validation schema for our form:
// Form validation schema
const formSchema = z.object({
// Personal Information
firstName: z.string().min(2, "First name must be at least 2 characters"),
lastName: z.string().min(2, "Last name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
phone: z.string().min(10, "Phone number must be at least 10 digits"),
dateOfBirth: z.string().min(1, "Date of birth is required"),
// Address Information (nested object)
address: z.object({
street: z.string().min(5, "Street address is required"),
city: z.string().min(2, "City is required"),
state: z.string().min(2, "State is required"),
zipCode: z.string().min(5, "ZIP code must be at least 5 characters"),
country: z.string().min(2, "Country is required"),
}),
// Professional Information
company: z.string().min(2, "Company name is required"),
position: z.string().min(2, "Position is required"),
experience: z.enum(["entry", "junior", "mid", "senior", "lead", "executive"]),
salary: z.number().min(0, "Salary must be a positive number"),
skills: z.array(z.string()).min(1, "At least one skill is required"),
// Preferences (nested object with boolean values)
preferences: z.object({
newsletter: z.boolean(),
notifications: z.boolean(),
publicProfile: z.boolean(),
dataSharing: z.boolean(),
}),
// Additional Information
bio: z.string().max(500, "Bio must be less than 500 characters"),
website: z.string().url("Invalid URL").optional().or(z.literal("")),
linkedIn: z.string().url("Invalid LinkedIn URL").optional().or(z.literal("")),
github: z.string().url("Invalid GitHub URL").optional().or(z.literal("")),
});
type FormData = z.infer<typeof formSchema>;
Notice how we naturally represent the form data with nested objects and arrays - this matches exactly how we think about the data in our application.
The most remarkable part is how we handle form submission:
const onSubmit = async (data: FormData) => {
try {
// Save to RushDB
await db.records.createMany({
label: "FORM_DATA",
data
});
reset(); // Reset form after successful submission
} catch (error) {
// ..
} finally {
// ..
}
};
That's it! Just a single API call to store the entire form data, including nested objects and arrays, without any normalization or transformation.
Network request contains the raw form data that gets sent to RushDB. Notice how the nested structure stays intact with no transformation required.
When you submit the form data to RushDB:
address and preferences) are automatically normalized into separate nodes in the graphskills) are stored as a normal Property of FORM_DATA RecordRushDB handles all the complexity of storing a deeply nested object structure while maintaining the relationships between entities.
The 3D graph visualization shows how RushDB has automatically normalized your form data into a graph structure. Each node represents an entity from your form, and the edges show the relationships between them.
Despite being stored as a graph, RushDB also provides this familiar table view of your data. This makes it easy to query and analyze your data in a familiar way.
No need to:
One of the most powerful aspects of RushDB is its ability to query this complex data structure easily. For example, finding all form submissions from senior engineers:
const seniorEngineers = await db.records.find({
labels: ["FORM_DATA"],
where: {
experience: "senior",
position: { $contains: "Engineer" },
},
});
Or finding all users who have subscribed to the newsletter and have JavaScript skills:
const subscribedJsDevelopers = await db.records.find({
labels: ["FORM_DATA"],
where: {
preferences: {
newsletter: true,
},
skills: { $contains: "JavaScript" },
},
});
The combination of React Hook Form for frontend validation and RushDB for data storage creates a powerful backendless approach to full-stack development. It allows you to focus on what really matters - the shape of your data and the user experience - without getting bogged down in database schemas, normalization, and complex backend architectures.
This approach is particularly well-suited for:
By removing the traditional backend complexity, you can build sophisticated applications faster and with less code. RushDB's ability to handle nested JSON structures directly means you can model your data in the most natural way for your application without worrying about how it will be stored.
For more information about RushDB's capabilities, check out the official documentation and explore the examples repository.
Source Code: The complete example from this article is available at github.com/rush-db/examples/tree/main/vite-react-useForm