

.png)







.png)






.png)



.png)



.png)



.png)




// schema.graphql
type Dog @table @export {
id: ID @primaryKey
name: String
breed: String @indexed
age: Int
status: String # available | adopted | fostered
bio: String
tricks: [String]
embedding: [Float] @indexed(type: "HNSW", distance: "cosine")
photo: Blob
owner: Owner @relationship(from: "ownerId")
ownerId: ID @indexed
}
type Owner @table @export {
id: ID @primaryKey
name: String
phone: String
city: String
}
// You immediately get:
GET /Dog/{id}
POST /Dog/
PUT /Dog/{id}
PATCH /Dog/{id}
DELETE /Dog/{id}
GET /Dog/?breed=Labrador&sort(-age)
GET /Owner/{id}
POST /Owner/
...
// No migrations. No REST framework. No code generation step.
// 1st Let's start by adding data. Add as much as you want.
POST /Owner/
Content-Type: application/json
{
"name": "John Smith",
"phone": "123-456-7890",
"city": "Denver"
}
POST/Dog/
Content-Type: application/json
{
"name": "Rex",
"breed": "Labrador",
"age": 5,
"status": "available",
"bio": "Loves fetch and long walks",
"tricks": ["sit", "shake", "fetch"],
"ownerId": "<copy id from `POST /Owner/`>"
}
// 2nd Now let's filter, sort, and traverse relationships in the address bar with URL querys
// Senior dogs available for adoption
GET /Dog/?age=gt=7&status=available&sort(-age)&limit(10)
// Breed is "Retriever", status is available OR fostered
GET /Dog/?breed=Retriever&(status=available|status=fostered)
// Join through the owner relationship
GET /Dog/?owner.city=Austin&select(name,breed,owner{name,phone})
// fetch — same filters, works anywhere JS runs
const res = await fetch(
'/Dog/?breed=Retriever&status=available&select(name,breed,age)',
{ headers: { Authorization: 'Basic ' + btoa('user:pass') } }
);
const dogs = await res.json();
// GraphQL — enable with one line in config.yaml, query /graphql
{
Dog(status: "available") {
name
breed
age
owner {
name
phone
}
}
}
// resources.js
import { tables } from 'harperdb';
const { Dog } = tables;
export class AdoptableDog extends Dog {
// Enrich every GET with computed fields
async get(query) {
const dog = await super.get(query);
return {
...dog,
humanAge: 15 + dog.age * 5,
isGoodBoy: true, // always
};
}
// Validate and set defaults on every POST
async post(target, data) {
if (!data.name) throw new Error('Every dog deserves a name');
data.tricks = data.tricks ?? [];
data.status = 'available';
return super.post(target, data);
}
}
// Three files. That's still the whole backend.
// schema.graphql — cached for 1 hour
type BreedImage @table(expiration: 3600) @export {
id: ID @primaryKey
image: String
}
// resources.js — point it at the dog.ceo API
import { Resource, tables } from 'harperdb';
class DogCeoAPI extends Resource {
async get() {
const breed = this.getId();
const res = await fetch(
`https://dog.ceo/api/breed/${breed}/images/random`
);
const data = await res.json();
return { breed, image: data.message };
}
}
tables.BreedImage.sourcedFrom(DogCeoAPI);
// Cache miss fetches from dog.ceo API
GET /BreedInfo/labrador
// Cache hits return in <1ms
GET -H 'If-None-Match: "<Etag>"' /BreedInfo/labrador
// 3 Examples of Real-Time In Action
// OPTION 1 | Server Sent Events (SSE), no library needed
const events = new EventSource('/Dog/<id>/');
events.onmessage = (e) => {
const data = JSON.parse(e.data);
const dog = data.value;
console.log(`${dog.name} is now: ${dog.status}`);
// → "Rex is now: adopted"
};
// OPTION 2 | WebSocket with custom actions via resources.js
import { tables } from 'harperdb';
export class LiveDog extends Resource {
async *connect(target, incomingMessages) {
const subscription = await tables.Dog.subscribe(target);
if (!incomingMessages) {
return subscription; // SSE mode
}
for await (let msg of incomingMessages) {
if (msg.action === 'wag') yield { tail: 'wagging' };
}
}
}
// OPTION 3 | config.yaml — enable MQTT for IoT collar tracking
mqtt:
network:
port: 1883
webSocket: true
requireAuthentication: trueembedding field in your schema already has an HNSW index. Store vectors alongside your data and query them with the same REST API, no separate vector database.// Already declared in schema.graphql (Tab 1:Schema):
// embedding: [Float] @indexed(type: "HNSW", distance: "cosine")
// Store a dog profile with its bio embedding
await fetch('/Dog/<id>', {
method: 'POST',
body: JSON.stringify({
name: 'Biscuit',
breed: 'Golden Retriever',
bio: 'Loves fetch, belly rubs, and long walks',
embedding: await getEmbedding('Loves fetch, belly rubs, and long walks'),
status: 'available',
}),
});
// Find the 5 most similar dogs to a query
import { tables } from 'harperdb';
const results = tables.Dog.search({
select: ['name', 'breed', 'bio', '$distance'],
sort: {
attribute: 'embedding',
target: await getEmbedding('friendly dog who loves walks'),
},
limit: 5,
});
// → dogs ranked by cosine similarity to the query vector photo field in your schema is a native Blob. Upload and serve binary files from the same endpoint as your data, no S3 bucket, no file service.// Already declared in schema.graphql (Tab 1:Schema):
// photo: Blob
// Upload and retrieve a dog photo
// Upload
PUT /Dog/<id>/photo
Content-Type: image/jpeg
< ./rex-headshot.jpg
// Retrieve — streams back with correct Content-Type
GET /Dog/<id>/photo
// Upload from a browser form
const formData = new FormData();
formData.append('photo', fileInput.files[0]);
await fetch('/Dog/<id>/photo', {
method: 'PUT',
body: formData,
});// Develop locally
harper dev .
// Deploy local project to Fabric (push-based deploys)
cd my-app
harper deploy .
project=my-app \
target="https://your-app.fabric.harper.fast/" \
username="your-cluster-username" \
password="your-cluster-password" \
restart=rolling \
replicated=true
// Deploy GitHub project to Fabric (pull-based deploys)
harper deploy \
project=my-app \
package="https://github.com/User/my-app" \
target="https://your-app.fabric.harper.fast/" \
username="your-cluster-username" \
password="your-cluster-password" \
restart=rolling \
replicated=true
// Same API. Same schema. Same logic. Just… everywhere.
GET https://your-app.fabric.harper.fast/Dog/?breed=Labrador&status=available
// No Dockerfile. No cloud console wizards.
// All your files → one command → globally distributed. 




.png)

