Very basic NextJS and Api
commit
652143db1d
@ -0,0 +1,2 @@
|
||||
.next/
|
||||
node_modules/
|
@ -0,0 +1,8 @@
|
||||
const router = require('express-promise-router')()
|
||||
|
||||
router.get('/', (req, res)=>{
|
||||
console.log('api request')
|
||||
res.json({test: true})
|
||||
})
|
||||
|
||||
module.exports = router;
|
@ -0,0 +1,31 @@
|
||||
import Link from "next/link"
|
||||
import {DateTime} from 'luxon'
|
||||
import React from "react"
|
||||
|
||||
import styles from './style.module.css'
|
||||
|
||||
const Footer = () => (
|
||||
<footer className={styles.container}>
|
||||
<div>
|
||||
<h1 className={styles.title}>
|
||||
<Link href="/"><a>Society <span>of</span> Socks</a></Link>
|
||||
</h1>
|
||||
<div className={styles.footerInfo}>
|
||||
<p>Website by <a href="https://coleserickson.com/">Cole Erickson</a> - © 2015 - {DateTime.utc().year} Society of Socks</p>
|
||||
</div>
|
||||
<ul className={styles.footerNav}>
|
||||
<li><Link href="#mailingList"><a onClick={(ev)=>{if(ev) ev.preventDefault(); console.log('mailing list')}}>Mailing List</a></Link></li>
|
||||
<li><Link href="/contact"><a>Contact Us</a></Link></li>
|
||||
<li><Link href="/privacy"><a>Privacy</a></Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
|
||||
Footer.propTypes = {
|
||||
}
|
||||
|
||||
Footer.defaultProps = {
|
||||
}
|
||||
|
||||
export default Footer
|
@ -0,0 +1,94 @@
|
||||
.container {
|
||||
background: #313131;
|
||||
box-shadow: inset 0 15px 7.5px -7.5px rgba(0,0,0,0.2);
|
||||
padding-top: 15px;
|
||||
color: white;
|
||||
padding-left: 25px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.container > div {
|
||||
max-width: 1000px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h1.title {
|
||||
display: block;
|
||||
width: 100%;
|
||||
top: -20px;
|
||||
font-size: 24px;
|
||||
border-bottom: solid rgba(255,255,255,0.2) 1px;
|
||||
}
|
||||
|
||||
h1.title a {
|
||||
font-family: 'Cormorant Infant',serif;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none !important;
|
||||
text-align: center;
|
||||
color: inherit;
|
||||
height: 1.02em;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
h1.title span {
|
||||
font-family: 'Cormorant Upright',serif;
|
||||
font-weight: 300;
|
||||
text-transform: lowercase;
|
||||
font-style: italic;
|
||||
margin-left: -0.2em;
|
||||
margin-right: .2em;
|
||||
position: relative;
|
||||
top: -0.2em;
|
||||
left: .05em;
|
||||
font-size: 73.91304348%;
|
||||
}
|
||||
|
||||
h1.title a {
|
||||
border-bottom: solid 1px transparent;
|
||||
position: relative;
|
||||
padding-bottom: 2px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
h1.title a:hover {
|
||||
border-bottom: solid 1px currentColor;
|
||||
}
|
||||
|
||||
.footerInfo {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.footerInfo a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.footerNav {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
top: -8px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.footerNav li {
|
||||
display: inline-block;
|
||||
font-family: 'Cormorant SC', serif;
|
||||
padding-left: 40px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.footerNav li a {
|
||||
display: inline-block;
|
||||
font-family: 'Cormorant SC', serif;
|
||||
color: white;
|
||||
opacity: .7;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footerNav li a:hover {
|
||||
opacity: .9;
|
||||
border-bottom: solid 1px white;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
import Link from "next/link"
|
||||
import PropTypes from "prop-types"
|
||||
import React from "react"
|
||||
|
||||
// import logo from './sos-logo.png'
|
||||
import styles from './style.module.css'
|
||||
|
||||
const Header = ({user}) => (
|
||||
<header className={styles.container}>
|
||||
<div className={styles.logo}>
|
||||
{/* <img alt="" src={logo}/> */}
|
||||
</div>
|
||||
<h1 className={styles.title}>
|
||||
<Link href="/"><a>Society <span>of</span> Socks</a></Link>
|
||||
</h1>
|
||||
<ul className={styles.primaryNav}>
|
||||
<li><Link href="/store/categories"><a>Catalogue</a></Link></li>
|
||||
<li><Link href="/store/popular"><a>Popular</a></Link></li>
|
||||
<li><Link href="/store/new"><a>New</a></Link></li>
|
||||
</ul>
|
||||
<ul className={styles.accountNav}>
|
||||
<li><Link href="/store/cart"><a><span className="fa fa-shopping-cart"></span> Cart</a></Link></li>
|
||||
{
|
||||
(!user)?(
|
||||
<li><Link href="/login"><a>Log in</a></Link></li>
|
||||
):(
|
||||
<>
|
||||
<li><Link href="/account"><a>Account</a></Link></li>
|
||||
<li><Link href="/logout"><a>Log out</a></Link></li>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
</header>
|
||||
)
|
||||
|
||||
Header.propTypes = {
|
||||
user: PropTypes.object,
|
||||
}
|
||||
|
||||
Header.defaultProps = {
|
||||
user: null,
|
||||
}
|
||||
|
||||
export default Header
|
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
@ -0,0 +1,139 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Cormorant+Infant:400,600|Cormorant+SC|Cormorant+Upright:300');
|
||||
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css');
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
position: relative;
|
||||
box-sizing: content-box;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.container::after {
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
height: 15px;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #9C27B0;
|
||||
box-shadow: inset 0 5px 2.5px -2.5px rgba(0,0,0,0.2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.container + div {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 100px;
|
||||
position: relative;
|
||||
overflow-y: hidden;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
position: absolute;
|
||||
top: -70px;
|
||||
height: 180%;
|
||||
padding: 20px;
|
||||
opacity: .47;
|
||||
}
|
||||
|
||||
h1.title {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
font-size: 46px;
|
||||
}
|
||||
|
||||
h1.title a {
|
||||
font-family: 'Cormorant Infant',serif;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none !important;
|
||||
text-align: center;
|
||||
color: inherit;
|
||||
height: 1.02em;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
h1.title span {
|
||||
font-family: 'Cormorant Upright',serif;
|
||||
font-weight: 300;
|
||||
text-transform: lowercase;
|
||||
font-style: italic;
|
||||
margin-left: -0.2em;
|
||||
margin-right: .2em;
|
||||
position: relative;
|
||||
top: -0.2em;
|
||||
left: .05em;
|
||||
font-size: 73.91304348%;
|
||||
}
|
||||
|
||||
h1.title a:hover {
|
||||
border-bottom: solid 1px black;
|
||||
}
|
||||
|
||||
.primaryNav {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
color: black;
|
||||
opacity: .87;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.primaryNav li {
|
||||
font-family: 'Cormorant SC',serif;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.primaryNav li a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.primaryNav li:not(:first-child){
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.accountNav {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.accountNav li {
|
||||
font-family: 'Cormorant Infant',serif;
|
||||
font-weight: 400;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
color: black;
|
||||
opacity: .87;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.accountNav li a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.accountNav li:not(:first-child){
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.container ul li a:hover {
|
||||
border-bottom: solid 1px black;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 297 KiB |
@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
|
||||
import logo from './societyofsocks-white.png'
|
||||
import background from './hero-background-wood.jpg'
|
||||
import styles from './style.module.css'
|
||||
|
||||
export default function Hero(){
|
||||
return (
|
||||
<div className={styles.hero}>
|
||||
<div style={{backgroundImage: `url(${background})`}}>
|
||||
<img class={styles.icon} src={logo}/>
|
||||
<div class={styles.content}>
|
||||
<h2>Your Socks. Your Style.</h2>
|
||||
<p>Are you tired of plain (boring) white socks? We've got you covered.</p>
|
||||
<p>At Society of Socks we strive to give every design a unique personality that is sure to stand out from the crowd.</p>
|
||||
<p>So find your style, and wear them with pride. They're your socks, shouldn't they fit you?</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
@ -0,0 +1,51 @@
|
||||
.hero {
|
||||
background: linear-gradient(#0f0f0f, #080808);
|
||||
position: relative;
|
||||
box-shadow: inset 0 -15px 7.5px -7.5px rgba(0,0,0,0.2);
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
.hero > div {
|
||||
margin: 0;
|
||||
margin-right: 0px;
|
||||
margin-left: 0px;
|
||||
max-width: 2000px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
top: 0;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
min-height: 400px;
|
||||
box-shadow: inset 0 -15px 7.5px -7.5px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.hero img.icon {
|
||||
position: absolute;
|
||||
right: 60%;
|
||||
margin-right: 20px;
|
||||
margin-top: -10px;
|
||||
top: 80px;
|
||||
max-width: 300px;
|
||||
|
||||
}
|
||||
|
||||
.hero div.content {
|
||||
position: absolute;
|
||||
left: 40%;
|
||||
right: 20%;
|
||||
padding-left: 20px;
|
||||
top: 80px;
|
||||
color: white;
|
||||
font-family: 'Cormorant Infant',serif;
|
||||
}
|
||||
|
||||
.hero h2 {
|
||||
font-family: 'Cormorant SC',serif;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
opacity: .7;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* SEO component that queries for data with
|
||||
* Gatsby's useStaticQuery React hook
|
||||
*
|
||||
* See: https://www.gatsbyjs.org/docs/use-static-query/
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
import Helmet from "react-helmet"
|
||||
import { useStaticQuery, graphql } from "gatsby"
|
||||
|
||||
function SEO({ description, lang, meta, title }) {
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
const metaDescription = description || site.siteMetadata.description
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:creator`,
|
||||
content: site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
].concat(meta)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
SEO.defaultProps = {
|
||||
lang: `en`,
|
||||
meta: [],
|
||||
description: ``,
|
||||
}
|
||||
|
||||
SEO.propTypes = {
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default SEO
|
@ -0,0 +1,32 @@
|
||||
const express = require('express')
|
||||
const nextjs = require('next')
|
||||
const {promisify} = require('util')
|
||||
|
||||
const dev = process.env.NODE_ENV !== 'production'
|
||||
const next = nextjs({dev})
|
||||
const nextRequestHandler = next.getRequestHandler()
|
||||
|
||||
;(async ()=>{
|
||||
|
||||
// Allow Next.js to compile its templates
|
||||
console.log('Preparing Next.js templates . . .')
|
||||
await next.prepare()
|
||||
|
||||
const app = express()
|
||||
|
||||
app.use('/api', require('./api'))
|
||||
app.use(nextRequestHandler)
|
||||
|
||||
// await promisify(app.listen)(3000)
|
||||
|
||||
app.listen(3000, err=>{
|
||||
if(err) throw err
|
||||
|
||||
console.log('App listening on port 3000')
|
||||
})
|
||||
|
||||
|
||||
})().catch((ex) => {
|
||||
console.error(ex.stack)
|
||||
process.exit(1)
|
||||
})
|
@ -0,0 +1,8 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
webpack(config, options) {
|
||||
config.resolve.alias["components"] = path.join(__dirname, 'components');
|
||||
return config;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "sos-nextjs",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "next start",
|
||||
"dev": "next dev",
|
||||
"build": "next build"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {},
|
||||
"dependencies": {
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^3.0.3",
|
||||
"luxon": "^1.22.0",
|
||||
"next": "^9.2.1",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
import React from "react"
|
||||
import PropTypes from "prop-types"
|
||||
|
||||
import Header from 'components/header'
|
||||
import Footer from 'components/footer'
|
||||
import "./layout.css"
|
||||
// import useUserSession from "../hooks/useUserSession";
|
||||
|
||||
const Layout = ({ Component, pageProps }) => {
|
||||
// Retrieve user information
|
||||
// const user = useUserSession()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main><Component {...pageProps} /></main>
|
||||
<Footer/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Layout.propTypes = {
|
||||
Component: PropTypes.node.isRequired,
|
||||
pageProps: PropTypes.object
|
||||
}
|
||||
|
||||
export default Layout
|
@ -0,0 +1,8 @@
|
||||
import React from 'react'
|
||||
|
||||
const Index = () => (
|
||||
<div>
|
||||
<p>Hello Next.js, this is your friend Brian from logrocket</p>
|
||||
</div>
|
||||
)
|
||||
export default Index
|
@ -0,0 +1,22 @@
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
html,body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #313131;
|
||||
}
|
||||
|
||||
main {
|
||||
background: #E4E4E4;
|
||||
color: black;
|
||||
padding: 30px 0;
|
||||
}
|
Loading…
Reference in New Issue