mirror of
https://github.com/cupcakearmy/fantus.git
synced 2025-09-05 21:50:40 +00:00
update, formatting and vercel
This commit is contained in:
@@ -2,7 +2,6 @@ import React from 'react'
|
||||
import App from 'next/app'
|
||||
import Head from 'next/head'
|
||||
import dynamic from 'next/dynamic'
|
||||
import getConfig from 'next/config'
|
||||
|
||||
import 'tachyons/css/tachyons.min.css'
|
||||
import '../styles/app.styl'
|
||||
@@ -10,28 +9,29 @@ import Menu from '../screens/menu'
|
||||
import Content from '../components/content'
|
||||
|
||||
const Background = dynamic(() => import('../components/background'), { ssr: false })
|
||||
const { RECAPTCHA_CLIENT } = getConfig().publicRuntimeConfig
|
||||
|
||||
export default class extends App {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>fantus</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="description" content="fantus - producer, dj, engineer" />
|
||||
<meta name="keywords" content="dj,producer,mastering,service,free,sets,mix,techno,music,set" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Space+Mono:400,700&display=swap" rel="stylesheet" />
|
||||
<script src={'https://www.google.com/recaptcha/api.js?render=' + RECAPTCHA_CLIENT}></script>
|
||||
</Head>
|
||||
<Menu />
|
||||
<Background />
|
||||
<Content>
|
||||
<Component {...pageProps} />
|
||||
</Content>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>fantus</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="description" content="fantus - producer, dj, engineer" />
|
||||
<meta name="keywords" content="dj,producer,mastering,service,free,sets,mix,techno,music,set" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Space+Mono:400,700&display=swap" rel="stylesheet" />
|
||||
<script
|
||||
src={'https://www.google.com/recaptcha/api.js?render=' + process.env.NEXT_PUBLIC_RECAPTCHA_CLIENT}
|
||||
></script>
|
||||
</Head>
|
||||
<Menu />
|
||||
<Background />
|
||||
<Content>
|
||||
<Component {...pageProps} />
|
||||
</Content>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,29 @@
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
export default class extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html lang='en'>
|
||||
<Head />
|
||||
<body>
|
||||
<script type="x-shader/x-vertex" id="vertexshader" dangerouslySetInnerHTML={{ __html: `attribute float scale;void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;}` }}></script>
|
||||
<script type="x-shader/x-fragment" id="fragmentshader" dangerouslySetInnerHTML={{ __html: `uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;gl_FragColor = vec4( color, 1.0 );}` }}></script>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head />
|
||||
<body>
|
||||
<script
|
||||
type="x-shader/x-vertex"
|
||||
id="vertexshader"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `attribute float scale;void main() {vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );gl_PointSize = scale * ( 300.0 / - mvPosition.z );gl_Position = projectionMatrix * mvPosition;}`,
|
||||
}}
|
||||
></script>
|
||||
<script
|
||||
type="x-shader/x-fragment"
|
||||
id="fragmentshader"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `uniform vec3 color;void main() {if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;gl_FragColor = vec4( color, 1.0 );}`,
|
||||
}}
|
||||
></script>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -1,33 +1,45 @@
|
||||
import React from 'react'
|
||||
|
||||
const Home = () => {
|
||||
return <div className='center color'>
|
||||
<h1 className='ma0'>about</h1>
|
||||
<div className='text'>
|
||||
<p>
|
||||
yet another producer. because we don't already have enough of them.
|
||||
<br />
|
||||
<br />
|
||||
📍based on planet earth
|
||||
<br />
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<a target='_blank' href='https://www.mixcloud.com/fantus/'>mixcloud</a>
|
||||
<br />
|
||||
<a target='_blank' href='https://soundcloud.com/fantus_music'>soundcloud</a>
|
||||
<br />
|
||||
<a target='_blank' href='https://www.instagram.com/fantus.studio/'>instagram</a>
|
||||
<br />
|
||||
<br />
|
||||
<a target='_blank' href='mailto:hi@fantus.studio'>contact email</a>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
website made by 🤖 with ❤️. <a target='_blank' href="https://github.com/cupcakearmy/fantus">source code available here</a>
|
||||
</p>
|
||||
</div>
|
||||
return (
|
||||
<div className="center color">
|
||||
<h1 className="ma0">about</h1>
|
||||
<div className="text">
|
||||
<p>
|
||||
yet another producer. because we don't already have enough of them.
|
||||
<br />
|
||||
<br />
|
||||
📍based on planet earth
|
||||
<br />
|
||||
</p>
|
||||
<p>
|
||||
<a target="_blank" href="https://www.mixcloud.com/fantus/">
|
||||
mixcloud
|
||||
</a>
|
||||
<br />
|
||||
<a target="_blank" href="https://soundcloud.com/fantus_music">
|
||||
soundcloud
|
||||
</a>
|
||||
<br />
|
||||
<a target="_blank" href="https://www.instagram.com/fantus.studio/">
|
||||
instagram
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<a target="_blank" href="mailto:hi@fantus.studio">
|
||||
contact email
|
||||
</a>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
website made by 🤖 with ❤️.{' '}
|
||||
<a target="_blank" href="https://github.com/cupcakearmy/fantus">
|
||||
source code available here
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
export default Home
|
||||
|
@@ -1,83 +1,77 @@
|
||||
import { createReadStream, statSync, unlinkSync, writeFileSync } from 'fs'
|
||||
import { tmpdir } from 'os'
|
||||
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import getConfig from 'next/config'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import Formidable from 'formidable'
|
||||
import axios from 'axios'
|
||||
|
||||
const { RECAPTCHA_SERVER, NEXTCLOUD_TOKEN } = getConfig().serverRuntimeConfig
|
||||
|
||||
const sendFileAndDelete = async (name: string, path: string) => {
|
||||
const stat = statSync(path)
|
||||
const stream = createReadStream(path)
|
||||
const stat = statSync(path)
|
||||
const stream = createReadStream(path)
|
||||
|
||||
await axios({
|
||||
url: 'https://cloud.nicco.io/public.php/webdav/' + name,
|
||||
method: 'put',
|
||||
auth: {
|
||||
username: NEXTCLOUD_TOKEN,
|
||||
password: '',
|
||||
},
|
||||
headers: {
|
||||
'Content-Length': stat.size
|
||||
},
|
||||
data: stream
|
||||
})
|
||||
await axios({
|
||||
url: 'https://cloud.nicco.io/public.php/webdav/' + name,
|
||||
method: 'put',
|
||||
auth: {
|
||||
username: process.env.NEXTCLOUD_TOKEN || '',
|
||||
password: '',
|
||||
},
|
||||
headers: {
|
||||
'Content-Length': stat.size,
|
||||
},
|
||||
data: stream,
|
||||
maxContentLength: Infinity,
|
||||
})
|
||||
|
||||
unlinkSync(path)
|
||||
unlinkSync(path)
|
||||
}
|
||||
|
||||
export default async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
try {
|
||||
// @ts-ignore
|
||||
const form = new Formidable()
|
||||
|
||||
// @ts-ignore
|
||||
const form = new Formidable();
|
||||
form.maxFileSize = 300 * 1024 * 1024 // 300MiB
|
||||
|
||||
form.maxFileSize = 300 * 1024 * 1024 // 300MiB
|
||||
const body = await new Promise<any>((resolve, reject) => {
|
||||
form.parse(req, (err: any, fields: any, files: any) => {
|
||||
if (err) reject()
|
||||
else
|
||||
resolve({
|
||||
fields: JSON.parse(fields.json),
|
||||
files: Object.values(files),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const body = await new Promise<any>((resolve, reject) => {
|
||||
form.parse(req, (err: any, fields: any, files: any) => {
|
||||
if (err) reject()
|
||||
else resolve({
|
||||
fields: JSON.parse(fields.json),
|
||||
files: Object.values(files)
|
||||
})
|
||||
});
|
||||
})
|
||||
const { token, ...rest } = body.fields
|
||||
|
||||
const { data } = await axios({
|
||||
url: 'https://www.google.com/recaptcha/api/siteverify',
|
||||
method: 'post',
|
||||
params: {
|
||||
secret: process.env.RECAPTCHA_SERVER,
|
||||
response: token,
|
||||
},
|
||||
})
|
||||
|
||||
if (!data.success) throw new Error()
|
||||
|
||||
const { token, ...rest } = body.fields
|
||||
const now = Date.now()
|
||||
for (const file of body.files) await sendFileAndDelete(`${now}_${file.name}`, file.path)
|
||||
|
||||
const { data } = await axios({
|
||||
url: 'https://www.google.com/recaptcha/api/siteverify',
|
||||
method: 'post',
|
||||
params: {
|
||||
secret: RECAPTCHA_SERVER,
|
||||
response: token,
|
||||
},
|
||||
})
|
||||
const txtFile = `${tmpdir()}/text`
|
||||
writeFileSync(txtFile, `${rest.contact}\n${rest.description}`)
|
||||
await sendFileAndDelete(`${now}_details.txt`, txtFile)
|
||||
|
||||
if (!data.success) throw new Error()
|
||||
|
||||
const now = Date.now()
|
||||
for (const file of body.files)
|
||||
sendFileAndDelete(`${now}_${file.name}`, file.path)
|
||||
|
||||
const txtFile = `${tmpdir()}/text`
|
||||
writeFileSync(txtFile, `${rest.contact}\n${rest.description}`)
|
||||
sendFileAndDelete(`${now}_details.txt`, txtFile)
|
||||
|
||||
res.status(200).end()
|
||||
|
||||
} catch {
|
||||
res.status(400).end()
|
||||
}
|
||||
res.status(200).end()
|
||||
} catch {
|
||||
res.status(400).end()
|
||||
}
|
||||
}
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: false,
|
||||
},
|
||||
}
|
||||
api: {
|
||||
bodyParser: false,
|
||||
},
|
||||
}
|
||||
|
@@ -1,27 +1,37 @@
|
||||
import React from 'react'
|
||||
|
||||
const Home = () => {
|
||||
return <div className='center'>
|
||||
<h2>neodymium enabled waves. new.</h2>
|
||||
<p>
|
||||
<b><u>neodymium:</u> </b>
|
||||
<cite>
|
||||
a bright, silvery, reactive rare-earth element, found in monazite and bastnaesite and used for coloring glass, for doping laser glass and crystals, and in materials with strong, permanent magnetic properties that make them useful for computer and audio equipment. Atomic number 60; atomic weight 144.24; melting point 1,016°C; boiling point 3,074°C;
|
||||
</cite>
|
||||
</p>
|
||||
<p>
|
||||
<b><u>enabled:</u> </b>
|
||||
<cite>
|
||||
to make able; give power, means, competence, or ability to; authorize
|
||||
</cite>
|
||||
</p>
|
||||
<p>
|
||||
<b><u>wave:</u> </b>
|
||||
<cite>
|
||||
the continuous, repeating pattern in which some types of energy, such as sound, light, and heat, are spread or carried
|
||||
</cite>
|
||||
</p>
|
||||
return (
|
||||
<div className="center">
|
||||
<h2>neodymium enabled waves. new.</h2>
|
||||
<p>
|
||||
<b>
|
||||
<u>neodymium:</u>{' '}
|
||||
</b>
|
||||
<cite>
|
||||
a bright, silvery, reactive rare-earth element, found in monazite and bastnaesite and used for coloring glass,
|
||||
for doping laser glass and crystals, and in materials with strong, permanent magnetic properties that make
|
||||
them useful for computer and audio equipment. Atomic number 60; atomic weight 144.24; melting point 1,016°C;
|
||||
boiling point 3,074°C;
|
||||
</cite>
|
||||
</p>
|
||||
<p>
|
||||
<b>
|
||||
<u>enabled:</u>{' '}
|
||||
</b>
|
||||
<cite>to make able; give power, means, competence, or ability to; authorize</cite>
|
||||
</p>
|
||||
<p>
|
||||
<b>
|
||||
<u>wave:</u>{' '}
|
||||
</b>
|
||||
<cite>
|
||||
the continuous, repeating pattern in which some types of energy, such as sound, light, and heat, are spread or
|
||||
carried
|
||||
</cite>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
export default Home
|
||||
|
@@ -3,34 +3,38 @@ import React from 'react'
|
||||
import Form from '../screens/form'
|
||||
|
||||
const Home = () => {
|
||||
return <div className='center color'>
|
||||
<h1 className='ma0'>mastering</h1>
|
||||
<div>
|
||||
<h3>how does it work?</h3>
|
||||
<p>
|
||||
My aim is to practise mastering.
|
||||
As anything it requires a lot of trial and error. So the idea is as follows:
|
||||
</p>
|
||||
<ol>
|
||||
<li>You send me a track</li>
|
||||
<li>It gets mastered based on your wishes & feedback</li>
|
||||
<li>If you like it, you are free to use the master for free. Otherwise just trash it.</li>
|
||||
</ol>
|
||||
<h3>what's the catch then?</h3>
|
||||
<p>
|
||||
Nothing really. It's <b><i>completely free</i></b> for you.
|
||||
It goes without saying that of course I will not upload the tracks anywhere.
|
||||
No surprises.
|
||||
</p>
|
||||
<h3>what if you like the result?</h3>
|
||||
<p>
|
||||
If you think the master is good you can use it for free withouth any royalties to me.
|
||||
It would be cool if you could reference me in the youtube description or spotify credits for mastering it, but it's totally optional and up to you.
|
||||
</p>
|
||||
</div>
|
||||
<br />
|
||||
<Form />
|
||||
return (
|
||||
<div className="center color">
|
||||
<h1 className="ma0">mastering</h1>
|
||||
<div>
|
||||
<h3>how does it work?</h3>
|
||||
<p>
|
||||
My aim is to practise mastering. As anything it requires a lot of trial and error. So the idea is as follows:
|
||||
</p>
|
||||
<ol>
|
||||
<li>You send me a track</li>
|
||||
<li>It gets mastered based on your wishes & feedback</li>
|
||||
<li>If you like it, you are free to use the master for free. Otherwise just trash it.</li>
|
||||
</ol>
|
||||
<h3>what's the catch then?</h3>
|
||||
<p>
|
||||
Nothing really. It's{' '}
|
||||
<b>
|
||||
<i>completely free</i>
|
||||
</b>{' '}
|
||||
for you. It goes without saying that of course I will not upload the tracks anywhere. No surprises.
|
||||
</p>
|
||||
<h3>what if you like the result?</h3>
|
||||
<p>
|
||||
If you think the master is good you can use it for free withouth any royalties to me. It would be cool if you
|
||||
could reference me in the youtube description or spotify credits for mastering it, but it's totally optional
|
||||
and up to you.
|
||||
</p>
|
||||
</div>
|
||||
<br />
|
||||
<Form />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
export default Home
|
||||
|
@@ -1,31 +1,56 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { NextPage } from 'next'
|
||||
import type { NextPage, GetStaticProps } from 'next'
|
||||
import React from 'react'
|
||||
import axios from 'axios'
|
||||
|
||||
const Home: NextPage = () => {
|
||||
|
||||
const [links, setLinks] = useState([] as string[])
|
||||
|
||||
useEffect(() => {
|
||||
axios.get('https://api.fantus.studio/directus/items/mixes?status=published')
|
||||
.then(({ data }) => {
|
||||
setLinks(data.data.map((entry: any) => entry.link))
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <div className='sets'>
|
||||
<h1 className='ma0'>sets</h1>
|
||||
<p>
|
||||
collection of some sets made here and there.
|
||||
</p>
|
||||
<ul>
|
||||
{links.map(link => (
|
||||
<li key={link}>
|
||||
<iframe width="100%" height="120" src={link} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
type Props = {
|
||||
slugs: string[]
|
||||
}
|
||||
|
||||
export default Home
|
||||
const Home: NextPage<Props> = ({ slugs }) => {
|
||||
const encoded = slugs.map((slug) => encodeURIComponent(`/fantus/${slug}/`))
|
||||
|
||||
return (
|
||||
<div className="sets">
|
||||
<h1 className="ma0">sets</h1>
|
||||
<p>collection of some sets made here and there.</p>
|
||||
<ul>
|
||||
{encoded.map((link) => (
|
||||
<li key={link}>
|
||||
<iframe
|
||||
width="100%"
|
||||
height="120"
|
||||
src={`https://www.mixcloud.com/widget/iframe/?hide_cover=1&feed=${link}`}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async (context) => {
|
||||
const { data } = await axios({
|
||||
url: 'https://www.mixcloud.com/graphql',
|
||||
method: 'post',
|
||||
data: {
|
||||
query: `
|
||||
query UserUploadsQuery($lookup: UserLookup!, $orderBy: CloudcastOrderByEnum) {
|
||||
user: userLookup(lookup: $lookup) {
|
||||
uploads(first: 100, orderBy: $orderBy) {
|
||||
edges {
|
||||
node {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { lookup: { username: 'fantus' }, orderBy: 'LATEST' },
|
||||
},
|
||||
})
|
||||
const slugs: string[] = data.data.user.uploads.edges.map((item: any) => item.node.slug)
|
||||
return { props: { slugs } }
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import React from 'react'
|
||||
|
||||
const Home = () => {
|
||||
return <div className='center'>
|
||||
<h2>works</h2>
|
||||
<p>
|
||||
in progress... lot of skratches lying around
|
||||
</p>
|
||||
return (
|
||||
<div className="center">
|
||||
<h2>works</h2>
|
||||
<p>in progress... lot of skratches lying around</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
export default Home
|
||||
|
Reference in New Issue
Block a user