diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..f1ced41
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,6 @@
+{
+ "presets": [
+ "next/babel",
+ "@zeit/next-typescript/babel"
+ ]
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..85421a7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+.next/
+package-lock.json
\ No newline at end of file
diff --git a/next.config.js b/next.config.js
new file mode 100644
index 0000000..55495a2
--- /dev/null
+++ b/next.config.js
@@ -0,0 +1,2 @@
+const withTs = require('@zeit/next-typescript');
+module.exports = withTs();
diff --git a/nodemon.json b/nodemon.json
new file mode 100644
index 0000000..3e16e4c
--- /dev/null
+++ b/nodemon.json
@@ -0,0 +1,15 @@
+{
+ "ignore": [
+ "**/*.test.ts",
+ "**/*.spec.ts",
+ ".git",
+ "node_modules",
+ ".next"
+ ],
+ "watch": [
+ "server",
+ "types"
+ ],
+ "exec": "npm run dev",
+ "ext": "ts"
+}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9f1350d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "ydb",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "tsc": "tsc",
+ "dev": "ts-node --files ./server/index.ts",
+ "nodemon": "./node_modules/nodemon/bin/nodemon.js",
+ "lint:ts": "tslint -c tslint.json 'src/**/*.ts*'",
+ "pretty": "prettier --write client/**/*.ts* server/**/*.ts"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "@types/express-graphql": "^0.6.2",
+ "@types/graphql": "^14.2.0",
+ "@types/morgan": "^1.7.35",
+ "@zeit/next-typescript": "^1.1.1",
+ "express": "^4.16.4",
+ "express-graphql": "^0.8.0",
+ "express-router-async": "^0.3.0",
+ "graphql": "^14.2.1",
+ "morgan": "^1.9.1",
+ "next": "^8.1.0",
+ "nodemon": "^1.18.11",
+ "react": "^16.8.6",
+ "react-dom": "^16.8.6",
+ "ts-node": "^8.1.0",
+ "typescript": "^3.4.4"
+ },
+ "devDependencies": {
+ "@types/express": "^4.16.1",
+ "@types/next": "^8.0.3",
+ "husky": "^1.3.1",
+ "lint-staged": "^8.1.5",
+ "prettier": "^1.17.0",
+ "tslint": "^5.16.0",
+ "tslint-config-prettier": "^1.18.0"
+ },
+ "lint-staged": {
+ "*.ts*": [
+ "npm run pretty",
+ "git add"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/pages/_error.tsx b/pages/_error.tsx
new file mode 100644
index 0000000..b815d47
--- /dev/null
+++ b/pages/_error.tsx
@@ -0,0 +1,3 @@
+import * as React from 'react';
+
+export default () =>
o no error
diff --git a/pages/home.tsx b/pages/home.tsx
new file mode 100644
index 0000000..afb99f7
--- /dev/null
+++ b/pages/home.tsx
@@ -0,0 +1,3 @@
+import * as React from 'react';
+
+export default () => i home!
diff --git a/pages/index.tsx b/pages/index.tsx
new file mode 100644
index 0000000..738ba88
--- /dev/null
+++ b/pages/index.tsx
@@ -0,0 +1,3 @@
+import * as React from 'react';
+
+export default () => hi
diff --git a/server/graph/index.ts b/server/graph/index.ts
new file mode 100644
index 0000000..7c8172e
--- /dev/null
+++ b/server/graph/index.ts
@@ -0,0 +1,16 @@
+import { GraphQLSchema, GraphQLObjectType } from 'graphql';
+
+const schema = new GraphQLSchema({
+ query: new GraphQLObjectType({
+ name: 'RootQueries',
+ description: 'Top level queries',
+ fields: () => ({}),
+ }),
+ mutation: new GraphQLObjectType({
+ name: 'RootMutations',
+ description: 'Top level mutations',
+ fields: () => ({}),
+ }),
+});
+
+export default schema;
diff --git a/server/index.ts b/server/index.ts
new file mode 100644
index 0000000..3265b61
--- /dev/null
+++ b/server/index.ts
@@ -0,0 +1,24 @@
+import * as express from 'express';
+import * as morgan from 'morgan';
+import nextjs from './lib/next';
+import PagesRouter from './routers/pages';
+import GraphqlRouter from './routers/graphql';
+
+const app: express.Application = express();
+
+nextjs.nextApp.prepare().then(() => {
+ const port = process.env.SERVER_PORT || 8080;
+
+ app.use(morgan(':method :url :status'));
+
+ app.use(PagesRouter);
+ app.use(GraphqlRouter);
+
+ app.get('*', (req, res) => {
+ nextjs.handle(req, res);
+ });
+
+ app.listen(port, function() {
+ console.log(`started on port ${port}`);
+ });
+});
diff --git a/server/lib/next.ts b/server/lib/next.ts
new file mode 100644
index 0000000..52395c3
--- /dev/null
+++ b/server/lib/next.ts
@@ -0,0 +1,15 @@
+import * as express from 'express';
+import * as next from "next";
+
+const isDev = process.env.NODE_ENV !== 'production';
+
+const nextApp = next({ dev: isDev });
+const handle = nextApp.getRequestHandler();
+
+const nextjs = {
+ nextApp,
+ handle,
+ render: (req: express.Request, res: express.Response, page: string) => nextApp.render(req, res, page),
+};
+
+export default nextjs;
diff --git a/server/routers/graphql.ts b/server/routers/graphql.ts
new file mode 100644
index 0000000..ea4bba4
--- /dev/null
+++ b/server/routers/graphql.ts
@@ -0,0 +1,17 @@
+import * as express from 'express';
+import * as graphqlHTTP from 'express-graphql';
+import schema from '../graph';
+
+const router = express.Router();
+
+router.get('/graphql', graphqlHTTP({
+ schema,
+ graphiql: true,
+}))
+
+router.post('/graphql', graphqlHTTP({
+ schema,
+ graphiql: false,
+}))
+
+export default router;
diff --git a/server/routers/pages.ts b/server/routers/pages.ts
new file mode 100644
index 0000000..500394b
--- /dev/null
+++ b/server/routers/pages.ts
@@ -0,0 +1,15 @@
+import * as express from 'express';
+import * as asyncRouter from 'express-router-async';
+import nextjs from '../lib/next';
+
+const router = asyncRouter();
+
+router.get('/', (req: express.Request, res: express.Response) => {
+ nextjs.render(req, res, '/');
+});
+
+router.getAsync('/home', async (req: express.Request, res: express.Response) => {
+ nextjs.render(req, res, '/home');
+});
+
+export default router;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..ea38c5e
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "allowJs": true,
+ "allowSyntheticDefaultImports": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2017"
+ ],
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "noEmit": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "preserveConstEnums": true,
+ "removeComments": false,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "target": "es6"
+ },
+ "include": [
+ "./types/**/*"
+ ]
+}
\ No newline at end of file
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 0000000..a6abc25
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,15 @@
+{
+ "defaultSeverity": "error",
+ "extends": [
+ "tslint:recommended",
+ "tslint-config-prettier"
+ ],
+ "jsRules": {},
+ "rules": {
+ "quotemark": [
+ true,
+ "single"
+ ]
+ },
+ "rulesDirectory": []
+}
\ No newline at end of file
diff --git a/types/expressRouterAsync.d.ts b/types/expressRouterAsync.d.ts
new file mode 100644
index 0000000..6e12688
--- /dev/null
+++ b/types/expressRouterAsync.d.ts
@@ -0,0 +1,14 @@
+declare namespace Express {
+ interface IRoute {
+ getAsync: express.IRouterMatcher;
+ postAsync: express.IRouterMatcher;
+ }
+}
+
+declare module 'express-router-async' {
+ import * as express from 'express';
+
+ const router = express.IRouter;
+
+ export = router: express.IRouter;
+};