├── src ├── app │ ├── routes │ │ ├── Home │ │ │ ├── index.js │ │ │ ├── defaultQuery.js │ │ │ └── Home.js │ │ └── NotFound │ │ │ ├── index.js │ │ │ └── NotFound.js │ ├── .DS_Store │ ├── components │ │ └── App │ │ │ ├── index.js │ │ │ └── App.js │ ├── styles │ │ └── main.css │ └── assets │ │ └── logo.svg ├── .DS_Store ├── server │ ├── types │ │ ├── TalkPrepared.graphql │ │ ├── Contributor.graphql │ │ ├── Job.graphql │ │ ├── Project.graphql │ │ ├── Repo.graphql │ │ ├── Talk.graphql │ │ ├── index.js │ │ ├── SpeakerInfo.graphql │ │ └── Query.graphql │ ├── data │ │ ├── countries.js │ │ ├── basic.js │ │ ├── main.js │ │ ├── github.js │ │ ├── resume.json │ │ ├── speaker-info.js │ │ ├── projects.js │ │ └── talks.js │ ├── middleware │ │ ├── webpack.js │ │ └── render.js │ └── index.js └── client │ └── index.js ├── .vscode └── settings.json ├── .travis.yml ├── .babelrc ├── README.md ├── .eslintrc ├── .gitignore ├── .editorconfig ├── webpack ├── common.js ├── webpack.server.babel.js └── webpack.client.babel.js ├── LICENSE ├── yarn-error.log └── package.json /src/app/routes/Home/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Home' 2 | -------------------------------------------------------------------------------- /src/app/routes/NotFound/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './NotFound' 2 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaraVieira/graphql-portfolio/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /src/app/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaraVieira/graphql-portfolio/HEAD/src/app/.DS_Store -------------------------------------------------------------------------------- /src/app/components/App/index.js: -------------------------------------------------------------------------------- 1 | import '../../styles/main.css' 2 | export { default } from './App' 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true, 3 | "prettier.trailingComma": "none" 4 | } 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 7 4 | - 6 5 | - 8 6 | script: npm run lint && npm run build 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-object-rest-spread" 4 | ], 5 | "presets": [ 6 | "env" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Licensed under the MIT LICENSE 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "prettier-standard/lib/base", 4 | "standard-react", 5 | "prettier" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/server/types/TalkPrepared.graphql: -------------------------------------------------------------------------------- 1 | type TalksPrepared { 2 | # Talk Name 3 | name: String, 4 | # Talk Description 5 | description: String 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | stats.json 4 | .vscode 5 | 6 | # Ignore Mac DS_Store files 7 | .DS_Store 8 | 9 | # Ignore IntelliJ generated files 10 | .idea 11 | -------------------------------------------------------------------------------- /src/app/styles/main.css: -------------------------------------------------------------------------------- 1 | body, 2 | html, 3 | #root { 4 | padding: 0; 5 | margin: 0; 6 | height: 100%; 7 | } 8 | 9 | .variable-editor { 10 | display: none; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/routes/NotFound/NotFound.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const NotFound = () => ( 4 |
5 |

Page not found

6 |
7 | ) 8 | 9 | export default NotFound 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /src/server/data/countries.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | 'Portugal', 3 | 'Spain', 4 | 'Germany', 5 | 'Netherlands', 6 | 'Poland', 7 | 'Austria', 8 | 'United Kingdom', 9 | 'France', 10 | 'Switzerland' 11 | ] 12 | -------------------------------------------------------------------------------- /src/server/types/Contributor.graphql: -------------------------------------------------------------------------------- 1 | # List of amazing people who helped this project 2 | type Contributor { 3 | # Name of the Amazing Person that contributed 4 | name: String 5 | # Their Github URL 6 | url: String 7 | } 8 | -------------------------------------------------------------------------------- /src/server/types/Job.graphql: -------------------------------------------------------------------------------- 1 | # Jobs I have had or still have 2 | type Job { 3 | # Name of the Company 4 | company: String 5 | # Title I had there 6 | title: String! 7 | # Where this job was located 8 | location: String 9 | # Started Date 10 | started: String 11 | # End date 12 | finished: String 13 | } 14 | -------------------------------------------------------------------------------- /src/server/types/Project.graphql: -------------------------------------------------------------------------------- 1 | # Dumb and maybe not so dumb Projects/Packages I have done over the years 2 | type Project { 3 | # Name 4 | name: String! 5 | # Description 6 | description: String 7 | # The repo of this 8 | github: String 9 | # The website of this if there is one 10 | website: String 11 | } 12 | -------------------------------------------------------------------------------- /src/server/types/Repo.graphql: -------------------------------------------------------------------------------- 1 | # All my github repos 2 | type Repo { 3 | # Repo Name 4 | name: String 5 | # Link to repo 6 | url: String 7 | # Repo description 8 | description: String 9 | # Language used 10 | language: String 11 | # Number of stars 12 | stars: Int 13 | # Is it forked? 14 | fork: Boolean! 15 | # Owner of the repo 16 | owner: String 17 | } 18 | -------------------------------------------------------------------------------- /src/server/types/Talk.graphql: -------------------------------------------------------------------------------- 1 | type Talk { 2 | # Talk name 3 | name: String 4 | # The awesome event that hosted this talk 5 | event: String 6 | # The Date 7 | date: String 8 | # Video link if there is one 9 | video: String 10 | # Slides link if there is one 11 | slides: String 12 | # Have I already done this talk? 13 | done: Boolean, 14 | # Where is this ? 15 | location: String 16 | } 17 | -------------------------------------------------------------------------------- /src/server/middleware/webpack.js: -------------------------------------------------------------------------------- 1 | import devMiddleware from 'webpack-dev-middleware' 2 | import hotMiddleware from 'webpack-hot-middleware' 3 | import webpack from 'webpack' 4 | 5 | import config from '../../../webpack/webpack.client.babel' 6 | 7 | const compiler = webpack(config) 8 | 9 | export const webpackDevMiddleware = devMiddleware(compiler, { 10 | stats: 'minimal' 11 | }) 12 | export const webpackHotMiddleware = hotMiddleware(compiler) 13 | -------------------------------------------------------------------------------- /src/client/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { BrowserRouter as Router } from 'react-router-dom' 3 | import { render } from 'react-dom' 4 | import App from '../app/components/App' 5 | import * as OfflinePluginRuntime from 'offline-plugin/runtime' 6 | 7 | render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ) 13 | 14 | if (module.hot) { 15 | module.hot.accept() 16 | } 17 | OfflinePluginRuntime.install() 18 | -------------------------------------------------------------------------------- /src/server/data/basic.js: -------------------------------------------------------------------------------- 1 | const distanceInWordsToNow = require('date-fns/distance_in_words_to_now') 2 | 3 | module.exports = { 4 | name: 'Sara Vieira', 5 | company: 'YLD', 6 | email: 'hey@iamsaravieira.com', 7 | age: distanceInWordsToNow(new Date(1991, 11, 29)), 8 | twitter: 'https://twitter.com/NikkitaFTW', 9 | github: 'https://github.com/SaraVieira/', 10 | instagram: 'https://www.instagram.com/niikkitaftw/', 11 | medium: 'https://medium.com/@nikkitaftw' 12 | } 13 | -------------------------------------------------------------------------------- /src/app/components/App/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Route, Switch } from 'react-router-dom' 3 | 4 | import Home from '../../routes/Home' 5 | import NotFound from '../../routes/NotFound' 6 | 7 | const App = () => { 8 | return ( 9 |
10 | 11 | 12 | 13 | 14 |
15 | ) 16 | } 17 | 18 | export default App 19 | -------------------------------------------------------------------------------- /src/server/types/index.js: -------------------------------------------------------------------------------- 1 | import Job from './Job.graphql' 2 | import Repo from './Repo.graphql' 3 | import Talk from './Talk.graphql' 4 | import Query from './Query.graphql' 5 | import Contributor from './Contributor.graphql' 6 | import Project from './Project.graphql' 7 | import SpeakerInfo from './SpeakerInfo.graphql' 8 | import TalkPrepared from './TalkPrepared.graphql' 9 | 10 | export { 11 | Job, 12 | Repo, 13 | Talk, 14 | Query, 15 | Contributor, 16 | Project, 17 | SpeakerInfo, 18 | TalkPrepared 19 | } 20 | -------------------------------------------------------------------------------- /src/server/types/SpeakerInfo.graphql: -------------------------------------------------------------------------------- 1 | # Speaker Info for talks (this part is mostly for me 😝) 2 | type SpeakerInfo { 3 | # My Name 4 | name: String 5 | # My Email 6 | email: String 7 | # My Twitter handler 8 | twitter: String 9 | # My GitHub name 10 | github: String 11 | # Shirt size I want 12 | shirtSize: String 13 | # Country flying from 14 | country: String, 15 | # My Bio 16 | bio: String 17 | # My Photo 18 | photo: String 19 | # Talks 20 | talks: [TalksPrepared] 21 | # Recored Talks 22 | videos: [String] 23 | } 24 | -------------------------------------------------------------------------------- /src/app/routes/Home/defaultQuery.js: -------------------------------------------------------------------------------- 1 | const defaultQuery = ` 2 | # Yellow 3 | # My name is Sara and I am Front End Developer from Portugal 4 | # I made this GraphQL API as my page because everyone loves GraphQL 5 | # Also it's waaay easier to update like this. 6 | # Check out the Docs and here is a sample query 7 | 8 | { 9 | name, 10 | age, 11 | email, 12 | github, 13 | twitter, 14 | employed, 15 | talks, 16 | projects, 17 | jobs, 18 | repos, 19 | contributors 20 | } 21 | ` 22 | export default defaultQuery 23 | -------------------------------------------------------------------------------- /src/server/types/Query.graphql: -------------------------------------------------------------------------------- 1 | # Fun right!? 2 | type Query { 3 | # My Name 4 | name: String! 5 | # My Age 6 | age: String! 7 | # My Email 8 | email: String! 9 | # The company I work for as of now 10 | company: String! 11 | # My Twitter handler 12 | twitter: String! 13 | # My GitHub name 14 | github: String! 15 | # Am I employed? 16 | employed: Boolean! 17 | jobs: [Job] 18 | repos: [Repo] 19 | talks: [Talk] 20 | contributors: [Contributor] 21 | projects: [Project] 22 | countries: [String], 23 | speakerInfo: SpeakerInfo, 24 | # Have fun 25 | randomCurseWord: String 26 | } 27 | -------------------------------------------------------------------------------- /src/server/data/main.js: -------------------------------------------------------------------------------- 1 | const curseWords = require('curse-words-common') 2 | const uniqueRandomArray = require('unique-random-array') 3 | const jobs = require('./resume.json') 4 | const { repos, contributors } = require('./github') 5 | const talks = require('./talks') 6 | const projects = require('./projects') 7 | const countries = require('./countries') 8 | const speakerInfo = require('./speaker-info') 9 | const basic = require('./basic') 10 | 11 | const rand = uniqueRandomArray(curseWords) 12 | 13 | module.exports = { 14 | ...basic, 15 | randomCurseWord: rand(), 16 | jobs, 17 | repos, 18 | talks, 19 | projects, 20 | contributors, 21 | countries, 22 | speakerInfo 23 | } 24 | -------------------------------------------------------------------------------- /src/app/routes/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import GraphiQL from 'graphiql' 3 | import fetch from 'isomorphic-fetch' 4 | import Logo from '../../assets/logo.svg' 5 | import defaultQuery from './defaultQuery' 6 | import 'graphiql-material-theme' 7 | 8 | const graphQLFetcher = graphQLParams => 9 | fetch('/graphql', { 10 | method: 'post', 11 | headers: { 'Content-Type': 'application/json' }, 12 | body: JSON.stringify(graphQLParams) 13 | }).then(response => response.json()) 14 | 15 | const Home = () => ( 16 | 20 | 21 | Logo 22 | 23 | 24 | ) 25 | 26 | export default Home 27 | -------------------------------------------------------------------------------- /src/server/data/github.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | 3 | export const repos = axios( 4 | 'https://api.github.com/users/SaraVieira/repos?type=all&per_page=100' 5 | ) 6 | .then(repos => 7 | repos.data.map(repo => ({ 8 | name: repo.name, 9 | url: repo.html_url, 10 | description: repo.description, 11 | language: repo.language, 12 | stars: repo.stargazers_count, 13 | fork: repo.fork, 14 | owner: repo.owner.login 15 | })) 16 | ) 17 | .then(repos => repos.filter(r => !r.fork)) 18 | .then(repos => repos.sort((a, b) => b.stars - a.stars)) 19 | 20 | export const contributors = axios( 21 | 'https://api.github.com/repos/SaraVieira/graphql-portfolio/contributors' 22 | ).then(contributors => 23 | contributors.data.map(contributor => ({ 24 | name: contributor.login, 25 | url: contributor.html_url 26 | })) 27 | ) 28 | -------------------------------------------------------------------------------- /src/server/data/resume.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "company": "YLD", 4 | "title": "Full-stack Developer", 5 | "location": "Lisboa/London", 6 | "started": "Sep 2017", 7 | "finished": "" 8 | }, 9 | { 10 | "company": "Mindera", 11 | "title": "Front End Developer", 12 | "location": "Porto", 13 | "started": "Apr 2016", 14 | "finished": "Sep 2017" 15 | }, 16 | { 17 | "company": "Porto Tech Center (Africa Internet Group)", 18 | "title": "Front End Developer", 19 | "location": "Porto, Portugal", 20 | "started": "Feb 2015", 21 | "finished": "Apr 2016" 22 | }, 23 | { 24 | "company": "Pixelmatters", 25 | "title": "Front-End Developer", 26 | "location": "Porto", 27 | "started": "Aug 2014", 28 | "finished": "Dec 2014" 29 | }, 30 | { 31 | "company": "Ideoma Design", 32 | "title": "Developer / Wordpress", 33 | "location": "Vila Nova de Gaia", 34 | "started": "Jan 2014", 35 | "finished": "Jul 2014" 36 | } 37 | ] 38 | -------------------------------------------------------------------------------- /webpack/common.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import webpack from 'webpack' 3 | 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | 6 | export const babelLoaderOptions = { 7 | cacheDirectory: !isProduction, 8 | plugins: [ 9 | 'transform-object-rest-spread', 10 | ...(isProduction && ['transform-react-remove-prop-types']) 11 | ] 12 | } 13 | 14 | export const cssLoaderOptions = { 15 | minimize: isProduction 16 | } 17 | 18 | export const urlLoaderOptions = { 19 | limit: 10000, 20 | name: `media/[name]${isProduction ? '.[hash:8]' : ''}.[ext]` 21 | } 22 | 23 | export default { 24 | output: { 25 | path: path.resolve(__dirname, '../build'), 26 | publicPath: '/' 27 | }, 28 | plugins: [ 29 | new webpack.DefinePlugin({ 30 | 'process.env': { 31 | NODE_ENV: JSON.stringify(process.env.NODE_ENV) 32 | } 33 | }), 34 | ...(isProduction && [ 35 | new webpack.optimize.UglifyJsPlugin({ comments: false }) 36 | ]) 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Richard Käll (richardkall.se) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/server/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable global-require, no-console */ 2 | import path from 'path' 3 | import compression from 'compression' 4 | import express from 'express' 5 | import format from 'date-fns/format' 6 | import graphqlHTTP from 'express-graphql' 7 | import morgan from 'morgan' 8 | import { makeExecutableSchema } from 'graphql-tools' 9 | 10 | import data from './data/main' 11 | import renderMiddleware from './middleware/render' 12 | 13 | // Schemas 14 | import { 15 | Job, 16 | Repo, 17 | Talk, 18 | Query, 19 | Contributor, 20 | Project, 21 | SpeakerInfo, 22 | TalkPrepared 23 | } from './types' 24 | 25 | const isProduction = process.env.NODE_ENV === 'production' 26 | const port = process.env.PORT || 3000 27 | const app = express() 28 | 29 | const typeDefs = Query.concat( 30 | Job, 31 | Project, 32 | Repo, 33 | Talk, 34 | Contributor, 35 | SpeakerInfo, 36 | TalkPrepared 37 | ) 38 | 39 | const resolvers = { 40 | Query: { 41 | name: () => data.name, 42 | age: () => data.age, 43 | email: () => data.email, 44 | company: () => data.company, 45 | twitter: () => data.twitter, 46 | github: () => data.github, 47 | employed: () => true, 48 | jobs: () => data.jobs, 49 | repos: () => data.repos, 50 | randomCurseWord: () => data.randomCurseWord, 51 | contributors: () => data.contributors, 52 | countries: () => data.countries, 53 | talks: () => 54 | data.talks.map(talk => ({ 55 | ...talk, 56 | date: format(talk.date, 'DD/MM/YY') 57 | })), 58 | projects: () => data.projects, 59 | speakerInfo: () => data.speakerInfo 60 | } 61 | } 62 | 63 | const schema = makeExecutableSchema({ typeDefs, resolvers }) 64 | 65 | if (isProduction) { 66 | app.use(compression()) 67 | } else { 68 | const { 69 | webpackDevMiddleware, 70 | webpackHotMiddleware 71 | } = require('./middleware/webpack') 72 | 73 | app.use(webpackDevMiddleware) 74 | app.use(webpackHotMiddleware) 75 | } 76 | 77 | app.use( 78 | '/graphql', 79 | graphqlHTTP({ 80 | schema, 81 | graphiql: false 82 | }) 83 | ) 84 | 85 | app.use(morgan(isProduction ? 'combined' : 'dev')) 86 | app.use(express.static(path.resolve(__dirname, '../build'))) 87 | app.use(renderMiddleware) 88 | 89 | app.listen(port, console.log(`Server running on port ${port}`)) 90 | -------------------------------------------------------------------------------- /src/server/data/speaker-info.js: -------------------------------------------------------------------------------- 1 | import basic from './basic' 2 | import talks from './talks' 3 | 4 | module.exports = { 5 | name: basic.name, 6 | email: basic.email, 7 | twitter: basic.twitter, 8 | github: basic.github, 9 | shirtSize: "Men's M", 10 | country: 'Portugal', 11 | bio: 12 | 'Front-End Developer at @YLDio, open sorcerer, Blogger , Drummer and horror movie fan girl 🐈🎃🇵🇹🌈', 13 | photo: 'https://avatars0.githubusercontent.com/u/1051509?s=460&v=4', 14 | talks: [ 15 | { 16 | name: 'We need to talk about Preact', 17 | description: 18 | "I know many of you have heard about Preact and may have even played around with it but have you seen it's true potential? In this talk we are going to have the needed discussion about Preact and why it's awesome." 19 | }, 20 | { 21 | name: 'The Dream of Styleguide Driven Development', 22 | description: 23 | 'React is awesome! We probably all here agree on that. You have heard of all types of driven development but react emerged a new type, styleguide driven development became a reality with components. This type of development focuses on Developer/Designer collaboration and on assertive components. With the use of React, CSS Modules, Flow and Snapshot testing we were able to almost remove style regressions. In this talk you get a glimpse of you can start styleguide driven development and how you can sell this dream to your project managers. ' 24 | }, 25 | { 26 | name: "Let's manage our local state with GraphQL.", 27 | description: 28 | "Apollo has given us freedom and happiness when it comes to managing our data coming from the server but we still had to write code and sometimes a lot of it to manage our local state? Well, what if we managed it with queries too? Sounds too awesome right? Let's learn how to do this with apollo-link-state" 29 | }, 30 | { 31 | name: 'The Lonely and Dark Road to Styling in React', 32 | description: `CSS is hard !I made a living out of it being hard but when React was introduced we had a whole new level of fighting over CSS, there are so many ways to approach it and so many tradeoffs one can do when choosing the better approach that a talk that will go over these options is more than necessary. 33 | Let's walk this road thogheter and I promise it will all be fine and you will leave with an ideia of type of styling is better for each project. 34 | Hint: There is no perfect way ....` 35 | } 36 | ], 37 | videos: talks.map(talk => talk.video && talk.video) 38 | } 39 | -------------------------------------------------------------------------------- /src/server/middleware/render.js: -------------------------------------------------------------------------------- 1 | /* global VENDOR_BUNDLE: true, CLIENT_BUNDLE: true */ 2 | function render(req, res) { 3 | const context = {} 4 | 5 | if (context.url) { 6 | return res.redirect(302, context.url) 7 | } 8 | 9 | return res.status(context.status || 200).send(` 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Sara Vieira 29 | 30 | 31 |
32 |
33 | 37 | 38 | 39 | 54 | 55 | 56 | `) 57 | } 58 | 59 | export default render 60 | -------------------------------------------------------------------------------- /webpack/webpack.server.babel.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-unresolved, global-require */ 2 | import nodeExternals from 'webpack-node-externals' 3 | import webpack from 'webpack' 4 | 5 | import common, { 6 | babelLoaderOptions, 7 | cssLoaderOptions, 8 | urlLoaderOptions 9 | } from './common' 10 | 11 | const isProduction = process.env.NODE_ENV === 'production' 12 | 13 | export default { 14 | name: 'server', 15 | entry: './src/server', 16 | target: 'node', 17 | node: { 18 | __dirname: false 19 | }, 20 | output: { 21 | ...common.output, 22 | filename: 'server.js', 23 | libraryTarget: 'commonjs2' 24 | }, 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.css$/, 29 | use: [ 30 | { 31 | loader: 'style-loader' 32 | }, 33 | { 34 | loader: 'css-loader', 35 | options: cssLoaderOptions 36 | } 37 | ] 38 | }, 39 | { 40 | test: /\.js$/, 41 | exclude: /node_modules/, 42 | use: [ 43 | { 44 | loader: 'babel-loader', 45 | options: { 46 | ...babelLoaderOptions, 47 | presets: [ 48 | [ 49 | 'env', 50 | { 51 | targets: { 52 | node: true 53 | }, 54 | modules: false 55 | } 56 | ], 57 | 'react' 58 | ] 59 | } 60 | } 61 | ] 62 | }, 63 | { 64 | test: /\.flow$/, 65 | use: 'null-loader' 66 | }, 67 | { 68 | test: /\.graphql$/, 69 | use: 'raw-loader' 70 | }, 71 | { 72 | include: /\.(png|jpeg|jpg|svg)$/, 73 | use: [ 74 | { 75 | loader: 'url-loader', 76 | options: { 77 | ...urlLoaderOptions, 78 | emitFile: false 79 | } 80 | } 81 | ] 82 | } 83 | ] 84 | }, 85 | plugins: [ 86 | ...common.plugins, 87 | new webpack.DefinePlugin({ 88 | CLIENT_BUNDLE: JSON.stringify( 89 | isProduction 90 | ? require('../build/assets.json').client.js 91 | : '/js/client.js' 92 | ), 93 | VENDOR_BUNDLE: JSON.stringify( 94 | isProduction 95 | ? require('../build/assets.json').vendor.js 96 | : '/js/vendor.js' 97 | ), 98 | 'process.env': { 99 | PORT: JSON.stringify(process.env.PORT) 100 | } 101 | }) 102 | ], 103 | externals: [nodeExternals()], 104 | bail: isProduction 105 | } 106 | -------------------------------------------------------------------------------- /webpack/webpack.client.babel.js: -------------------------------------------------------------------------------- 1 | import AssetsPlugin from 'assets-webpack-plugin' 2 | import WebpackMd5Hash from 'webpack-md5-hash' 3 | import webpack from 'webpack' 4 | import OfflinePlugin from 'offline-plugin' 5 | import common, { 6 | babelLoaderOptions, 7 | cssLoaderOptions, 8 | urlLoaderOptions 9 | } from './common' 10 | 11 | const isProduction = process.env.NODE_ENV === 'production' 12 | 13 | export default { 14 | name: 'client', 15 | entry: { 16 | client: [ 17 | ...(!isProduction && ['webpack-hot-middleware/client']), 18 | './src/client' 19 | ] 20 | }, 21 | output: { 22 | ...common.output, 23 | filename: `js/[name]${isProduction ? '.[chunkhash:8]' : ''}.js` 24 | }, 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.css$/, 29 | use: [ 30 | { 31 | loader: 'style-loader' 32 | }, 33 | { 34 | loader: 'css-loader', 35 | options: cssLoaderOptions 36 | }, 37 | { 38 | loader: 'postcss-loader', 39 | options: { 40 | plugins() { 41 | return [ 42 | require('postcss-import')({ 43 | path: ['src/app/styles'] 44 | }), 45 | require('postcss-cssnext')({ apply: false }), // eslint-disable-line global-require 46 | require('postcss-apply') 47 | ] 48 | } 49 | } 50 | } 51 | ] 52 | }, 53 | { 54 | test: /\.flow$/, 55 | use: 'null-loader' 56 | }, 57 | { 58 | test: /\.js$/, 59 | exclude: /node_modules/, 60 | use: [ 61 | { 62 | loader: 'babel-loader', 63 | options: { 64 | ...babelLoaderOptions, 65 | presets: [ 66 | [ 67 | 'env', 68 | { 69 | targets: { 70 | browsers: '> 1%, Last 2 versions' 71 | }, 72 | modules: false 73 | } 74 | ], 75 | 'react' 76 | ] 77 | } 78 | } 79 | ] 80 | }, 81 | { 82 | include: /\.(png|jpeg|jpg|svg)$/, 83 | use: [ 84 | { 85 | loader: 'url-loader', 86 | options: urlLoaderOptions 87 | } 88 | ] 89 | } 90 | ] 91 | }, 92 | plugins: [ 93 | ...common.plugins, 94 | ...(isProduction 95 | ? [ 96 | new AssetsPlugin({ 97 | filename: 'assets.json', 98 | path: common.output.path 99 | }) 100 | ] 101 | : [new webpack.HotModuleReplacementPlugin()]), 102 | new webpack.optimize.CommonsChunkPlugin({ 103 | name: 'vendor', 104 | minChunks: ({ resource }) => /node_modules/.test(resource) 105 | }), 106 | new WebpackMd5Hash(), 107 | new OfflinePlugin() 108 | ], 109 | bail: isProduction 110 | } 111 | -------------------------------------------------------------------------------- /yarn-error.log: -------------------------------------------------------------------------------- 1 | Arguments: 2 | /usr/local/bin/node /usr/local/Cellar/yarn/1.2.1/libexec/bin/yarn.js 3 | 4 | PATH: 5 | /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/flyingunicornaway/Library/Android/sdk/tools:/Users/flyingunicornaway/Library/Android/sdk/platform-tools 6 | 7 | Yarn version: 8 | 1.2.1 9 | 10 | Node version: 11 | 8.8.1 12 | 13 | Platform: 14 | darwin x64 15 | 16 | npm manifest: 17 | { 18 | "name": "react-starter", 19 | "version": "0.0.0", 20 | "private": true, 21 | "engines": { 22 | "node": ">=4" 23 | }, 24 | "scripts": { 25 | "analyze": "webpack --config webpack/webpack.client.babel.js --profile --json > stats.json", 26 | "build": "npm run build:client && npm run build:server", 27 | "build:client": "webpack --progress --config webpack/webpack.client.babel.js", 28 | "build:server": "webpack --progress --config webpack/webpack.server.babel.js", 29 | "dev": "npm run build:server && node build/server", 30 | "lint": "eslint --ignore-path .gitignore .", 31 | "prebuild": "rimraf build/*", 32 | "start": "node build/server" 33 | }, 34 | "devDependencies": { 35 | "eslint": "^4.10.0", 36 | "eslint-config-standard": "^10.2.1", 37 | "eslint-plugin-import": "^2.8.0", 38 | "eslint-plugin-node": "^5.2.1", 39 | "eslint-plugin-promise": "^3.6.0", 40 | "eslint-plugin-react": "7.4.0", 41 | "eslint-plugin-standard": "^3.0.1", 42 | "svg-inline-loader": "^0.8.0" 43 | }, 44 | "dependencies": { 45 | "assets-webpack-plugin": "3.5.1", 46 | "axios": "^0.17.0", 47 | "babel-cli": "6.26.0", 48 | "babel-loader": "7.1.2", 49 | "babel-plugin-transform-object-rest-spread": "6.26.0", 50 | "babel-plugin-transform-react-remove-prop-types": "0.3.2", 51 | "babel-preset-env": "1.6.1", 52 | "babel-preset-react": "6.24.1", 53 | "compression": "1.7.1", 54 | "css-loader": "0.28.7", 55 | "date-fns": "^1.29.0", 56 | "eslint-plugin-react": "7.4.0", 57 | "express": "^4.16.2", 58 | "express-graphql": "^0.6.11", 59 | "extract-text-webpack-plugin": "3.0.2", 60 | "file-loader": "1.1.5", 61 | "graphql": "^0.11.7", 62 | "graphql-playground": "^1.1.0", 63 | "morgan": "1.9.0", 64 | "postcss-cssnext": "3.0.2", 65 | "postcss-loader": "2.0.8", 66 | "react": "16.0.0", 67 | "react-dom": "16.0.0", 68 | "react-router-dom": "4.2.2", 69 | "rimraf": "2.6.2", 70 | "url-loader": "0.6.2", 71 | "webpack": "3.8.1", 72 | "webpack-dev-middleware": "1.12.0", 73 | "webpack-hot-middleware": "2.20.0", 74 | "webpack-md5-hash": "0.0.5", 75 | "webpack-node-externals": "1.6.0" 76 | } 77 | } 78 | 79 | yarn manifest: 80 | No manifest 81 | 82 | Lockfile: 83 | No lockfile 84 | 85 | Trace: 86 | Error: https://registry.yarnpkg.com/assets-webpack-plugin: ETIMEDOUT 87 | at Timeout._onTimeout (/usr/local/Cellar/yarn/1.2.1/libexec/lib/cli.js:123675:19) 88 | at ontimeout (timers.js:471:11) 89 | at tryOnTimeout (timers.js:306:5) 90 | at Timer.listOnTimeout (timers.js:266:5) 91 | -------------------------------------------------------------------------------- /src/server/data/projects.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | name: 'Isthereuber.in', 4 | description: 5 | 'A website that tells you if there is uber or other drive sharing apps in the city you type in', 6 | github: 'https://github.com/SaraVieira/uber-cities', 7 | website: 'https://isthereuber.in' 8 | }, 9 | { 10 | name: 'Webpack.wtf', 11 | description: 'A simple website for all of us to share our webpack pains', 12 | github: 'https://github.com/SaraVieira/webpack.wtf', 13 | website: 'https://webpack.wtf' 14 | }, 15 | { 16 | name: 'WutTheLint?', 17 | description: 'The proof that we have way too many linters', 18 | github: 'https://github.com/SaraVieira/wutthelint', 19 | website: 'https://wutthelint.now.sh' 20 | }, 21 | { 22 | name: 'postcss-caralho', 23 | description: 24 | 'PostCSS plugin for that changes curse words after ! to !important because why not ?', 25 | github: 'https://github.com/SaraVieira/postcss-caralho' 26 | }, 27 | { 28 | name: 'PreactCasts', 29 | description: 'ScreenCasts to help you get started with preact', 30 | website: 31 | 'https://www.youtube.com/watch?v=lF5TQwbYr9Q&list=PL1O2bxLvC8EPw09PKUl3smGrujiZbQFG9' 32 | }, 33 | { 34 | name: 'Caninameit', 35 | description: 36 | 'A cli tool to help you see a npm name is already taken because this a problem now 😱', 37 | github: 'https://github.com/SaraVieira/caninameit' 38 | }, 39 | { 40 | name: 'styled-loaders', 41 | description: 'Loaders Built with Preact and Styled Components', 42 | github: 'https://github.com/SaraVieira/styled-loaders', 43 | website: 'https://styled-loaders.now.sh/' 44 | }, 45 | { 46 | name: 'vscode-preact-preact-router-snippets', 47 | description: 'Useful Preact Ecosystem snippets for Visual Studio Code', 48 | github: 49 | 'https://github.com/SaraVieira/vscode-preact-preact-router-snippets', 50 | website: 51 | 'https://marketplace.visualstudio.com/items?itemName=saravieira.preact-preact-router-snippets' 52 | }, 53 | { 54 | name: 'randomoji', 55 | description: 'GET A RANDOM EMOJI', 56 | github: 'https://github.com/SaraVieira/randomoji' 57 | }, 58 | { 59 | name: 'preact-cli-plugin-flow', 60 | description: 'Use flow with the Preact CLI', 61 | github: 'https://github.com/SaraVieira/preact-cli-plugin-flow' 62 | }, 63 | { 64 | name: 'Eslint Config Flying Rocket 🚀', 65 | description: 66 | 'An ESLint Shareable Config for the style I use and you may like too 🍕', 67 | github: 'https://github.com/SaraVieira/eslint-config-flying-rocket' 68 | }, 69 | { 70 | name: 'preact-cli-lodash', 71 | description: 'Minify build when using lodash and preact-cli', 72 | github: 'https://github.com/SaraVieira/preact-cli-lodash' 73 | }, 74 | { 75 | name: 'preact-cli-postcss', 76 | description: 77 | 'Removes default postcss config and instead will use postcss.config.js', 78 | github: 'https://github.com/SaraVieira/preact-cli-postcss' 79 | }, 80 | { 81 | name: 'isthereuber-db', 82 | description: 'DB of cities with uber', 83 | github: 'https://github.com/SaraVieira/isthereuber-db', 84 | website: 'https://isthereuber-db.now.sh/cities' 85 | } 86 | ] 87 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GraphQL-portfolio", 3 | "version": "1.0.0", 4 | "engines": { 5 | "node": ">=4" 6 | }, 7 | "scripts": { 8 | "analyze": "webpack --config webpack/webpack.client.babel.js --profile --json > stats.json", 9 | "build": "npm run build:client && npm run build:server", 10 | "now-build": "NODE_ENV=production npm run build:client -- -p && NODE_ENV=production npm run build:server -- -p", 11 | "build:client": "webpack --progress --config webpack/webpack.client.babel.js", 12 | "build:server": "webpack --progress --config webpack/webpack.server.babel.js", 13 | "pretty": "prettier-standard {src,webpack}/**/*.js --single-quote", 14 | "dev": "npm run build:server && node build/server", 15 | "lint": "eslint --ignore-path .gitignore .", 16 | "prebuild": "rimraf build/*", 17 | "start": "node build/server", 18 | "precommit": "lint-staged" 19 | }, 20 | "lint-staged": { 21 | "*.js": [ 22 | "npm run pretty", 23 | "git add" 24 | ] 25 | }, 26 | "devDependencies": { 27 | "eslint": "^4.10.0", 28 | "eslint-config-prettier": "^2.7.0", 29 | "eslint-config-prettier-standard": "^1.0.1", 30 | "eslint-config-standard": "^10.2.1", 31 | "eslint-config-standard-react": "^5.0.0", 32 | "eslint-plugin-import": "^2.8.0", 33 | "eslint-plugin-node": "^5.2.1", 34 | "eslint-plugin-prettier": "^2.3.1", 35 | "eslint-plugin-promise": "^3.6.0", 36 | "eslint-plugin-react": "7.4.0", 37 | "eslint-plugin-standard": "^3.0.1", 38 | "husky": "^0.14.3", 39 | "lint-staged": "^4.3.0", 40 | "nodemon": "^1.12.1", 41 | "null-loader": "^0.1.1", 42 | "offline-plugin": "^4.8.4", 43 | "postcss-apply": "^0.8.0", 44 | "postcss-import": "^11.0.0", 45 | "prettier": "^1.7.4", 46 | "prettier-standard": "^7.0.3", 47 | "raw-loader": "^0.5.1" 48 | }, 49 | "dependencies": { 50 | "assets-webpack-plugin": "3.5.1", 51 | "axios": "^0.17.0", 52 | "babel-cli": "6.26.0", 53 | "babel-loader": "7.1.2", 54 | "babel-plugin-transform-object-rest-spread": "6.26.0", 55 | "babel-plugin-transform-react-remove-prop-types": "0.3.2", 56 | "babel-preset-env": "1.6.1", 57 | "babel-preset-react": "6.24.1", 58 | "compression": "1.7.1", 59 | "css-loader": "0.28.7", 60 | "curse-words-common": "^1.1.0", 61 | "date-fns": "^1.29.0", 62 | "eslint-plugin-react": "7.4.0", 63 | "express": "^4.16.2", 64 | "express-graphql": "^0.6.11", 65 | "file-loader": "1.1.5", 66 | "graphiql": "^0.11.10", 67 | "graphiql-material-theme": "^1.0.3", 68 | "graphql": "^0.11.7", 69 | "graphql-tools": "^2.7.2", 70 | "isomorphic-fetch": "^2.2.1", 71 | "morgan": "1.9.0", 72 | "normalize.css": "^7.0.0", 73 | "postcss-cssnext": "3.0.2", 74 | "postcss-loader": "2.0.8", 75 | "react": "16.0.0", 76 | "react-dom": "16.0.0", 77 | "react-router-dom": "4.2.2", 78 | "rimraf": "2.6.2", 79 | "style-jsx": "^0.0.0", 80 | "style-loader": "^0.19.0", 81 | "unique-random-array": "^1.0.0", 82 | "url-loader": "0.6.2", 83 | "webpack": "3.8.1", 84 | "webpack-dev-middleware": "1.12.0", 85 | "webpack-hot-middleware": "2.20.0", 86 | "webpack-md5-hash": "0.0.5", 87 | "webpack-node-externals": "1.6.0" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/server/data/talks.js: -------------------------------------------------------------------------------- 1 | const isPast = require('date-fns/is_past') 2 | 3 | const talks = [ 4 | { 5 | name: 'CSS Hates You', 6 | event: 'Mtalks', 7 | date: new Date(2017, 5, 14), 8 | done: !!isPast(new Date(2017, 5, 14)), 9 | video: 'https://youtu.be/gwW36kV9TV4?t=10s', 10 | slides: 11 | 'https://github.com/SaraVieira/talks/blob/master/CSS%20Hates%20You.pptx', 12 | location: 'Porto, Portugal' 13 | }, 14 | { 15 | name: "There's a whole new world offline", 16 | event: 'Require("lx")', 17 | date: new Date(2017, 6, 6), 18 | done: !!isPast(new Date(2017, 6, 6)), 19 | video: 'https://www.youtube.com/watch?v=ZvA41uuyujA', 20 | slides: 21 | 'https://docs.google.com/presentation/d/1vQ9xAijI8NjbQkFESu0LwVYEcpCxqQhcjC7ESzddMTE/edit#slide=id.p', 22 | location: 'Lisbon, Portugal' 23 | }, 24 | { 25 | name: 'CSS Hates You', 26 | event: 'Formidable & Friends Birthday Bash!', 27 | date: new Date(2017, 10, 9), 28 | done: !!isPast(new Date(2017, 10, 9)), 29 | slides: 30 | 'https://drive.google.com/open?id=1lwjwVFpC_hnxZE7aUiuetgzHoEG87cxrzQ4oItdCAo4', 31 | location: 'London, UK' 32 | }, 33 | { 34 | name: 'We need to talk about Preact', 35 | event: 'JS Roundabout', 36 | date: new Date(2017, 10, 8), 37 | done: !!isPast(new Date(2017, 10, 8)), 38 | slides: 39 | 'https://drive.google.com/open?id=1BJRGOBNySWpN7NRkr1kQVI1ul7EG9SCo5t4NSnFJrSM', 40 | video: 'https://www.youtube.com/watch?v=Bb3Vyj0KTd4', 41 | location: 'London, UK' 42 | }, 43 | { 44 | name: 'We need to talk about Preact', 45 | event: 'React Day Berlin', 46 | date: new Date(2017, 11, 2), 47 | done: !!isPast(new Date(2017, 11, 2)), 48 | video: 'https://www.youtube.com/watch?v=jqXRSvXWYf8', 49 | slides: 50 | 'https://drive.google.com/open?id=1BJRGOBNySWpN7NRkr1kQVI1ul7EG9SCo5t4NSnFJrSM', 51 | location: 'Berlin, Germany' 52 | }, 53 | { 54 | name: 'We need to talk about Preact', 55 | event: 'EnterJS', 56 | date: new Date(2018, 20, 5), 57 | done: !!isPast(new Date(2018, 20, 5)), 58 | location: 'Darmstadt, Germany' 59 | }, 60 | { 61 | name: 'We need to talk about Preact', 62 | event: 'React Vienna', 63 | date: new Date(2017, 0, 18), 64 | done: !!isPast(new Date(2017, 0, 18)), 65 | video: 'https://www.youtube.com/watch?v=bYdeMvr5Aus', 66 | slides: 67 | 'https://drive.google.com/open?id=1BJRGOBNySWpN7NRkr1kQVI1ul7EG9SCo5t4NSnFJrSM', 68 | location: 'Vienna, Autria' 69 | }, 70 | { 71 | name: "Your brain doesn't have a --fix flag", 72 | event: 'Agent Conf', 73 | date: new Date(2018, 0, 25), 74 | done: !!isPast(new Date(2018, 0, 25)), 75 | location: 'Dornbirn, Austria', 76 | slides: 'https://brain-fix.now.sh' 77 | }, 78 | { 79 | name: "Your brain doesn't have a --fix flag", 80 | event: 'Front End NE', 81 | date: new Date(2018, 3, 5), 82 | done: !!isPast(new Date(2018, 3, 5)), 83 | location: 'Newcastle, UK', 84 | slides: 'https://brain-fix.now.sh' 85 | }, 86 | { 87 | name: 'Testing React Applications', 88 | event: 'React Finland', 89 | date: new Date(2018, 3, 25), 90 | done: !!isPast(new Date(2018, 3, 25)), 91 | location: 'Helsinki, Finland' 92 | }, 93 | { 94 | event: 'React Fest', 95 | name: 'The lonely and dark road to Styling in React', 96 | date: new Date(2018, 2, 9), 97 | done: !!isPast(new Date(2018, 2, 9)), 98 | location: 'London, UK' 99 | }, 100 | 101 | { 102 | event: 'JSHeroes', 103 | date: new Date(2018, 3, 18), 104 | done: !!isPast(new Date(2018, 3, 18)), 105 | location: 'Cluj-Napoca, Romania' 106 | }, 107 | { 108 | event: 'Graphql Europe', 109 | date: new Date(2018, 5, 15), 110 | done: !!isPast(new Date(2018, 5, 15)), 111 | location: 'Berlin, Germany' 112 | }, 113 | { 114 | event: 'Front End United', 115 | date: new Date(2018, 4, 31), 116 | done: !!isPast(new Date(2018, 4, 31)), 117 | location: 'Utrecht, Netherlands' 118 | }, 119 | { 120 | name: 'Styleguide Driven Development', 121 | event: 'React Girls London', 122 | date: new Date(2017, 8, 26), 123 | done: !!isPast(new Date(2017, 8, 26)), 124 | slides: 'https://github.com/SaraVieira/styleguide-driven-development', 125 | location: 'London, UK' 126 | }, 127 | { 128 | name: 'Styleguide Driven Development', 129 | event: 'React Alicante', 130 | date: new Date(2017, 9, 30), 131 | done: !!isPast(new Date(2017, 9, 30)), 132 | slides: 'https://github.com/SaraVieira/styleguide-driven-development', 133 | video: 'https://www.youtube.com/watch?v=JjXnmhNW8Cs', 134 | location: 'Alicante, Spain' 135 | }, 136 | { 137 | name: "The Hitchhiker's Guide to the Webpack", 138 | event: 'Codemotion Amsterdam', 139 | date: new Date(2016, 4, 16), 140 | done: !!isPast(new Date(2016, 4, 16)), 141 | video: 'https://www.youtube.com/watch?v=Zor8E6_ZoVA', 142 | slides: 143 | 'https://github.com/SaraVieira/talks/blob/master/Codemotion%20Amsterdam.pptx', 144 | location: 'Amsterdam, Netherlands' 145 | }, 146 | { 147 | name: 'CSS3 Layouts: Flexbox vs CSS Grid', 148 | event: 'Codemotion Milan', 149 | date: new Date(2015, 10, 20), 150 | done: !!isPast(new Date(2015, 10, 20)), 151 | video: 'https://www.youtube.com/watch?v=b-in0QpvDiQ', 152 | slides: 153 | 'https://github.com/SaraVieira/talks/blob/master/Codemotion%20Amsterdam.pptx', 154 | location: 'Milan, Italy' 155 | }, 156 | { 157 | name: 'CSS as a programming language', 158 | event: 'Front Trends', 159 | date: new Date(2014, 4, 20), 160 | done: !!isPast(new Date(2014, 4, 20)), 161 | video: 'https://vimeo.com/105956446', 162 | slides: 163 | 'https://github.com/SaraVieira/talks/tree/master/css-as-programming-language', 164 | location: 'Warsaw, Poland' 165 | }, 166 | { 167 | name: 'Front-end Tools and Workflows', 168 | event: 'QCon London 2015', 169 | date: new Date(2015, 5, 20), 170 | done: !!isPast(new Date(2015, 5, 20)), 171 | video: 'https://www.infoq.com/presentations/front-end-tools-workflows', 172 | location: 'London, UK' 173 | } 174 | ] 175 | 176 | module.exports = talks.sort((a, b) => (a.date > b.date ? -1 : 1)) 177 | -------------------------------------------------------------------------------- /src/app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | noun_614040_cc 3 | Created using Figma 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | --------------------------------------------------------------------------------