Initial commit

This commit is contained in:
Daniele Salatti 2022-05-03 23:26:15 -07:00
commit 5beca54202
52 changed files with 11125 additions and 0 deletions

12
.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
[
"next/babel",
{
"styled-jsx": {
"plugins": ["styled-jsx-plugin-postcss"]
}
}
]
]
}

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
out

72
.eslintrc Normal file
View File

@ -0,0 +1,72 @@
{
// Configuration for JavaScript files
"extends": [
"airbnb-base",
"next/core-web-vitals",
"plugin:prettier/recommended"
],
"rules": {
"prettier/prettier": [
"error",
{
"singleQuote": true
}
]
},
"overrides": [
// Configuration for TypeScript files
{
"files": ["**/*.ts", "**/*.tsx"],
"plugins": ["@typescript-eslint", "unused-imports"],
"extends": [
"airbnb-typescript",
"next/core-web-vitals",
"plugin:prettier/recommended"
],
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"prettier/prettier": [
"error",
{
"singleQuote": true
}
],
"react/destructuring-assignment": "off", // Vscode doesn't support automatically destructuring, it's a pain to add a new variable
"jsx-a11y/anchor-is-valid": "off", // Next.js use his own internal link system
"react/require-default-props": "off", // Allow non-defined react props as undefined
"react/jsx-props-no-spreading": "off", // _app.tsx uses spread operator and also, react-hook-form
"@next/next/no-img-element": "off", // We currently not using next/image because it isn't supported with SSG mode
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"pathGroups": [
{
"pattern": "react",
"group": "external",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": ["react"],
"newlines-between": "always",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
],
"@typescript-eslint/comma-dangle": "off", // Avoid conflict rule between Eslint and Prettier
"import/prefer-default-export": "off", // Named export is easier to refactor automatically
"class-methods-use-this": "off", // _document.tsx use render method without `this` keyword
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"error",
{ "argsIgnorePattern": "^_" }
]
}
}
]
}

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
custom: ['https://creativedesignsguru.com/category/nextjs/', 'https://www.buymeacoffee.com/ixartz']

35
.gitignore vendored Normal file
View File

@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next
/out
# production
/build
# misc
.DS_Store
*.pem
Thumbs.db
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# dotenv local files
.env*.local
# local folder
local
# vercel
.vercel

5
.husky/pre-commit Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Disable concurent to run build-types after ESLint in lint-staged
npx lint-staged --concurrent false

11
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"mikestead.dotenv",
"csstools.postcss",
"blanu.vscode-styled-jsx",
"msjsdiag.debugger-for-chrome",
"bradlc.vscode-tailwindcss"
]
}

31
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,31 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Next: Chrome",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "Next: Node",
"program": "${workspaceFolder}/node_modules/.bin/next",
"args": ["dev"],
"autoAttachChildProcesses": true,
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
}
],
"compounds": [
{
"name": "Next: Full",
"configurations": ["Next: Node", "Next: Chrome"]
}
]
}

22
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"editor.tabSize": 2,
"editor.detectIndentation": false,
"jest.autoRun": {
"watch": false,
"onSave": "test-file"
},
"search.exclude": {
"package-lock.json": true
},
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.formatOnSave": false,
"editor.codeActionsOnSave": [
"source.addMissingImports",
"source.fixAll.eslint"
],
// Multiple language settings for json and jsonc files
"[json][jsonc]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

21
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,21 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Project wide type checking with TypeScript",
"type": "npm",
"script": "build-types",
"problemMatcher": ["$tsc"],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"clear": true,
"reveal": "never"
}
}
]
}

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
MIT License
Copyright (c) 2022 Daniele Salatti
Template:
Copyright (c) 2020 Rem W.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

0
README.md Normal file
View File

5
lint-staged.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'eslint'],
'**/*.ts?(x)': () => 'npm run build-types',
'*.json': ['prettier --write'],
};

6
netlify.toml Normal file
View File

@ -0,0 +1,6 @@
[build]
publish = "out"
command = "npm run build-prod"
[build.environment]
NETLIFY_NEXT_PLUGIN_SKIP = "true"

5
next-env.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

14
next.config.js Normal file
View File

@ -0,0 +1,14 @@
/* eslint-disable import/no-extraneous-dependencies */
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
poweredByHeader: false,
trailingSlash: true,
basePath: '',
// The starter code load resources from `public` folder with `router.basePath` in React components.
// So, the source code is "basePath-ready".
// You can remove `basePath` if you don't need it.
reactStrictMode: true,
});

10020
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

59
package.json Normal file
View File

@ -0,0 +1,59 @@
{
"name": "convictionvotingwtf",
"version": "1.0.0",
"author": {
"email": "me@danielesalatti.com",
"name": "Daniele Salatti",
"url": "https://danielesalatti.com"
},
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"build-stats": "cross-env ANALYZE=true npm run build",
"export": "next export",
"build-prod": "run-s clean build export",
"clean": "rimraf .next out",
"lint": "next lint",
"build-types": "tsc --noEmit --pretty",
"prepare": "husky install"
},
"dependencies": {
"classnames": "^2.3.1",
"next": "^12.0.9",
"next-seo": "^4.29.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"styled-jsx-plugin-postcss": "^4.0.1"
},
"devDependencies": {
"@next/bundle-analyzer": "^12.0.9",
"@types/node": "^17.0.13",
"@types/react": "^17.0.38",
"@typescript-eslint/eslint-plugin": "^5.10.1",
"@typescript-eslint/parser": "^5.10.1",
"autoprefixer": "^10.4.2",
"cross-env": "^7.0.3",
"cssnano": "^5.0.16",
"eslint": "^8.7.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-next": "^12.0.9",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-unused-imports": "^2.0.0",
"husky": "^7.0.4",
"lint-staged": "^12.3.2",
"npm-run-all": "^4.1.5",
"postcss": "^8.4.5",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"tailwindcss": "^3.0.17",
"typescript": "^4.5.5"
},
"license": "MIT"
}

10
postcss.config.js Normal file
View File

@ -0,0 +1,10 @@
// Please do not use the array form (like ['tailwindcss', 'postcss-preset-env'])
// it will create an unexpected error: Invalid PostCSS Plugin found: [0]
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}),
},
};

BIN
public/apple-touch-icon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

BIN
public/favicon-16x16.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

BIN
public/favicon-32x32.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 B

BIN
public/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,12 @@
import { ReactNode } from 'react';
type IBackgroundProps = {
children: ReactNode;
color: string;
};
const Background = (props: IBackgroundProps) => (
<div className={props.color}>{props.children}</div>
);
export { Background };

47
src/button/Button.tsx Normal file
View File

@ -0,0 +1,47 @@
import className from 'classnames';
type IButtonProps = {
xl?: boolean;
children: string;
};
const Button = (props: IButtonProps) => {
const btnClass = className({
btn: true,
'btn-xl': props.xl,
'btn-base': !props.xl,
'btn-primary': true,
});
return (
<div className={btnClass}>
{props.children}
<style jsx>
{`
.btn {
@apply inline-block rounded-md text-center;
}
.btn-base {
@apply text-lg font-semibold py-2 px-4;
}
.btn-xl {
@apply font-extrabold text-xl py-4 px-6;
}
.btn-primary {
@apply text-white bg-primary-500;
}
.btn-primary:hover {
@apply bg-primary-600;
}
`}
</style>
</div>
);
};
export { Button };

24
src/cta/CTABanner.tsx Normal file
View File

@ -0,0 +1,24 @@
import { ReactNode } from 'react';
type ICTABannerProps = {
title: ReactNode;
subtitle: string;
button: ReactNode;
text: ReactNode;
};
const CTABanner = (props: ICTABannerProps) => (
<div className="text-center flex flex-col p-4 sm:text-left sm:flex-row sm:items-center sm:justify-between sm:p-12 bg-primary-100 rounded-md">
<div className="text-2xl font-semibold">
<div className="text-gray-900">{props.title}</div>
<div className="text-primary-500">{props.subtitle}</div>
<div className="text-gray-900 text-lg font-normal">{props.text}</div>
</div>
<div className="whitespace-no-wrap mt-3 sm:mt-0 sm:ml-2 w-32">
{props.button}
</div>
</div>
);
export { CTABanner };

View File

@ -0,0 +1,39 @@
import className from 'classnames';
import { useRouter } from 'next/router';
type IVerticalFeatureRowProps = {
title: string;
description: string;
image: string;
imageAlt: string;
reverse?: boolean;
};
const VerticalFeatureRow = (props: IVerticalFeatureRowProps) => {
const verticalFeatureClass = className(
'mt-20',
'flex',
'flex-wrap',
'items-center',
{
'flex-row-reverse': props.reverse,
}
);
const router = useRouter();
return (
<div className={verticalFeatureClass}>
<div className="w-full sm:w-1/2 text-center sm:px-6">
<h3 className="text-3xl text-gray-900 font-semibold">{props.title}</h3>
<div className="mt-6 text-xl leading-9">{props.description}</div>
</div>
<div className="w-full sm:w-1/2 p-6">
<img src={`${router.basePath}${props.image}`} alt={props.imageAlt} />
</div>
</div>
);
};
export { VerticalFeatureRow };

View File

@ -0,0 +1,40 @@
import { ReactNode } from 'react';
import { FooterCopyright } from './FooterCopyright';
import { FooterIconList } from './FooterIconList';
type ICenteredFooterProps = {
logo: ReactNode;
iconList: ReactNode;
children: ReactNode;
};
const CenteredFooter = (props: ICenteredFooterProps) => (
<div className="text-center">
{props.logo}
<nav>
<ul className="navbar mt-5 flex flex-row justify-center font-medium text-xl text-gray-800">
{props.children}
</ul>
</nav>
<div className="mt-8 flex justify-center">
<FooterIconList>{props.iconList}</FooterIconList>
</div>
<div className="mt-8 text-sm">
<FooterCopyright />
</div>
<style jsx>
{`
.navbar :global(li) {
@apply mx-4;
}
`}
</style>
</div>
);
export { CenteredFooter };

View File

@ -0,0 +1,20 @@
import { AppConfig } from '../utils/AppConfig';
const FooterCopyright = () => (
<div className="footer-copyright">
© Copyright {new Date().getFullYear()} <a href="https://danielesalatti.com">Daniele Salatti</a> - All rights reserved.
<style jsx>
{`
.footer-copyright :global(a) {
@apply text-primary-500;
}
.footer-copyright :global(a:hover) {
@apply underline;
}
`}
</style>
</div>
);
export { FooterCopyright };

View File

@ -0,0 +1,33 @@
import { ReactNode } from 'react';
type IFooterIconListProps = {
children: ReactNode;
};
const FooterIconList = (props: IFooterIconListProps) => (
<div className="footer-icon-list flex flex-wrap">
{props.children}
<style jsx>
{`
.footer-icon-list :global(a:not(:last-child)) {
@apply mr-3;
}
.footer-icon-list :global(a) {
@apply text-gray-500;
}
.footer-icon-list :global(a:hover) {
@apply text-gray-700;
}
.footer-icon-list :global(svg) {
@apply fill-current w-5 h-5;
}
`}
</style>
</div>
);
export { FooterIconList };

View File

@ -0,0 +1,20 @@
import { ReactNode } from 'react';
type IHeroOneButtonProps = {
title: ReactNode;
description: ReactNode;
button: ReactNode;
};
const HeroOneButton = (props: IHeroOneButtonProps) => (
<header className="text-center">
<h1 className="text-5xl text-gray-900 font-bold whitespace-pre-line leading-hero">
{props.title}
</h1>
<div className="text-2xl mt-4 mb-16">{props.description}</div>
{props.button}
</header>
);
export { HeroOneButton };

66
src/layout/Meta.tsx Normal file
View File

@ -0,0 +1,66 @@
import { NextSeo } from 'next-seo';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { AppConfig } from '../utils/AppConfig';
type IMetaProps = {
title: string;
description: string;
canonical?: string;
};
const Meta = (props: IMetaProps) => {
const router = useRouter();
return (
<>
<Head>
<meta charSet="UTF-8" key="charset" />
<meta
name="viewport"
content="width=device-width,initial-scale=1"
key="viewport"
/>
<link
rel="apple-touch-icon"
href={`${router.basePath}/apple-touch-icon.png`}
key="apple"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href={`${router.basePath}/favicon-32x32.png`}
key="icon32"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href={`${router.basePath}/favicon-16x16.png`}
key="icon16"
/>
<link
rel="icon"
href={`${router.basePath}/favicon.ico`}
key="favicon"
/>
</Head>
<NextSeo
title={props.title}
description={props.description}
canonical={props.canonical}
openGraph={{
title: props.title,
description: props.description,
url: props.canonical,
locale: AppConfig.locale,
site_name: AppConfig.site_name,
}}
/>
</>
);
};
export { Meta };

31
src/layout/Section.tsx Normal file
View File

@ -0,0 +1,31 @@
import { ReactNode } from 'react';
type ISectionProps = {
title?: string;
description?: string;
yPadding?: string;
children: ReactNode;
};
const Section = (props: ISectionProps) => (
<div
className={`max-w-screen-lg mx-auto px-3 ${
props.yPadding ? props.yPadding : 'py-16'
}`}
>
{(props.title || props.description) && (
<div className="mb-12 text-center">
{props.title && (
<h2 className="text-4xl text-gray-900 font-bold">{props.title}</h2>
)}
{props.description && (
<div className="mt-4 text-xl md:px-20">{props.description}</div>
)}
</div>
)}
{props.children}
</div>
);
export { Section };

View File

@ -0,0 +1,38 @@
import { ReactNode } from 'react';
import Link from 'next/link';
type INavbarProps = {
logo: ReactNode;
children: ReactNode;
};
const NavbarTwoColumns = (props: INavbarProps) => (
<div className="flex flex-wrap justify-between items-center">
<div>
<Link href="/">
<a>{props.logo}</a>
</Link>
</div>
<nav>
<ul className="navbar flex items-center font-medium text-xl text-gray-800">
{props.children}
</ul>
</nav>
<style jsx>
{`
.navbar :global(li:not(:first-child)) {
@apply mt-0;
}
.navbar :global(li:not(:last-child)) {
@apply mr-5;
}
`}
</style>
</div>
);
export { NavbarTwoColumns };

9
src/pages/_app.tsx Normal file
View File

@ -0,0 +1,9 @@
import { AppProps } from 'next/app';
import '../styles/global.css';
const MyApp = ({ Component, pageProps }: AppProps) => (
<Component {...pageProps} />
);
export default MyApp;

20
src/pages/_document.tsx Normal file
View File

@ -0,0 +1,20 @@
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { AppConfig } from '../utils/AppConfig';
// Need to create a custom _document because i18n support is not compatible with `next export`.
class MyDocument extends Document {
render() {
return (
<Html lang={AppConfig.locale}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;

5
src/pages/index.tsx Normal file
View File

@ -0,0 +1,5 @@
import { Base } from '../templates/Base';
const Index = () => <Base />;
export default Index;

5
src/styles/global.css Normal file
View File

@ -0,0 +1,5 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

33
src/templates/Banner.tsx Normal file
View File

@ -0,0 +1,33 @@
import Link from 'next/link';
import { Button } from '../button/Button';
import { CTABanner } from '../cta/CTABanner';
import { Section } from '../layout/Section';
const Banner = () => (
<Section>
<CTABanner
title={<>{"🖖 Hi, I'm "}
<Link href='/'>
<a href='https://danielesalatti.com' target='_blank'>
Daniele Salatti
</a>
</Link>
</>}
subtitle="And I am part of the 🏰 BuidlGuidl"
text={<>
<p>{"A curated group of Ethereum builders creating products, prototypes, and tutorials to enrich the web3 ecosytem."}</p>
<p className="mt-4">{"❤️ We are an Ethereum public good."}</p>
</>}
button={
<Link href="/">
<a href="https://buidlguidl.com" target="_blank">
<Button>Join us</Button>
</a>
</Link>
}
/>
</Section>
);
export { Banner };

18
src/templates/Base.tsx Normal file
View File

@ -0,0 +1,18 @@
import { Meta } from '../layout/Meta';
import { AppConfig } from '../utils/AppConfig';
import { Banner } from './Banner';
import { Footer } from './Footer';
import { Hero } from './Hero';
import { VerticalFeatures } from './VerticalFeatures';
const Base = () => (
<div className="antialiased text-gray-600">
<Meta title={AppConfig.title} description={AppConfig.description} />
<Hero />
<VerticalFeatures />
<Banner />
<Footer />
</div>
);
export { Base };

80
src/templates/Footer.tsx Normal file
View File

@ -0,0 +1,80 @@
import Link from 'next/link';
import { Background } from '../background/Background';
import { CenteredFooter } from '../footer/CenteredFooter';
import { Section } from '../layout/Section';
import { Logo } from './Logo';
const Footer = () => (
<Background color="bg-gray-100">
<Section>
<CenteredFooter
logo={<Logo />}
iconList={
<>
<Link href="/">
<a href='https://github.com/DanieleSalatti' target='_blank'>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
</a>
</Link>
<Link href="/">
<a href='https://twitter.com/DanieleSalatti' target='_blank'>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M23.954 4.569a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.691 8.094 4.066 6.13 1.64 3.161a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.061a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.937 4.937 0 004.604 3.417 9.868 9.868 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63a9.936 9.936 0 002.46-2.548l-.047-.02z" />
</svg>
</a>
</Link>
<Link href="/">
<a href='https://www.youtube.com/channel/UCK0Q8q7wFeM_DJU8cz6sgjA' target='_blank'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z" />
</svg>
</a>
</Link>
<Link href="/">
<a href='https://linkedin.com/in/DanieleSalatti' target='_blank'>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
</svg>
</a>
</Link>
<Link href="/">
<a href='mailto:me@danielesalatti.com'>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M11.585 5.267c1.834 0 3.558.811 4.824 2.08v.004c0-.609.41-1.068.979-1.068h.145c.891 0 1.073.842 1.073 1.109l.005 9.475c-.063.621.64.941 1.029.543 1.521-1.564 3.342-8.038-.946-11.79-3.996-3.497-9.357-2.921-12.209-.955-3.031 2.091-4.971 6.718-3.086 11.064 2.054 4.74 7.931 6.152 11.424 4.744 1.769-.715 2.586 1.676.749 2.457-2.776 1.184-10.502 1.064-14.11-5.188C-.977 13.521-.847 6.093 5.62 2.245 10.567-.698 17.09.117 21.022 4.224c4.111 4.294 3.872 12.334-.139 15.461-1.816 1.42-4.516.037-4.498-2.031l-.019-.678c-1.265 1.256-2.948 1.988-4.782 1.988-3.625 0-6.813-3.189-6.813-6.812 0-3.659 3.189-6.885 6.814-6.885zm4.561 6.623c-.137-2.653-2.106-4.249-4.484-4.249h-.09c-2.745 0-4.268 2.159-4.268 4.61 0 2.747 1.842 4.481 4.256 4.481 2.693 0 4.464-1.973 4.592-4.306l-.006-.536z" />
</svg>
</a>
</Link>
<Link href="/">
<a href='https://danielesalatti.com/feed.xml' target='_blank'>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M19.199 24C19.199 13.467 10.533 4.8 0 4.8V0c13.165 0 24 10.835 24 24h-4.801zM3.291 17.415a3.3 3.3 0 013.293 3.295A3.303 3.303 0 013.283 24C1.47 24 0 22.526 0 20.71s1.475-3.294 3.291-3.295zM15.909 24h-4.665c0-6.169-5.075-11.245-11.244-11.245V8.09c8.727 0 15.909 7.184 15.909 15.91z" />
</svg>
</a>
</Link>
</>
}
>
<li>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li>
<Link href="https://github.com/DanieleSalatti/convictionvotingwtf">
<a>GitHub</a>
</Link>
</li>
</CenteredFooter>
</Section>
</Background>
);
export { Footer };

62
src/templates/Hero.tsx Normal file
View File

@ -0,0 +1,62 @@
import Link from 'next/link';
import { Background } from '../background/Background';
import { Button } from '../button/Button';
import { HeroOneButton } from '../hero/HeroOneButton';
import { Section } from '../layout/Section';
import { NavbarTwoColumns } from '../navigation/NavbarTwoColumns';
import { Logo } from './Logo';
const Hero = () => (
<Background color="bg-gray-100">
<Section yPadding="py-6">
<NavbarTwoColumns logo={<Logo xl />}>
<li>
<Link href="https://github.com/DanieleSalatti/convictionvotingwtf">
<a>GitHub</a>
</Link>
</li>
</NavbarTwoColumns>
</Section>
<Section yPadding="pt-20 pb-32">
<HeroOneButton
title={
<>
{'What is \n'}
<span className="text-primary-500">Conviction Voting</span>
{'\nand why do we need it?'}
</>
}
description={
<>{'"Conviction Voting offers a novel decision making process that funds proposals based on the aggregated preference of community members, expressed continuously."'}<br />
<Link href="/">
<a href='https://twitter.com/jeffemmett' target='_blank'>
Jeff Emmett
</a>
</Link>
{', '}
<Link href="/">
<a href='https://commonsstack.org/' target='_blank'>
@CommonsStack
</a>
</Link>
</>
}
button={null}
/*
button={
<Link href="">
<a>
<Button xl>CTA</Button>
</a>
</Link>
}*/
/>
</Section>
</Background>
);
export { Hero };

38
src/templates/Logo.tsx Normal file
View File

@ -0,0 +1,38 @@
import { AppConfig } from '../utils/AppConfig';
type ILogoProps = {
xl?: boolean;
};
const Logo = (props: ILogoProps) => {
const size = props.xl ? '44' : '32';
const fontStyle = props.xl
? 'font-semibold text-3xl'
: 'font-semibold text-xl';
return (
<span className={`text-gray-900 inline-flex items-center ${fontStyle}`}>
<svg
className="text-primary-500 stroke-current mr-1"
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox="0 0 24 24"
strokeWidth="1.5"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M0 0h24v24H0z" stroke="none" />
<rect x="3" y="12" width="6" height="8" rx="1" />
<rect x="9" y="8" width="6" height="12" rx="1" />
<rect x="15" y="4" width="6" height="16" rx="1" />
<path d="M4 20h14" />
</svg>
{AppConfig.site_name}
</span>
);
};
export { Logo };

View File

@ -0,0 +1,33 @@
import { VerticalFeatureRow } from '../feature/VerticalFeatureRow';
import { Section } from '../layout/Section';
const VerticalFeatures = () => (
<Section
title="Working in progress"
description="We are working on this page. Please check back later."
>
{/*
<VerticalFeatureRow
title="Your title here"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse bibendum, nunc non posuere consectetur, justo erat semper enim, non hendrerit dui odio id enim."
image="/assets/images/feature.svg"
imageAlt="First feature alt text"
/>
<VerticalFeatureRow
title="Your title here"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse bibendum, nunc non posuere consectetur, justo erat semper enim, non hendrerit dui odio id enim."
image="/assets/images/feature2.svg"
imageAlt="Second feature alt text"
reverse
/>
<VerticalFeatureRow
title="Your title here"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse bibendum, nunc non posuere consectetur, justo erat semper enim, non hendrerit dui odio id enim."
image="/assets/images/feature3.svg"
imageAlt="Third feature alt text"
/>
*/}
</Section>
);
export { VerticalFeatures };

6
src/utils/AppConfig.ts Normal file
View File

@ -0,0 +1,6 @@
export const AppConfig = {
site_name: 'Conviction Voting',
title: 'Conviction Voting',
description: 'What is conviction voting and why is important?',
locale: 'en',
};

48
tailwind.config.js Normal file
View File

@ -0,0 +1,48 @@
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: {
fontSize: {
xs: '0.75rem',
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
'4xl': '2.25rem',
'5xl': '3rem',
'6xl': '4rem',
},
extend: {
colors: {
primary: {
100: '#E6F6FE',
200: '#C0EAFC',
300: '#9ADDFB',
400: '#4FC3F7',
500: '#03A9F4',
600: '#0398DC',
700: '#026592',
800: '#014C6E',
900: '#013349',
},
gray: {
100: '#f7fafc',
200: '#edf2f7',
300: '#e2e8f0',
400: '#cbd5e0',
500: '#a0aec0',
600: '#718096',
700: '#4a5568',
800: '#2d3748',
900: '#1a202c',
},
},
lineHeight: {
hero: '4.5rem',
},
},
},
variants: {},
plugins: [],
};

40
tsconfig.json Normal file
View File

@ -0,0 +1,40 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"removeComments": true,
"preserveConstEnums": true,
"strict": true,
"alwaysStrict": true,
"strictNullChecks": true,
"noUncheckedIndexedAccess": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowUnreachableCode": false,
"noFallthroughCasesInSwitch": true,
"target": "es5",
"outDir": "out",
"declaration": true,
"sourceMap": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"allowJs": false,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"jsx": "preserve",
"noEmit": true,
"isolatedModules": true,
"incremental": true
},
"exclude": ["./out/**/*", "./node_modules/**/*"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}