diff --git a/examples/with-emotion/.babelrc b/examples/with-emotion/.babelrc
new file mode 100644
index 000000000..625fc6a03
--- /dev/null
+++ b/examples/with-emotion/.babelrc
@@ -0,0 +1,11 @@
+{
+ "presets": ["razzle/babel"],
+ "env": {
+ "production": {
+ "plugins": ["@emotion"]
+ },
+ "development": {
+ "plugins": [["@emotion", { "sourceMap": true }]]
+ }
+ }
+}
\ No newline at end of file
diff --git a/examples/with-emotion/.gitignore b/examples/with-emotion/.gitignore
new file mode 100644
index 000000000..2b27d2abd
--- /dev/null
+++ b/examples/with-emotion/.gitignore
@@ -0,0 +1,12 @@
+logs
+*.log
+npm-debug.log*
+.DS_Store
+
+coverage
+node_modules
+build
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
\ No newline at end of file
diff --git a/examples/with-emotion/README.md b/examples/with-emotion/README.md
new file mode 100644
index 000000000..29f72cd7c
--- /dev/null
+++ b/examples/with-emotion/README.md
@@ -0,0 +1,24 @@
+# Razzle with-emotion Example
+
+## How to use
+Download the example [or clone the whole project](https://github.com/jaredpalmer/razzle.git):
+
+```bash
+curl https://codeload.github.com/jaredpalmer/razzle/tar.gz/master | tar -xz --strip=2 razzle-master/examples/with-emotion
+cd with-emotion
+```
+
+Install it and run:
+
+```bash
+yarn install
+yarn start
+```
+
+## Idea behind the example
+This is a basic, bare-bones example that shows a very minimal implementation
+of [emotion 11](https://github.com/emotion-js/emotion).
+It satisfies the entry points `src/index.js` for the server and`src/client.js`
+for the browser.
+There are comments in `src/server.js` to show how the styles are gathered and
+rendered into to the DOM
diff --git a/examples/with-emotion/package.json b/examples/with-emotion/package.json
new file mode 100644
index 000000000..218f2bce0
--- /dev/null
+++ b/examples/with-emotion/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "razzle-examples-with-emotion",
+ "version": "0.1.0",
+ "license": "MIT",
+ "scripts": {
+ "start": "razzle start",
+ "build": "razzle build",
+ "test": "razzle test --env=jsdom",
+ "start:prod": "NODE_ENV=production node build/server.js"
+ },
+ "dependencies": {
+ "express": "^4.15.2",
+ "react": "^16.13.0",
+ "react-dom": "^16.13.0",
+ "react-router": "^5.1.2",
+ "react-router-dom": "^5.1.2",
+ "@emotion/cache": "^11.0.0-next.10",
+ "@emotion/css": "^11.0.0-next.11",
+ "@emotion/react": "^11.0.0-next.11",
+ "@emotion/server": "^11.0.0-next.10",
+ "@emotion/styled": "^11.0.0-next.11"
+ },
+ "devDependencies": {
+ "razzle": "^3.0.0",
+ "@emotion/babel-plugin": "^11.0.0-next.10"
+ }
+}
diff --git a/examples/with-emotion/public/favicon.ico b/examples/with-emotion/public/favicon.ico
new file mode 100644
index 000000000..46bceb8c7
Binary files /dev/null and b/examples/with-emotion/public/favicon.ico differ
diff --git a/examples/with-emotion/public/robots.txt b/examples/with-emotion/public/robots.txt
new file mode 100644
index 000000000..54fb98911
--- /dev/null
+++ b/examples/with-emotion/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+
diff --git a/examples/with-emotion/src/App.js b/examples/with-emotion/src/App.js
new file mode 100644
index 000000000..d43c45245
--- /dev/null
+++ b/examples/with-emotion/src/App.js
@@ -0,0 +1,27 @@
+import React from 'react';
+import { Route, Switch, Link } from 'react-router-dom';
+import styled from '@emotion/styled';
+import { GreenPage } from './pages/green/green.page';
+import { HomePage } from './pages/home/home.page';
+import { Footer } from './components/footer';
+import { Header } from './components/header';
+
+const Root = styled.div`
+ width: 980px;
+ margin: auto;
+`;
+
+const App = () => (
+
+
+
+
+
+
+
+
+
+
+);
+
+export default App;
diff --git a/examples/with-emotion/src/App.test.js b/examples/with-emotion/src/App.test.js
new file mode 100644
index 000000000..d998494fe
--- /dev/null
+++ b/examples/with-emotion/src/App.test.js
@@ -0,0 +1,16 @@
+import App from './App';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import MemoryRouter from 'react-router-dom/MemoryRouter';
+
+describe('', () => {
+ test('renders without exploding', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(
+
+
+ ,
+ div
+ );
+ });
+});
diff --git a/examples/with-emotion/src/client.js b/examples/with-emotion/src/client.js
new file mode 100644
index 000000000..5b264501e
--- /dev/null
+++ b/examples/with-emotion/src/client.js
@@ -0,0 +1,33 @@
+import App from './App';
+import { BrowserRouter } from 'react-router-dom';
+import React from 'react';
+import { hydrate } from 'react-dom';
+import { CacheProvider, Global, css } from '@emotion/react';
+import { cache } from '@emotion/css';
+
+hydrate(
+
+
+
+
+
+ ,
+ document.getElementById('root')
+);
+
+if (module.hot) {
+ module.hot.accept();
+}
diff --git a/examples/with-emotion/src/components/footer/footer.component.js b/examples/with-emotion/src/components/footer/footer.component.js
new file mode 100644
index 000000000..255e8bd23
--- /dev/null
+++ b/examples/with-emotion/src/components/footer/footer.component.js
@@ -0,0 +1,30 @@
+import React from 'react';
+
+/** @jsx jsx */
+import { jsx, css } from '@emotion/react';
+
+export const Footer = () => (
+
+);
diff --git a/examples/with-emotion/src/components/footer/index.js b/examples/with-emotion/src/components/footer/index.js
new file mode 100644
index 000000000..a50d57382
--- /dev/null
+++ b/examples/with-emotion/src/components/footer/index.js
@@ -0,0 +1 @@
+export * from './footer.component';
diff --git a/examples/with-emotion/src/components/header/header.component.js b/examples/with-emotion/src/components/header/header.component.js
new file mode 100644
index 000000000..8c6cc0db4
--- /dev/null
+++ b/examples/with-emotion/src/components/header/header.component.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import logo from '../../react.svg';
+import { Link } from 'react-router-dom';
+/** @jsx jsx */
+import { jsx, css } from '@emotion/react';
+import styled from '@emotion/styled';
+
+const Root = styled.div`
+ .top-bar {
+ display: flex;
+ .left {
+ flex: 1;
+ display: flex;
+ img {
+ width: 64px;
+ margin-right: 1rem;
+ }
+ }
+ .right {
+ flex: 0;
+ list-style: none;
+ display: inline-flex;
+ margin: 2rem auto;
+ li {
+ margin: 0 1rem;
+ }
+ }
+ }
+`;
+
+export const Header = () => (
+
+
+
+

+
Razzle
+
+
+
+
+);
diff --git a/examples/with-emotion/src/components/header/index.js b/examples/with-emotion/src/components/header/index.js
new file mode 100644
index 000000000..be62c26c7
--- /dev/null
+++ b/examples/with-emotion/src/components/header/index.js
@@ -0,0 +1 @@
+export * from './header.component';
diff --git a/examples/with-emotion/src/index.js b/examples/with-emotion/src/index.js
new file mode 100644
index 000000000..901931fe2
--- /dev/null
+++ b/examples/with-emotion/src/index.js
@@ -0,0 +1,32 @@
+import http from 'http';
+
+let app = require('./server').default;
+
+const server = http.createServer(app);
+
+let currentApp = app;
+
+server.listen(process.env.PORT || 3000, error => {
+ if (error) {
+ console.log(error);
+ }
+
+ console.log('🚀 started');
+});
+
+if (module.hot) {
+ console.log('✅ Server-side HMR Enabled!');
+
+ module.hot.accept('./server', () => {
+ console.log('🔁 HMR Reloading `./server`...');
+
+ try {
+ app = require('./server').default;
+ server.removeListener('request', currentApp);
+ server.on('request', app);
+ currentApp = app;
+ } catch (error) {
+ console.error(error);
+ }
+ });
+}
diff --git a/examples/with-emotion/src/pages/green/green.page.js b/examples/with-emotion/src/pages/green/green.page.js
new file mode 100644
index 000000000..6f409da73
--- /dev/null
+++ b/examples/with-emotion/src/pages/green/green.page.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import * as S from './green.styled';
+
+export const GreenPage = () => {
+ return (
+ <>
+ Hello, I am Green
+ >
+ );
+};
diff --git a/examples/with-emotion/src/pages/green/green.styled.js b/examples/with-emotion/src/pages/green/green.styled.js
new file mode 100644
index 000000000..4de47230f
--- /dev/null
+++ b/examples/with-emotion/src/pages/green/green.styled.js
@@ -0,0 +1,5 @@
+import styled from '@emotion/styled';
+
+export const Title = styled.h3`
+ color: green;
+`;
diff --git a/examples/with-emotion/src/pages/green/index.js b/examples/with-emotion/src/pages/green/index.js
new file mode 100644
index 000000000..4f2f7c770
--- /dev/null
+++ b/examples/with-emotion/src/pages/green/index.js
@@ -0,0 +1 @@
+export * from './green.page';
diff --git a/examples/with-emotion/src/pages/home/home.page.js b/examples/with-emotion/src/pages/home/home.page.js
new file mode 100644
index 000000000..01d509b48
--- /dev/null
+++ b/examples/with-emotion/src/pages/home/home.page.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import logo from '../../react.svg';
+import styled from '@emotion/styled';
+import { Link } from 'react-router-dom';
+import { Header } from '../../components/header';
+
+const Blue = styled.h3`
+ color: blue;
+`;
+
+export const HomePage = () => {
+ return (
+
+
+ To get started, edit src/App.js or src/Home.js{' '}
+ and save to reload.
+
+
+ Hello, I am Blue
+
+
+ );
+};
diff --git a/examples/with-emotion/src/pages/home/index.js b/examples/with-emotion/src/pages/home/index.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/with-emotion/src/react.svg b/examples/with-emotion/src/react.svg
new file mode 100644
index 000000000..2fddb2824
--- /dev/null
+++ b/examples/with-emotion/src/react.svg
@@ -0,0 +1,6 @@
+
+
diff --git a/examples/with-emotion/src/server.js b/examples/with-emotion/src/server.js
new file mode 100644
index 000000000..3cf580c6b
--- /dev/null
+++ b/examples/with-emotion/src/server.js
@@ -0,0 +1,55 @@
+import App from './App';
+import React from 'react';
+import { StaticRouter } from 'react-router-dom';
+import express from 'express';
+import { renderToString } from 'react-dom/server';
+import { extractCritical } from '@emotion/server';
+
+const assets = require(process.env.RAZZLE_ASSETS_MANIFEST);
+
+const server = express();
+server
+ .disable('x-powered-by')
+ .use(express.static(process.env.RAZZLE_PUBLIC_DIR))
+ .get('/*', (req, res) => {
+ const context = {};
+ const { css, html: markup, ids } = extractCritical(
+ renderToString(
+
+
+
+ )
+ );
+
+ if (context.url) {
+ res.redirect(context.url);
+ } else {
+ res.status(200).send(
+ `
+
+
+
+
+ Welcome to Razzle
+
+
+ ${
+ assets.client.css
+ ? ``
+ : ''
+ }
+ ${
+ process.env.NODE_ENV === 'production'
+ ? ``
+ : ``
+ }
+
+
+ ${markup}
+
+`
+ );
+ }
+ });
+
+export default server;