Skip to content

TypeScript first. Language-agnostic by design.

Atscript

Define your models once

Get TypeScript types, runtime validation, and DB metadata from a single `.as` model.

Atscript is built to power a broader model-driven stack over time. Today, TypeScript is the first supported plugin.

Atscript

No more scattered definitions

Before 3 files
db/schema.ts
ts
import { pgTable, serial, varchar, integer, uniqueIndex } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  email: varchar('email', { length: 255 }).notNull(),
  name: varchar('name', { length: 100 }).notNull(),
  age: integer('age').notNull(),
  role: varchar('role', { enum: ['admin', 'user'] }),
}, (t) => [uniqueIndex().on(t.email)])
validation/user.schema.ts
ts
import { createInsertSchema } from 'drizzle-zod'
import { users } from '../db/schema'

export const insertUserSchema = createInsertSchema(users, {
  email: (s) => s.email.email(),
  name: (s) => s.name.min(2).max(100),
  age: (s) => s.age.positive(),
})
components/UserForm.tsx
tsx
const fieldConfig = {
  email: { label: 'Email Address', placeholder: 'alice@company.com' },
  name:  { label: 'Full Name', placeholder: 'Alice Smith' },
  age:   { label: 'Age', type: 'number' },
  role:  { label: 'Role', component: 'select' },
}
After 1 file
user.as
atscript
@db.table 'users'
export interface User {
  @meta.id
  id: number

  @meta.label "Email Address"
  @ui.placeholder "alice@company.com"
  @db.index.unique 'email_idx'
  email: string.email

  @meta.label "Full Name"
  @ui.placeholder "Alice Smith"
  @expect.minLength 2
  @expect.maxLength 100
  @db.index.fulltext 'search_idx'
  name: string

  @meta.label "Age"
  age: number.int.positive

  @meta.label "Role"
  @ui.component "select"
  role?: 'admin' | 'user'
}
Available today

TypeScript + Validation

Start with one .as model. Atscript turns that model into TypeScript types, runtime metadata, and validation rules without a second schema layer.

string.email@expect.*User.validator()JSON Schema
  • Keep type shape and runtime rules on the same model.
  • Generate runtime metadata and JSON Schema from the same definition.
  • TypeScript is the first supported plugin and the best place to start today.
Email
Available today

DB + API Integrations

The same model can drive schema annotations, relations, sync, CRUD helpers, and REST/CRUD integrations instead of splitting those concerns into separate definitions. SQLite and MongoDB adapters are available today.

@db.table@db.rel.FKschema syncCRUD over HTTP
  • Define tables, relations, defaults, and indexes in the model itself.
  • Keep data-layer behavior aligned with the same types and validation rules.
  • Use supported SQLite, MongoDB, and Moost-based integrations from one source of truth.
User ProfileidPostidCommentid
Planned

UI Forms + Table Views

The long-term direction is one model across UI, API, TypeScript, and DB. The same metadata that powers runtime tooling today is the basis for automated forms and data-table views later.

@meta.labelfield hintsvalidation rulestable views
  • Reuse labels and constraints instead of rewriting them in UI config.
  • Keep forms and tables aligned with the model as the schema evolves.
  • Build toward a model-driven data flow from UI to API to TypeScript to DB.
user.as
Architecture

Language-agnostic by design

Atscript is not built as a TypeScript-only schema DSL. The core model and plugin system are meant to support other language targets over time, while TypeScript remains the first and most complete implementation today.

.as model->TypeScript plugin today->other targets later
  • The .as model stays stable as the shared schema layer.
  • Plugins define code generation and runtime behavior for each target ecosystem.
  • That lets Atscript grow beyond TypeScript without changing the core modeling idea.

Released under the MIT License.