@headlessly/sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +543 -0
  2. package/cli.js +48 -0
  3. package/index.js +19 -0
  4. package/package.json +61 -0
  5. package/types.d.ts +30 -0
package/README.md ADDED
@@ -0,0 +1,543 @@
1
+ # headless.ly
2
+
3
+ The operating system for agent-first startups.
4
+
5
+ Create an org. Get everything. CRM, project management, billing, analytics, content, support, marketing, experimentation — as a single unified system that AI agents can operate autonomously.
6
+
7
+ ```typescript
8
+ import Headlessly from 'headless.ly'
9
+
10
+ const org = Headlessly({ tenant: 'my-startup' })
11
+
12
+ // Everything exists. One line.
13
+ await org.Contact.create({ name: 'Alice', email: 'alice@vc.com', stage: 'Lead' })
14
+ await org.Deal.create({ name: 'Seed Round', contact: 'contact_1', value: 500_000 })
15
+ await org.Issue.create({ title: 'Build MVP', project: 'project_1', status: 'InProgress' })
16
+ await org.Subscription.create({ price: 'price_pro', customer: 'customer_1' })
17
+ ```
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install headless.ly
23
+ ```
24
+
25
+ ## Why headless.ly?
26
+
27
+ **You're building a startup, not configuring software.**
28
+
29
+ Most business tools make you choose modules, design schemas, wire integrations, and learn 15 different APIs. headless.ly gives you one typed graph of everything — contacts, deals, tasks, content, tickets, billing, analytics, experiments — connected and ready for agents to operate from day zero.
30
+
31
+ - **One graph, not 15 SaaS tools** — every entity lives in the same system
32
+ - **Agent-first** — TypeScript SDK is the primary contract, not a bolted-on API
33
+ - **Immutable event log** — nothing is ever deleted, every state is reconstructable
34
+ - **Zero configuration** — create an org and everything works
35
+
36
+ ## 32 Core Entities
37
+
38
+ Every entity exists because headless.ly needs it to run itself as an autonomous business. If headless.ly doesn't need it, it doesn't ship. Every entity carries `$type`, `$id`, `$context` (tenant namespace), `$version`, `$createdAt`, `$createdBy`, `$updatedAt`.
39
+
40
+ ### Identity — Authentication & Tenancy (WorkOS-backed)
41
+
42
+ ```typescript
43
+ // Users and orgs managed via WorkOS
44
+ await org.User.invite({ name: 'Alice', email: 'alice@acme.com', role: 'Member' })
45
+ await org.ApiKey.create({ name: 'CI/CD', scopes: ['read', 'write'] })
46
+ ```
47
+
48
+ | Entity | Purpose |
49
+ |--------|---------|
50
+ | **User** | Authenticated humans — founders, team members |
51
+ | **Organization** | Tenants — each org gets all 32 entities |
52
+ | **ApiKey** | Programmatic access — SDK, CI/CD, agents |
53
+
54
+ ### CRM — People & Relationships
55
+
56
+ ```typescript
57
+ await org.Contact.create({ name: 'Alice', email: 'alice@vc.com', stage: 'Lead' })
58
+ await org.Contact.qualify('contact_1')
59
+ await org.Company.create({ name: 'Acme Corp', domain: 'acme.com' })
60
+ await org.Deal.create({ name: 'Enterprise', value: 50_000, stage: 'Proposal' })
61
+ ```
62
+
63
+ | Entity | Purpose |
64
+ |--------|---------|
65
+ | **Contact** | People — developers, founders, VCs, partners |
66
+ | **Company** | Organizations — startups, enterprises, partners |
67
+ | **Deal** | Sales opportunities with value and pipeline stage |
68
+
69
+ ### Projects — Work (GitHub + Beads superset)
70
+
71
+ ```typescript
72
+ await org.Project.create({ name: 'v1 Launch', status: 'Active' })
73
+ await org.Issue.create({ title: 'Build auth flow', project: 'project_1', priority: 'High', type: 'Feature' })
74
+ await org.Issue.assign('issue_1', { assignee: 'user_1' })
75
+ ```
76
+
77
+ | Entity | Purpose |
78
+ |--------|---------|
79
+ | **Project** | Container for organized work, maps to GitHub Projects |
80
+ | **Issue** | Unit of work with deps/hierarchy, syncs with GitHub Issues |
81
+ | **Comment** | Polymorphic discussion on Issues, Tickets, or Content |
82
+
83
+ ### Content — Publishing (mdxui-typed)
84
+
85
+ ```typescript
86
+ await org.Content.create({ title: 'Pricing', slug: 'pricing', type: 'Page', status: 'Published' })
87
+ await org.Content.create({ title: 'Why Agent-First', type: 'Post', status: 'Draft' })
88
+ await org.Content.publish('content_1')
89
+ await org.Asset.create({ name: 'hero.png', url: 'https://...', type: 'Image' })
90
+ ```
91
+
92
+ | Entity | Purpose |
93
+ |--------|---------|
94
+ | **Content** | Typed MDX — Page, Post, Doc, LandingPage, LeanCanvas, StoryBrand, etc. |
95
+ | **Asset** | Media files — images, videos, documents |
96
+ | **Site** | mdxui site config — Marketing, Docs, Blog, Directory, etc. |
97
+
98
+ ### Billing — Revenue (Stripe-backed)
99
+
100
+ ```typescript
101
+ await org.Product.create({ name: 'headless.ly', type: 'Software' })
102
+ await org.Price.create({ name: 'Pro', product: 'product_1', amount: 49, interval: 'Monthly' })
103
+ await org.Customer.create({ contact: 'contact_1' })
104
+ await org.Subscription.create({ price: 'price_1', customer: 'customer_1' })
105
+ await org.Subscription.upgrade('sub_1', { price: 'price_enterprise' })
106
+ ```
107
+
108
+ | Entity | Purpose |
109
+ |--------|---------|
110
+ | **Customer** | Stripe Customer — links Contact to billing identity |
111
+ | **Product** | What you sell |
112
+ | **Price** | Pricing config — Monthly, Annual, OneTime, Usage |
113
+ | **Subscription** | Active paying relationships |
114
+ | **Invoice** | Bills — monthly/annual |
115
+ | **Payment** | Money movement — charges, refunds, credits |
116
+
117
+ ### Support — Help
118
+
119
+ ```typescript
120
+ await org.Ticket.create({ subject: 'API returns 500', priority: 'High', contact: 'contact_1' })
121
+ await org.Ticket.assign('ticket_1', { assignee: 'user_1' })
122
+ await org.Message.create({ ticket: 'ticket_1', body: 'Looking into this now.', channel: 'Web', direction: 'Outbound' })
123
+ await org.Ticket.resolve('ticket_1')
124
+ ```
125
+
126
+ | Entity | Purpose |
127
+ |--------|---------|
128
+ | **Ticket** | Support requests — bugs, questions, feature requests |
129
+
130
+ ### Analytics — Insights
131
+
132
+ ```typescript
133
+ // Events captured via browser SDK → forwarded to GA/Sentry/PostHog + stored in lakehouse
134
+ await org.Event.track({ name: 'signup', userId: 'user_1', properties: { plan: 'free' } })
135
+
136
+ // Financial metrics derived from real Stripe data (headless baremetrics)
137
+ const mrr = await org.Metric.get('mrr') // Real MRR from Stripe
138
+ const churn = await org.Metric.get('churn_rate') // Real churn rate
139
+
140
+ // Funnels track the full revenue pipeline
141
+ await org.Funnel.analyze('visitor-to-paid') // visitor → signup → activated → paid
142
+ await org.Goal.check('goal_mrr_100k')
143
+ ```
144
+
145
+ | Entity | Purpose |
146
+ |--------|---------|
147
+ | **Event** | Every tracked action — pageviews, API calls, sign-ups (forwarded to GA/PostHog + stored) |
148
+ | **Metric** | Real values — MRR, churn, NRR, LTV from Stripe; DAU, NPS from events |
149
+ | **Funnel** | Conversion flows — visitor → signup → activate → pay |
150
+ | **Goal** | Business objectives — revenue targets, user targets |
151
+
152
+ ### Marketing — Growth
153
+
154
+ ```typescript
155
+ await org.Campaign.create({ name: 'Product Hunt Launch', type: 'Event', status: 'Active' })
156
+ await org.Segment.create({ name: 'Power Users', definition: { events: { $gte: 100 } } })
157
+ await org.Form.create({ name: 'Waitlist', fields: ['name', 'email', 'company'] })
158
+ ```
159
+
160
+ | Entity | Purpose |
161
+ |--------|---------|
162
+ | **Campaign** | Marketing initiatives — launches, drips, content pushes |
163
+ | **Segment** | Audience groups — by ICP, usage, stage |
164
+ | **Form** | Data collection — sign-up, waitlist, contact us |
165
+
166
+ ### Experimentation — Testing
167
+
168
+ ```typescript
169
+ await org.Experiment.create({ name: 'Pricing Test', type: 'ABTest', variants: ['$29', '$49'] })
170
+ await org.FeatureFlag.create({ key: 'new-onboarding', rollout: 25 })
171
+ await org.FeatureFlag.rollout('new-onboarding', { percentage: 100 })
172
+ ```
173
+
174
+ | Entity | Purpose |
175
+ |--------|---------|
176
+ | **Experiment** | A/B tests on pricing, onboarding, features |
177
+ | **FeatureFlag** | Progressive rollouts, beta access |
178
+
179
+ ### Communication
180
+
181
+ ```typescript
182
+ // Cross-channel messaging — email, SMS, Slack, Discord, Teams, web, in-app
183
+ await org.Message.create({ body: 'Welcome!', channel: 'Email', direction: 'Outbound', to: 'contact_1' })
184
+ await org.Message.create({ body: 'Following up', channel: 'Slack', direction: 'Outbound', deal: 'deal_1' })
185
+ ```
186
+
187
+ | Entity | Purpose |
188
+ |--------|---------|
189
+ | **Message** | Cross-channel comms — Email, SMS, Slack, Discord, Teams, Web, InApp, API |
190
+
191
+ ### Platform — Infrastructure
192
+
193
+ ```typescript
194
+ // Automation: when a deal closes, create a subscription
195
+ org.Deal.closed(deal => {
196
+ org.Subscription.create({ price: 'price_pro', customer: deal.contact })
197
+ org.Contact.update(deal.contact, { stage: 'Customer' })
198
+ })
199
+
200
+ // AI agent with full autonomous interface
201
+ await org.Agent.create({ name: 'Support Bot', mode: 'Autonomous', role: 'Support', model: 'claude-sonnet' })
202
+ ```
203
+
204
+ | Entity | Purpose |
205
+ |--------|---------|
206
+ | **Workflow** | Automation rules — deal.closed → subscription.created |
207
+ | **Integration** | External connections — Stripe, GitHub, Slack, WorkOS |
208
+ | **Agent** | AI agents with do/ask/decide/approve/notify/delegate/escalate/learn |
209
+
210
+ ## Digital Objects
211
+
212
+ Entities are defined using the `Noun()` function from `digital-objects` — zero dependencies, zero codegen, full TypeScript inference:
213
+
214
+ ```typescript
215
+ import { Noun } from 'digital-objects'
216
+
217
+ export const Contact = Noun('Contact', {
218
+ name: 'string!',
219
+ email: 'string?#',
220
+ phone: 'string?',
221
+ title: 'string?',
222
+ stage: 'Lead | Qualified | Customer | Churned | Partner',
223
+ source: 'string?',
224
+ company: '-> Company.contacts',
225
+ deals: '<- Deal.contact[]',
226
+ messages: '<- Message.contact[]',
227
+
228
+ // Custom verbs (CRUD is automatic)
229
+ qualify: 'Qualified',
230
+ capture: 'Captured',
231
+ assign: 'Assigned',
232
+ merge: 'Merged',
233
+ enrich: 'Enriched',
234
+ })
235
+ ```
236
+
237
+ Every property value tells the parser what it is:
238
+
239
+ | Value Pattern | Meaning | Example |
240
+ |--------------|---------|---------|
241
+ | Type string | Data property | `'string!'`, `'number?'`, `'datetime!'` |
242
+ | Arrow syntax | Relationship | `'-> Company.contacts'`, `'<- Deal.contact[]'` |
243
+ | Pipe-separated PascalCase | Enum | `'Lead \| Qualified \| Customer'` |
244
+ | Single PascalCase word | Verb → Event | `'Qualified'`, `'Captured'` |
245
+ | `null` | Opt out of inherited verb | `update: null` (makes entity immutable) |
246
+
247
+ ## Verbs & Event Handlers
248
+
249
+ Every verb has a full conjugation that maps to the execution lifecycle:
250
+
251
+ ```
252
+ qualify
253
+ ├── qualify() → execute the action
254
+ ├── qualifying() → BEFORE hook (validate, transform, reject)
255
+ ├── qualified() → AFTER hook (react, trigger side effects)
256
+ └── qualifiedBy → who performed this action
257
+ ```
258
+
259
+ Register handlers directly on the entity:
260
+
261
+ ```typescript
262
+ // BEFORE hook — validate or reject
263
+ org.Contact.qualifying(contact => {
264
+ if (!contact.email) throw new Error('Cannot qualify without email')
265
+ return contact
266
+ })
267
+
268
+ // AFTER hook — react to what happened
269
+ org.Contact.qualified(contact => {
270
+ org.Activity.create({
271
+ type: 'Task',
272
+ subject: `Follow up with ${contact.name}`,
273
+ contact: contact.$id,
274
+ })
275
+ })
276
+
277
+ // Execute
278
+ await org.Contact.qualify('contact_123')
279
+ // → runs .qualifying() → sets stage → persists event → runs .qualified()
280
+ ```
281
+
282
+ ## Promise Pipelining
283
+
284
+ The SDK uses `rpc.do` with capnweb promise pipelining — chain dependent calls without awaiting, and the system batches them into a single round trip:
285
+
286
+ ```typescript
287
+ // One round trip, not three
288
+ const deals = await org.Contact
289
+ .find({ stage: 'Qualified' })
290
+ .map(contact => contact.deals)
291
+ .filter(deal => deal.status === 'Open')
292
+ ```
293
+
294
+ ## Time Travel
295
+
296
+ Every mutation is an event appended to an immutable log. Any point in time can be reconstructed:
297
+
298
+ ```typescript
299
+ const contacts = await org.Contact.find(
300
+ { stage: 'Lead' },
301
+ { asOf: '2026-01-15T10:00:00Z' }
302
+ )
303
+
304
+ await org.Contact.rollback('contact_123', { asOf: '2026-02-06T15:00:00Z' })
305
+ ```
306
+
307
+ This gives founders confidence to let agents operate freely — anything can be undone.
308
+
309
+ ## Foundational Integrations
310
+
311
+ Stripe and GitHub aren't "integrations to add later" — they're truth sources from day 1:
312
+
313
+ ```typescript
314
+ // Day 0: connect Stripe and GitHub
315
+ await org.Integration.connect('stripe', { apiKey: process.env.STRIPE_KEY })
316
+ await org.Integration.connect('github', { token: process.env.GITHUB_TOKEN })
317
+
318
+ // Billing entities are now Stripe-backed
319
+ // Creating a Subscription creates a Stripe subscription
320
+ await org.Subscription.create({ plan: 'pro', contact: 'contact_1' })
321
+
322
+ // Project entities sync with GitHub
323
+ // Creating an Issue creates a GitHub issue
324
+ await org.Issue.create({ title: 'Build auth', project: 'project_1' })
325
+ ```
326
+
327
+ ### Real Financial Metrics (Headless Baremetrics)
328
+
329
+ Financial metrics are derived from real Stripe data — not self-reported, not placeholders:
330
+
331
+ ```typescript
332
+ const mrr = await org.Metric.get('mrr') // Real MRR from Stripe subscriptions
333
+ const churn = await org.Metric.get('churn_rate') // Real churn from Stripe events
334
+ const nrr = await org.Metric.get('nrr') // Net revenue retention
335
+ const ltv = await org.Metric.get('ltv') // Lifetime value
336
+ const arpu = await org.Metric.get('arpu') // Average revenue per user
337
+ ```
338
+
339
+ ### Event Forwarding & Data Lakehouse
340
+
341
+ The browser SDK captures all events and forwards to your existing tools while building your own data lake:
342
+
343
+ ```html
344
+ <!-- One script tag — events flow everywhere -->
345
+ <script src="https://js.headless.ly/v1" data-tenant="my-startup" />
346
+ ```
347
+
348
+ ```
349
+ Browser → headless.ly → Google Analytics (web analytics)
350
+ → Sentry (error tracking)
351
+ → PostHog (product analytics)
352
+ → Iceberg R2 Lakehouse (your data, forever)
353
+ ```
354
+
355
+ Day 1: external tools handle analytics. Over time, your lakehouse enables more. The revenue pipeline — visitor → signup → paid → $$ — is tracked end-to-end.
356
+
357
+ ### Dashboards — Your Entire Business at a Glance
358
+
359
+ headless.ly is headless — no built-in UI dashboards. But because everything is one system, a single dashboard connection shows your *entire business*. Most founders wire up 5-10 SaaS tools to get one view. With headless.ly, one connection covers it all.
360
+
361
+ ```typescript
362
+ // One API, every metric
363
+ const metrics = await org.Metric.dashboard()
364
+ // {
365
+ // revenue: { mrr: 12_500, arr: 150_000, churn: 2.1, nrr: 108 },
366
+ // pipeline: { leads: 47, qualified: 12, deals_open: 8, deal_value: 340_000 },
367
+ // product: { tasks_open: 23, milestones_due: 2 },
368
+ // support: { tickets_open: 5, avg_response: '2h', csat: 94 },
369
+ // marketing: { campaigns_active: 3, signups_7d: 89 },
370
+ // engagement: { dau: 230, mau: 1_200, events_24h: 15_400 },
371
+ // }
372
+ ```
373
+
374
+ Plug into any visualization tool: **Numerics** (iOS/Mac widgets), **Grafana** (time-series), **Retool** (internal tools), **Google Sheets** (live connection), or any BI tool via OpenAPI.
375
+
376
+ ### All Integrations
377
+
378
+ | Connect... | ...and this lights up | When |
379
+ |------------|----------------------|------|
380
+ | **Stripe** | Products, subscriptions, invoices, MRR, churn → Billing + Metrics | **Day 1** |
381
+ | **GitHub** | Repos, issues, PRs, milestones → Projects | **Day 1** |
382
+ | **Numerics / Dashboards** | Real-time KPIs → entire business at a glance | **Day 1** |
383
+ | **Google Analytics** | Pageviews, sessions → Events (forwarded + stored) | Day 1 (proxy) |
384
+ | **Sentry** | Errors → Events (forwarded + stored) | Day 1 (proxy) |
385
+ | **PostHog** | Product events → Events (forwarded + stored) | Day 1 (proxy) |
386
+ | **Google Apps** | Email → Messages, Calendar → Events | Phase 2 |
387
+ | **Slack/Discord** | Messages → Messages, Channels → Segments | Phase 2 |
388
+
389
+ ## ICP Templates
390
+
391
+ At org creation, select an ICP template that configures defaults without changing the schema:
392
+
393
+ ```typescript
394
+ const org = Headlessly({
395
+ tenant: 'my-startup',
396
+ template: 'b2b-saas',
397
+ })
398
+ ```
399
+
400
+ | Template | Pipeline Stages | Key Metrics |
401
+ |----------|----------------|-------------|
402
+ | **B2B SaaS** | Lead → Demo → Trial → Closed → Active → Churned | MRR, CAC, LTV |
403
+ | **B2C / Consumer** | Signup → Activated → Engaged → Monetized → Churned | DAU/MAU, ARPU |
404
+ | **B2D / Developer Tools** | Discovered → Integrated → Active → Scaled | Time-to-first-call, API usage |
405
+ | **B2A / Agent Services** | Connected → Configured → Autonomous → Scaled | Tool invocations, success rate |
406
+
407
+ Same 32 entities. Same schema. Different default labels and metric calculations. Segment includes ICP sentence pattern (`as/at/are/using/to`) for structured audience targeting.
408
+
409
+ ## MCP: Search, Fetch, Do
410
+
411
+ Three primitives for AI agents — not hundreds of tools:
412
+
413
+ ```typescript
414
+ search({ type: 'Contact', filter: { stage: 'Lead' } })
415
+ fetch({ type: 'Contact', id: 'abc123' })
416
+ do({ method: 'Contact.qualify', args: ['abc123'] })
417
+ ```
418
+
419
+ ## Multi-Tenancy
420
+
421
+ Each tenant gets their own Cloudflare Durable Object — complete data isolation:
422
+
423
+ ```
424
+ POST headless.ly/~my-startup/Contact → create
425
+ GET headless.ly/~my-startup/Contact?stage=Lead → find
426
+ GET headless.ly/~my-startup/Contact/abc123 → get
427
+ ```
428
+
429
+ ## Journey Subdomains
430
+
431
+ Different stages of building a startup emphasize different capabilities. Journey subdomains provide contextual focus — all 32 entities are always available, but the subdomain surfaces what matters most:
432
+
433
+ | Subdomain | Stage | Focus |
434
+ |-----------|-------|-------|
435
+ | `build.headless.ly` | Day 0-30 | Projects, Issues, Content |
436
+ | `launch.headless.ly` | Day 30 | Campaigns, Content, Forms |
437
+ | `experiment.headless.ly` | Day 30-60 | Experiments, FeatureFlags, Funnels |
438
+ | `grow.headless.ly` | Day 30-90 | Contacts, Deals, Campaigns, Goals |
439
+ | `automate.headless.ly` | Day 60+ | Workflows, Agents, Integrations |
440
+ | `scale.headless.ly` | Day 90+ | Metrics, Subscriptions, Analytics |
441
+
442
+ ## The Startup Journey
443
+
444
+ ### Day 0 — "I have an idea" → build.headless.ly
445
+
446
+ ```typescript
447
+ import Headlessly from 'headless.ly'
448
+ const org = Headlessly({ tenant: 'my-startup' })
449
+ // Everything exists. CRM, PM, Content, Billing, Analytics, Support — all ready.
450
+
451
+ // Connect Stripe and GitHub immediately — real data from day 1
452
+ await org.Integration.connect('stripe', { apiKey: process.env.STRIPE_KEY })
453
+ await org.Integration.connect('github', { token: process.env.GITHUB_TOKEN })
454
+ ```
455
+
456
+ ### Day 1-30 — "I'm building" → build.headless.ly
457
+
458
+ ```typescript
459
+ await org.Contact.create({ name: 'Alice', email: 'alice@vc.com', stage: 'Lead' })
460
+ await org.Issue.create({ title: 'Build MVP', project: 'project_1', status: 'InProgress' })
461
+ await org.Content.create({ title: 'Introducing Our Product', type: 'Post' })
462
+
463
+ // Browser SDK captures everything → forwards to GA/Sentry/PostHog + lakehouse
464
+ // <script src="https://js.headless.ly/v1" data-tenant="my-startup" />
465
+ ```
466
+
467
+ ### Day 30-90 — "I have users" → grow.headless.ly
468
+
469
+ ```typescript
470
+ // Stripe webhooks are already flowing → billing entities are real
471
+ // GitHub events are already syncing → project entities are real
472
+ // Financial metrics are computing from Stripe → MRR, churn, NRR are real numbers
473
+
474
+ org.Contact.qualified(contact => {
475
+ org.Event.create({ name: 'demo_scheduled', source: 'crm', contact: contact.$id })
476
+ })
477
+
478
+ org.Deal.closed(deal => {
479
+ org.Subscription.create({ price: 'price_pro', customer: deal.contact })
480
+ org.Contact.update(deal.contact, { stage: 'Customer' })
481
+ })
482
+
483
+ const mrr = await org.Metric.get('mrr') // Real number from Stripe
484
+ ```
485
+
486
+ ### Day 90+ — "I'm scaling" → scale.headless.ly
487
+
488
+ ```typescript
489
+ // Full revenue pipeline: visitor → signup → activated → paid → $$ (MRR/NRR/Churn)
490
+ await org.Funnel.analyze('visitor-to-paid')
491
+
492
+ await org.Campaign.create({ name: 'Series A Outreach', type: 'Email' })
493
+ await org.Experiment.create({ name: 'Pricing v2', type: 'ABTest', variants: ['$29', '$49'] })
494
+ await org.Agent.create({ name: 'Support Bot', mode: 'Autonomous', role: 'Support' })
495
+ ```
496
+
497
+ The same system scales from 1 founder to a seed-stage team. No migration. No new tools. The graph grows, agents get smarter, the lakehouse gets deeper, and the immutable event log means nothing is ever lost.
498
+
499
+ ## Architecture
500
+
501
+ ```
502
+ ┌─────────────────────────────────────────────────┐
503
+ │ headless.ly │
504
+ │ Tenant management, ICP templates, SDK │
505
+ │ RPC client with capnweb pipelining │
506
+ ├─────────────────────────────────────────────────┤
507
+ │ objects.do │
508
+ │ Managed Digital Object service │
509
+ │ Verb conjugation, event subscriptions │
510
+ ├──────────────────┬──────────────────────────────┤
511
+ │ digital-objects │ .do services │
512
+ │ (zero-dep schemas)│ payments.do (Stripe) │
513
+ │ │ oauth.do (auth) │
514
+ │ Noun() definitions│ events.do (CDC) │
515
+ │ 32 core entities │ database.do (ParqueDB) │
516
+ │ Type inference │ functions.do (execution) │
517
+ ├──────────────────┴──────────────────────────────┤
518
+ │ @dotdo/do │
519
+ │ THE Durable Object for Digital Objects │
520
+ │ StorageHandler · EventsStore · WebSocket │
521
+ ├─────────────────────────────────────────────────┤
522
+ │ @dotdo/db (ParqueDB) │
523
+ │ Hybrid Relational-Document-Graph DB │
524
+ │ Parquet · Iceberg · time travel · inference │
525
+ ├─────────────────────────────────────────────────┤
526
+ │ Cloudflare Infrastructure │
527
+ │ Workers · Durable Objects · R2 · KV · AI │
528
+ └─────────────────────────────────────────────────┘
529
+ ```
530
+
531
+ ## Package Ecosystem
532
+
533
+ | Package | What it adds |
534
+ |---------|-------------|
535
+ | `digital-objects` | Pure schemas, zero deps |
536
+ | `business-as-code` | + business definition primitives |
537
+ | `business.org.ai` | + ontology data (NAICS, O*NET, APQC) |
538
+ | `startups.org.ai` | + ICP templates, startup metrics |
539
+ | `headless.ly` | + tenant composition, RPC client, managed service |
540
+
541
+ ## License
542
+
543
+ MIT
package/cli.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * headless.ly CLI
4
+ * @generated
5
+ *
6
+ * Proxies to cli.do, mcp.do, and oauth.do for functionality
7
+ */
8
+
9
+ import { cli } from 'cli.do'
10
+
11
+ // Auth commands -> oauth.do
12
+ cli.command('login', 'Authenticate with headless.ly', async () => {
13
+ const { login } = await import('oauth.do/node')
14
+ await login({ service: 'headless.ly' })
15
+ })
16
+
17
+ cli.command('logout', 'Log out from headless.ly', async () => {
18
+ const { logout } = await import('oauth.do/node')
19
+ await logout({ service: 'headless.ly' })
20
+ })
21
+
22
+ cli.command('whoami', 'Show current user', async () => {
23
+ const { whoami } = await import('oauth.do/node')
24
+ const user = await whoami({ service: 'headless.ly' })
25
+ console.log(user ? `Logged in as ${user.email}` : 'Not logged in')
26
+ })
27
+
28
+ // MCP server -> mcp.do
29
+ cli.command('mcp', 'Start MCP server for AI agents', async () => {
30
+ const { serve } = await import('mcp.do')
31
+ await serve({
32
+ name: 'headless.ly',
33
+ tools: await import('./mcp-tools.js')
34
+ })
35
+ })
36
+
37
+ // RPC commands -> rpc.do
38
+ cli.command('call <service> <method> [params]', 'Make RPC call', async (service, method, params) => {
39
+ const { ensureLoggedIn } = await import('oauth.do/node')
40
+ const { apiKey } = await ensureLoggedIn({ service: 'headless.ly' })
41
+ const { rpc } = await import('rpc.do')
42
+
43
+ const client = rpc(service, { apiKey })
44
+ const result = await client.call(method, params ? JSON.parse(params) : {})
45
+ console.log(JSON.stringify(result, null, 2))
46
+ })
47
+
48
+ cli.run()
package/index.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * headless.ly - Headless SaaS Platform for AI Agents
3
+ * @generated
4
+ */
5
+
6
+ // RPC client - all functionality is RPC against the backend
7
+ export { rpc, $ } from 'rpc.do'
8
+
9
+ // Convenience exports for common services
10
+ export const crm = (opts) => rpc('crm', opts)
11
+ export const sell = (opts) => rpc('sell', opts)
12
+ export const market = (opts) => rpc('market', opts)
13
+ export const erp = (opts) => rpc('erp', opts)
14
+ export const support = (opts) => rpc('support', opts)
15
+ export const analytics = (opts) => rpc('analytics', opts)
16
+ export const db = (opts) => rpc('db', opts)
17
+
18
+ // Re-export from rpc.do
19
+ import { rpc } from 'rpc.do'
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@headlessly/sdk",
3
+ "version": "0.0.1",
4
+ "description": "Headless SaaS Platform for AI Agents",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "types": "types.d.ts",
8
+ "bin": {
9
+ "headlessly": "./cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./index.js",
14
+ "require": "./index.js",
15
+ "types": "./types.d.ts"
16
+ },
17
+ "./nouns/*": {
18
+ "import": "./nouns/*/index.js",
19
+ "types": "./nouns/*/types.d.ts"
20
+ }
21
+ },
22
+ "files": [
23
+ "index.js",
24
+ "types.d.ts",
25
+ "cli.js",
26
+ "nouns/",
27
+ "README.md"
28
+ ],
29
+ "scripts": {
30
+ "test": "vitest run",
31
+ "test:watch": "vitest",
32
+ "typecheck": "vitest --typecheck"
33
+ },
34
+ "dependencies": {
35
+ "rpc.do": "^0.1.0",
36
+ "oauth.do": "^0.1.0",
37
+ "cli.do": "^0.1.0",
38
+ "mcp.do": "^0.1.0"
39
+ },
40
+ "devDependencies": {
41
+ "vitest": "^3.0.0",
42
+ "typescript": "^5.7.0"
43
+ },
44
+ "keywords": [
45
+ "headless",
46
+ "saas",
47
+ "ai",
48
+ "agents",
49
+ "rpc"
50
+ ],
51
+ "author": "headless.ly",
52
+ "license": "MIT",
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "https://github.com/headlessly/headless.ly"
56
+ },
57
+ "homepage": "https://headless.ly",
58
+ "publishConfig": {
59
+ "access": "public"
60
+ }
61
+ }
package/types.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * headless.ly - Headless SaaS Platform for AI Agents
3
+ * @generated from .db/ schemas
4
+ */
5
+
6
+ import type { RPCClient } from 'rpc.do'
7
+
8
+ // RPC exports
9
+ export { rpc, $ } from 'rpc.do'
10
+
11
+ // Service clients
12
+ export declare function crm(options?: { apiKey?: string }): RPCClient
13
+ export declare function sell(options?: { apiKey?: string }): RPCClient
14
+ export declare function market(options?: { apiKey?: string }): RPCClient
15
+ export declare function erp(options?: { apiKey?: string }): RPCClient
16
+ export declare function support(options?: { apiKey?: string }): RPCClient
17
+ export declare function analytics(options?: { apiKey?: string }): RPCClient
18
+ export declare function db(options?: { apiKey?: string }): RPCClient
19
+
20
+ // ============================================================================
21
+ // Entity Types (generated from .db/schema/)
22
+ // ============================================================================
23
+
24
+ // TODO: Generate from .db/schema/*.ts
25
+
26
+ // ============================================================================
27
+ // RPC Method Types
28
+ // ============================================================================
29
+
30
+ // TODO: Generate from RPC definitions