initial commit
1
.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
25
.github/workflows/merge-main-into-small-image.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: merge-main-into-small-image.yml
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types:
|
||||
- closed
|
||||
jobs:
|
||||
merge-main-into-small-image:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.merged == true
|
||||
timeout-minutes: 3
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Merge with main
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git fetch
|
||||
git checkout small-image
|
||||
git merge main --no-ff --no-edit
|
||||
git push origin small-image
|
104
.gitignore
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
BIN
img/logos/favicon-dark.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
img/logos/favicon-light.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
img/logos/favicon-mid.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
img/logos/favicon-t-dark.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
img/logos/favicon-t-light.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
img/logos/favicon-t-mid.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
img/logos/logo-dark.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
img/logos/logo-large.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
img/logos/logo-light.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
img/logos/logo-mid.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
img/logos/logo-white.png
Normal file
After Width: | Height: | Size: 14 KiB |
23
kube/Dockerfile
Normal file
@ -0,0 +1,23 @@
|
||||
# Start your image with a node base image
|
||||
FROM node:18-alpine
|
||||
|
||||
# The /app directory should act as the main application directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the app package and package-lock.json file
|
||||
COPY package*.json ./
|
||||
|
||||
# Copy local directories to the current local directory of our docker image (/app)
|
||||
COPY ./src ./src
|
||||
COPY ./public ./public
|
||||
|
||||
# Install node packages, install serve, build the app, and remove dependencies at the end
|
||||
RUN npm install \
|
||||
&& npm install -g serve \
|
||||
&& npm run build \
|
||||
&& rm -fr node_modules
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
# Start the app using serve command
|
||||
CMD [ "serve", "-s", "build" ]
|
107
kube/deploy-tomcode.yaml
Normal file
@ -0,0 +1,107 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: sites
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: tomcode-pv
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
storageClassName: manual
|
||||
capacity:
|
||||
storage: 128Mi
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
hostPath:
|
||||
path: "/var/lib/rancher/k3s/storage/tomcode"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: tomcode-pvc
|
||||
namespace: sites
|
||||
spec:
|
||||
volumeName: tomcode-pv
|
||||
storageClassName: manual
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
resources:
|
||||
requests:
|
||||
storage: 128Mi
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: tomcode
|
||||
namespace: sites
|
||||
labels:
|
||||
app: tomcode
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: tomcode
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: tomcode
|
||||
spec:
|
||||
containers:
|
||||
- name: tomcode
|
||||
image: tommansfield/tomcode:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "1"
|
||||
volumeMounts:
|
||||
- name: tomcode-volume
|
||||
mountPath: /data
|
||||
subPath: ./web
|
||||
volumes:
|
||||
- name: tomcode-volume
|
||||
persistentVolumeClaim:
|
||||
claimName: tomcode-pvc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: tomcode
|
||||
namespace: sites
|
||||
labels:
|
||||
app: tomcode
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- name: tomcode
|
||||
port: 80
|
||||
targetPort: 3000
|
||||
nodePort: 30800
|
||||
selector:
|
||||
app: tomcode
|
||||
---
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: tomcode
|
||||
namespace: sites
|
||||
spec:
|
||||
entryPoints:
|
||||
- websecure
|
||||
routes:
|
||||
- kind: Rule
|
||||
match: Host(`tomcode.io`, `www.tomcode.io`)
|
||||
services:
|
||||
- name: tomcode
|
||||
port: 80
|
||||
tls:
|
||||
certResolver: letsencrypt
|
||||
domains:
|
||||
- main: "tomcode.io"
|
||||
sans:
|
||||
- "*.tomcode.io"
|
16967
package-lock.json
generated
Normal file
36
package.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "welcome-to-docker",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-particles": "^2.9.3",
|
||||
"react-scripts": "5.0.1",
|
||||
"tsparticles": "^2.9.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
BIN
public/favicon-dark.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/favicon-light.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
18
public/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
|
||||
/>
|
||||
<title>tomcode.io</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
BIN
public/logo-white.png
Normal file
After Width: | Height: | Size: 14 KiB |
3
public/robots.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
36
src/App.css
Normal file
@ -0,0 +1,36 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #003f8c;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 3vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-header h1 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.App-header p {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.App-header .logo {
|
||||
width: 40vw;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color:#269cfc
|
||||
}
|
19
src/App.js
Normal file
@ -0,0 +1,19 @@
|
||||
import "./App.css";
|
||||
import Confetti from "./Confetti";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<div className="App">
|
||||
<Confetti />
|
||||
<header className="App-header">
|
||||
<img className="logo" src="logo-white.png" alt="tomcode.io computer logo"></img>
|
||||
<h1 style={{ marginBottom: "0px" }}>tomcode<span className="blue">.io</span></h1>
|
||||
<p style={{ marginTop: "10px", marginBottom: "50px" }}>
|
||||
Love the web 💻
|
||||
</p>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
177
src/Confetti.js
Normal file
@ -0,0 +1,177 @@
|
||||
import Particles from "react-particles";
|
||||
import { useCallback } from "react";
|
||||
import { loadFull } from "tsparticles";
|
||||
|
||||
const Confetti = () => {
|
||||
|
||||
const particlesInit = useCallback(async engine => {
|
||||
console.log(engine);
|
||||
// you can initiate the tsParticles instance (engine) here, adding custom shapes or presets
|
||||
// this loads the tsparticles package bundle, it's the easiest method for getting everything ready
|
||||
// starting from v2 you can add only the features you need reducing the bundle size
|
||||
await loadFull(engine);
|
||||
}, []);
|
||||
|
||||
const particlesLoaded = useCallback(async container => {
|
||||
await console.log(container);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Particles
|
||||
id="tsparticles"
|
||||
init={particlesInit}
|
||||
loaded={particlesLoaded}
|
||||
options={{
|
||||
fullScreen: {
|
||||
zIndex: 1
|
||||
},
|
||||
emitters: [
|
||||
{
|
||||
position: {
|
||||
x: 0,
|
||||
y: 30
|
||||
},
|
||||
rate: {
|
||||
quantity: 5,
|
||||
delay: 0.15
|
||||
},
|
||||
particles: {
|
||||
move: {
|
||||
direction: "top-right",
|
||||
outModes: {
|
||||
top: "none",
|
||||
left: "none",
|
||||
default: "destroy"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
position: {
|
||||
x: 100,
|
||||
y: 30
|
||||
},
|
||||
rate: {
|
||||
quantity: 5,
|
||||
delay: 0.15
|
||||
},
|
||||
particles: {
|
||||
move: {
|
||||
direction: "top-left",
|
||||
outModes: {
|
||||
top: "none",
|
||||
right: "none",
|
||||
default: "destroy"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
particles: {
|
||||
color: {
|
||||
value: [
|
||||
"#ffffff",
|
||||
"#FF0000"
|
||||
]
|
||||
},
|
||||
move: {
|
||||
decay: 0.05,
|
||||
direction: "top",
|
||||
enable: true,
|
||||
gravity: {
|
||||
"enable": true
|
||||
},
|
||||
outModes: {
|
||||
top: "none",
|
||||
default: "destroy"
|
||||
},
|
||||
speed: {
|
||||
min: 10,
|
||||
max: 50
|
||||
}
|
||||
},
|
||||
number: {
|
||||
value: 0
|
||||
},
|
||||
opacity: {
|
||||
value: 1
|
||||
},
|
||||
rotate: {
|
||||
value: {
|
||||
min: 0,
|
||||
max: 360
|
||||
},
|
||||
direction: "random",
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 30
|
||||
}
|
||||
},
|
||||
tilt: {
|
||||
direction: "random",
|
||||
enable: true,
|
||||
value: {
|
||||
min: 0,
|
||||
max: 360
|
||||
},
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 30
|
||||
}
|
||||
},
|
||||
size: {
|
||||
value: {
|
||||
min: 0,
|
||||
max: 7
|
||||
},
|
||||
animation: {
|
||||
enable: true,
|
||||
startValue: "min",
|
||||
count: 1,
|
||||
speed: 16,
|
||||
sync: true
|
||||
}
|
||||
},
|
||||
roll: {
|
||||
darken: {
|
||||
enable: true,
|
||||
value: 25
|
||||
},
|
||||
enable: true,
|
||||
speed: {
|
||||
min: 5,
|
||||
max: 15
|
||||
}
|
||||
},
|
||||
wobble: {
|
||||
distance: 30,
|
||||
enable: true,
|
||||
speed: {
|
||||
min: -7,
|
||||
max: 7
|
||||
}
|
||||
},
|
||||
shape: {
|
||||
type: [
|
||||
"square",
|
||||
"triangle",
|
||||
"polygon"
|
||||
],
|
||||
options: {
|
||||
polygon: [
|
||||
{
|
||||
sides: 5
|
||||
},
|
||||
{
|
||||
sides: 6
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Confetti;
|
13
src/index.css
Normal file
@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Roboto',
|
||||
monospace;
|
||||
}
|
11
src/index.js
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|