Skip to content

anuragts/circle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Circle

Real-time reactive database engine for React applications.

Quick Start

1. Start PostgreSQL

docker-compose up -d

2. Start the Backend

cd backend
pip3 install -r requirements.txt
python3 main.py

Backend runs at http://localhost:8000

3. Start the Example App

cd sdk && npm install && npm run build
cd ../example && npm install && npm run dev

App runs at http://localhost:3000

4. Test Real-time Sync

  1. Open http://localhost:3000 in two browser tabs
  2. Add a todo in Tab 1 → appears instantly in Tab 2
  3. Toggle/delete in Tab 2 → reflects in Tab 1

SDK Usage

Setup

Wrap your app with CircleProvider:

import { CircleProvider } from '@circle/sdk';

function App() {
  return (
    <CircleProvider config={{ url: 'http://localhost:8000' }}>
      <YourApp />
    </CircleProvider>
  );
}

Query Data (with real-time updates)

import { useQuery } from '@circle/sdk';

function TodoList() {
  const { data: todos, loading, error } = useQuery('todos');

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

Data updates automatically when the database changes — no polling, no manual refetch.

Mutations

import { useMutation } from '@circle/sdk';

function AddTodo() {
  const { insert, update, remove } = useMutation();

  const handleAdd = async () => {
    await insert('todos', { title: 'New todo', completed: false });
  };

  const handleToggle = async (id: number, completed: boolean) => {
    await update('todos', id, { completed: !completed });
  };

  const handleDelete = async (id: number) => {
    await remove('todos', id);
  };

  return <button onClick={handleAdd}>Add Todo</button>;
}

Connection Status

import { useConnectionStatus } from '@circle/sdk';

function StatusIndicator() {
  const status = useConnectionStatus();
  // 'connecting' | 'connected' | 'disconnected' | 'error'

  return <span>{status}</span>;
}

API Reference

Hooks

Hook Description
useQuery(table, filters?) Subscribe to table data with real-time updates
useMutation() Get insert, update, remove functions
useConnectionStatus() Get WebSocket connection status
useCircle() Access the Circle client directly

useQuery Return Value

{
  data: T[];        // Array of records
  loading: boolean; // True while fetching
  error: string | null;
  refetch: () => Promise<void>;
}

useMutation Return Value

{
  insert: (table: string, data: object) => Promise<object>;
  update: (table: string, id: number, data: object) => Promise<object>;
  remove: (table: string, id: number) => Promise<boolean>;
  loading: boolean;
  error: string | null;
}

Database Connection

Connect directly to PostgreSQL using any client (TablePlus, pgAdmin, psql):

Field Value
Host 127.0.0.1
Port 5432
User circle
Password circle_secret
Database circle

Connection string:

postgresql://circle:circle_secret@127.0.0.1:5432/circle

Changes made directly in the database sync to all connected clients instantly.

Adding New Tables

  1. Create your table in PostgreSQL
  2. Enable change tracking:
SELECT circle_track_table('your_table_name');
  1. Use it in React:
const { data } = useQuery('your_table_name');

Project Structure

circle/
├── docker-compose.yml          # PostgreSQL container
├── backend/
│   ├── requirements.txt        # Python dependencies
│   ├── init.sql               # DB schema + triggers
│   ├── main.py                # Entry point
│   └── circle/
│       ├── db.py              # PostgreSQL + LISTEN/NOTIFY
│       ├── tracker.py         # Subscription management
│       └── server.py          # FastAPI + WebSocket
├── sdk/
│   └── src/
│       ├── client.ts          # WebSocket client
│       ├── hooks.tsx          # React hooks
│       └── types.ts           # TypeScript types
└── example/                   # Demo React app

HTTP API

The backend also exposes a REST API:

# Query
curl -X POST http://localhost:8000/query \
  -H "Content-Type: application/json" \
  -d '{"table": "todos"}'

# Insert
curl -X POST http://localhost:8000/insert \
  -H "Content-Type: application/json" \
  -d '{"table": "todos", "data": {"title": "New", "completed": false}}'

# Update
curl -X POST http://localhost:8000/update \
  -H "Content-Type: application/json" \
  -d '{"table": "todos", "id": 1, "data": {"completed": true}}'

# Delete
curl -X POST http://localhost:8000/delete \
  -H "Content-Type: application/json" \
  -d '{"table": "todos", "id": 1}'

TODO: [ ] Add schema building support so we can build tables and migrations of tables. [ ] Add authentication system. [ ] Add deployment system and deploy to cloud.

How It Works

┌─────────────────┐     ┌─────────────────────────────────┐     ┌──────────────────┐
│   React App     │◄───►│       Python Backend            │◄───►│   PostgreSQL     │
│   (Circle SDK)  │ WS  │   (FastAPI + WebSocket)         │     │   (Docker)       │
└─────────────────┘     └─────────────────────────────────┘     └──────────────────┘
  1. PostgreSQL triggers fire on every INSERT/UPDATE/DELETE
  2. NOTIFY sends change events to the Python backend
  3. WebSocket broadcasts changes to all subscribed React clients
  4. React state updates automatically — no manual refetching

Changes from any source (your app, TablePlus, psql, another service) sync instantly to all connected clients.

License

MIT

About

Real-time reactive database engine

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors