diff --git a/src/reader/cif/schema.ts b/src/reader/cif/schema.ts
index 28f2afca2d78d3956ce2ac46fd1d8bfa11f0585d..8b390a4862a022e49ddb34717ddba7d6509f91d1 100644
--- a/src/reader/cif/schema.ts
+++ b/src/reader/cif/schema.ts
@@ -101,6 +101,7 @@ export namespace Field {
         }
     }
 
+    // spec argument is to allow for specialised implementation for undefined fields
     function createSchema<T>(spec: Spec | undefined, ctor: (field: Data.Field, category: Data.Category, key: string) => Column.Column<T>): Schema<T> {
         return { type: 0 as any, ctor, undefinedField: (spec && spec.undefinedField) || Data.DefaultUndefinedField, alias: spec && spec.alias };
     }
diff --git a/src/reader/cif/schema/ddl.ts b/src/reader/cif/schema/ddl.ts
new file mode 100644
index 0000000000000000000000000000000000000000..562133592a0ecb811f45af4ff26eccd6896a9c62
--- /dev/null
+++ b/src/reader/cif/schema/ddl.ts
@@ -0,0 +1,2 @@
+
+// TODO save frame schema for ddl http://mmcif.wwpdb.org/dictionaries/mmcif_ddl.dic/Index/
diff --git a/src/reader/cif/schema/dic.ts b/src/reader/cif/schema/dic.ts
new file mode 100644
index 0000000000000000000000000000000000000000..96f8d19c8b514aa3aee3750320db8401cd525f1c
--- /dev/null
+++ b/src/reader/cif/schema/dic.ts
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Field, Block } from '../schema'
+
+const str = Field.str()
+const float = Field.float()
+
+const datablock = {
+    id: str,
+    description: str
+}
+
+const dictionary = {
+    title: str,
+    datablock_id: str,
+    version: str
+}
+
+const dictionary_history = {
+    version: str,
+    update: str,
+    revision: str
+}
+
+const sub_category = {
+    id: str,
+    description: str
+}
+
+const category_group_list = {
+    id: str,
+    parent_id: str,
+    description: str
+}
+
+const item_type_list = {
+    code: str,
+    primitive_code: str,
+    construct: str,
+    detail: str
+}
+
+const item_units_list = {
+    code: str,
+    detail: str
+}
+
+const item_units_conversion = {
+    from_code: str,
+    to_code: str,
+    operator: str,
+    factor: float
+}
+
+// TODO save frame dic schema
+
+const dic = {
+    datablock,
+    dictionary,
+    dictionary_history,
+    sub_category,
+    category_group_list,
+    item_type_list,
+    item_units_list,
+    item_units_conversion
+}
+
+type dic = Block.Instance<typeof dic>
+export default dic
diff --git a/src/reader/cif/schema/utils.ts b/src/reader/cif/schema/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42093d8391390b99cc3a7f6e5efb2161dd362af1
--- /dev/null
+++ b/src/reader/cif/schema/utils.ts
@@ -0,0 +1,100 @@
+
+// import dic from './dic'
+import { Field, Category } from '../schema'
+import * as Data from '../data-model'
+
+const pooledStr = Field.pooledStr()
+const str = Field.str()
+const int = Field.int()
+const float = Field.float()
+
+function getFieldType (type: string) {
+    switch (type) {
+        case 'code':
+        case 'ucode':
+        case 'line':
+        case 'uline':
+        case 'text':
+        case 'name':
+        case 'idname':
+        case 'any':
+        case 'atcode':
+        case 'fax':
+        case 'phone':
+        case 'email':
+        case 'code30':
+        case 'ec-type':
+        case 'seq-one-letter-code':
+        case 'author':
+        case 'orcid_id':
+        case 'sequence_dep':
+        case 'pdb_id':
+        case 'emd_id':
+        // todo, consider adding specialised fields
+        case 'yyyy-mm-dd':
+        case 'yyyy-mm-dd:hh:mm':
+        case 'yyyy-mm-dd:hh:mm-flex':
+        case 'int-range':
+        case 'float-range':
+        case 'binary':
+        case 'operation_expression':
+        case 'ucode-alphanum-csv':
+        case 'point_symmetry':
+        case 'id_list':
+        case '4x3_matrix':
+        case 'point_group':
+        case 'point_group_helical':
+        case 'boolean':
+        case 'symmetry_operation':
+        case 'date_dep':
+            return str
+        case 'uchar3':
+        case 'uchar1':
+        case 'symop':
+            return pooledStr
+        case 'int':
+        case 'non_negative_int':
+        case 'positive_int':
+            return int
+        case 'float':
+            return float
+    }
+    console.log(`unknown type '${type}'`)
+    return str
+}
+
+export function getSchema (dic: Data.Block) {  // todo Block needs to be specialized with safe frames as well
+    const schema: { [category: string]: Category.Schema } = {}
+
+    dic.saveFrames.forEach(d => {
+        if (d.header[0] !== '_') {
+            schema[d.header] = {}
+        } else {
+            const categoryName = d.header.substring(1, d.header.indexOf('.'))
+            const itemName = d.header.substring(d.header.indexOf('.') + 1)
+            let fields
+            if (categoryName in schema) {
+                fields = schema[categoryName]
+            } else {
+                fields = {}
+                schema[categoryName] = fields
+            }
+            // console.log(util.inspect(d.categories, {showHidden: false, depth: 1}))
+            const item_type = d.categories['_item_type']
+            if (item_type) {
+                const code = item_type.getField('code')
+                if (code) {
+                    fields[itemName] = getFieldType(code.str(0))
+                } else {
+                    console.log(`item_type.code not found for '${d.header}'`)
+                }
+            } else {
+                // TODO check for _item_linked.parent_name and use its type
+                console.log(`item_type not found for '${d.header}'`)
+            }
+
+        }
+    })
+
+    return schema
+}
diff --git a/src/script.ts b/src/script.ts
index 724767d15e7d62088e67cd2cd27ef6ec260647e0..06868a492c54fa9971cfd113a919448c5a9051f8 100644
--- a/src/script.ts
+++ b/src/script.ts
@@ -11,6 +11,8 @@ import * as fs from 'fs'
 import Gro from './reader/gro/parser'
 import CIF from './reader/cif/index'
 
+import { getSchema } from './reader/cif/schema/utils'
+
 const file = '1crn.gro'
 // const file = 'water.gro'
 // const file = 'test.gro'
@@ -148,8 +150,9 @@ async function runDic(input: string | Uint8Array) {
         return;
     }
 
-    const data = parsed.result.blocks[0];
-    console.log(util.inspect(data.saveFrames, {showHidden: false, depth: 3}))
+    const schema = getSchema(parsed.result.blocks[0])
+    // console.log(util.inspect(schema, {showHidden: false, depth: 1}))
+    console.log(util.inspect(Object.keys(schema).length, {showHidden: false, depth: 1}))
 }
 
 export function _dic() {