gitea init.

This commit is contained in:
russoj88 2020-02-19 17:16:28 -08:00
commit b09a77f287
44 changed files with 7952 additions and 0 deletions

4
.dockerignore Normal file
View File

@ -0,0 +1,4 @@
.git
.gitignore
Dockerfile*
README.md

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
node_modules/
dist
# IDE
.idea

9
Dockerfile.dev Normal file
View File

@ -0,0 +1,9 @@
# Using the current version of Node and Alpine
FROM node:current-alpine
# This should be mounted with docker run command
WORKDIR /src
# Install deps and run the development server
ENV PATH="/node_modules/.bin:${PATH}"
ENTRYPOINT cd /src && yarn --modules-folder /node_modules install && yarn --modules-folder /node_modules dev

29
Dockerfile.prod Normal file
View File

@ -0,0 +1,29 @@
# STEP 1: Build the website's files
FROM node:current-alpine AS build-website
WORKDIR /src
COPY . /src/
RUN cd /src && yarn && yarn build
# STEP 2: Get a binary for the static-web-server
FROM golang:alpine AS build-webserver
RUN apk update && apk upgrade && \
apk add --no-cache git
RUN go get -u git.simplesystems.tech/SimpleSystems/static-web-server
# STEP 3: Combine static files and binary on fresh alpine image
FROM alpine:latest
WORKDIR /app
# Copy over static website files
COPY --from=build-website /src/dist /app/dist
# Copy over static-web-server
COPY --from=build-webserver /go/bin/static-web-server /app/
ENTRYPOINT ["./static-web-server", "-rootDir", "dist", "-port", "80", "-spa"]

69
README.md Normal file
View File

@ -0,0 +1,69 @@
# Simple Systems Website
## Local development
Build image
```shell script
docker build -f Dockerfile.dev -t website-fe .
```
Run the container using the current directory for the source files
```shell script
docker run -it -p 8080:8080 --mount source=$(pwd),target=/src,type=bind --rm website-fe
```
## Building (non docker)
To create a production build, run:
```shell script
yarn
yarn build
```
The static resources will be stored in the `./dist` directory.
## Production Docker build and run
To build the production site in a docker container, run the following command:
```shell script
docker build -f Dockerfile.prod -t website-rel .
```
To run the production container, run the following command:
```shell script
docker run --rm -it -p 8080:8080 website-rel
```
## Get static files for AWS hosting
Use Docker's copy to pull the files out of a working production container:
```shell script
docker cp CONTAINER_ID:/app/dist /local/destination
```
## Versioning
Tags will indicate when a particular commit was ready to be live.
Ex: `v2019-07-28_031407`
*nix command: `date -u +v%Y-%m-%d_%H%M%S`
## Managing Job Posts
To add a job post:
1. Place the markdown file in `./src/job-posts`.
2. Add the file name (excluding the extension) as an entry `./src/assets/jobKeys.js`.
These entries determine the display order.
To remove a job post:
1. Remove the markdown file from `./src/job-posts`.
2. Remove the entry from the data in `./src/assets/jobKeys.js`.
## Managing Blog Posts
To add a blog post:
1. Place the markdown file in `./src/blog-posts`.
2. Add the file name (excluding the extension) as an entry `./src/assets/blogKeys.js`.
These entries determine the display order.
To remove a blog post:
1. Remove the markdown file from `./src/blog-posts`.
2. Remove the entry from the data in `./src/assets/blogKeys.js`.

25
package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "SimpleSystems",
"version": "0.1.0",
"license": "MIT",
"scripts": {
"dev": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"devDependencies": {
"@vue/cli-service": "^3.11.0",
"deepmerge": "^4.1.1",
"fibers": "^4.0.1",
"frontmatter-markdown-loader": "^3.1.0",
"material-design-icons-iconfont": "^5.0.1",
"sass": "^1.23.0",
"sass-loader": "7.3.1",
"vue-cli-plugin-vuetify": "^1.1.1",
"vue-template-compiler": "^2.6.10"
},
"dependencies": {
"vue": "^2.6.10",
"vue-router": "^3.1.3",
"vuetify": "^2.1.5"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
public/img/checklist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/img/database.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
public/img/interact.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
public/img/jeff-snow.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

BIN
public/img/leverage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
public/img/monero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
public/img/monitor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/img/robust.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

BIN
public/img/rocket-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
public/img/tools.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
public/img/website.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

14
public/index.html Normal file
View File

@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link rel="shortcut icon" href="/favicon.ico">
<title>SimpleSystems, LLC</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

124
src/App.vue Normal file
View File

@ -0,0 +1,124 @@
<template>
<v-app id="inspire">
<v-app-bar dark fixed app>
<!-- Light / dark Vuetify theme toggle -->
<v-btn
icon
@click="$vuetify.theme.dark = !$vuetify.theme.dark"
>
<v-icon v-text="($vuetify.theme.dark) ? 'wb_sunny' : 'brightness_2'" />
</v-btn>
<v-spacer/>
<router-link to="/">
<div class="white--text">
Simple Systems, LLC
</div>
</router-link>
<v-spacer/>
<v-btn icon @click="drawer = true">
<v-icon>menu</v-icon>
</v-btn>
</v-app-bar>
<v-navigation-drawer
v-model="drawer"
height="auto"
app
fixed
right
temporary
>
<v-list>
<v-list-item @click="drawer = false">
<v-list-item-content>
<v-list-item-title>Close</v-list-item-title>
</v-list-item-content>
<v-list-item-action>
<v-icon>close</v-icon>
</v-list-item-action>
</v-list-item>
<v-list-item v-for="link in validNav" :key="link.title" :to="link.to" :href="link.href" :target="('href' in link) ? '_blank' : ''">
<v-list-item-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>{{ link.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
<v-content>
<router-view></router-view>
</v-content>
<app-footer />
</v-app>
</template>
<script>
import AppFooter from '@/components/AppFooter.vue'
export default {
components: { AppFooter },
data() {
return {
drawer: false,
navLinks: [
{ title: 'Home', icon: 'home', to: '/' },
{ title: 'Services', icon: 'work', to: '/services' },
// { title: 'Our Process', icon: 'build', to: '/process' },
// { title: 'Influences', icon: 'build', to: '/influences' },
{ title: 'About', icon: 'info', to: '/about' },
{ title: 'Blog', icon: 'description', to: '/blog' },
{ title: 'Jobs', icon: 'dns', to: '/jobs' },
{ title: 'Our Projects', icon: 'code', href: 'https://gitlab.com/simplesystems' },
]
}
},
computed: {
validNav() {
return this.navLinks.filter(l => l.to !== this.$route.path)
}
}
}
</script>
<style>
a {
text-decoration: none;
}
img {
max-width: 100%;
}
* {
letter-spacing: 0 !important;
text-transform: none !important;
}
hr {
color: white;
}
h2, h3, h4 {
margin-top: 1.75rem;
margin-bottom: 0.5rem;
}
.article h3 ~ p {
margin-left: 1rem;
text-indent: 20pt;
}
.v-card__title {
word-break: normal;
}
@media (max-width: 600px) {
.v-btn::before {
background-color: transparent !important;
}
}
</style>

4
src/assets/blogKeys.js Normal file
View File

@ -0,0 +1,4 @@
export default [
'cryptocurrency',
'simplicity',
]

8
src/assets/blogPosts.js Normal file
View File

@ -0,0 +1,8 @@
import blogKeys from '@/assets/blogKeys'
export default blogKeys.map(blogKey => {
return {
key: blogKey,
module: require('@/blog-posts/' + blogKey + '.md'),
}
})

3
src/assets/jobKeys.js Normal file
View File

@ -0,0 +1,3 @@
export default [
'front-end-engineer',
]

View File

@ -0,0 +1,85 @@
---
image: /img/monero.png
title: Simple Systems Accepts Cryptocurrency
author: Jeff Russo
published: Dec 1, 2019
desc: This is why we accept crypto
---
Simple Systems will accept payment in
[Monero](https://web.getmonero.org/),
[Bitcoin](https://bitcoin.org/), or
[Litecoin](https://litecoin.org/).
### What is cryptocurrency?
Cryptocurrency is a medium of exchange that uses cryptography to ensure the key [properties](https://en.wikipedia.org/wiki/Money#Properties) of money are fulfilled.
It is decentralized, meaning no single entity controls it; all the regulations come from cryptography and consensus.
### Centralized fiat currencies
Today, governments across the world maintain different fiat currencies.
Fiat has some advantages over its predecessor, precious metals.
The government can control the supply, stabilizing the value.
It is also more portable than precious metals.
Carrying a bag of gold doesn't make sense when you can use Apple Pay or Google Pay.
Unfortunately, fiat currencies always end in disaster.
The longest lasting fiat currency was around for 325 years, but its value eventually went to zero.
A currency which experiences hyperinflation eventually becomes worthless.
Here are a few examples of this happening:
* <a href="https://www.theguardian.com/money/2016/may/14/zimbabwe-trillion-dollar-note-hyerinflation-investment" target="_blank">Z$100 trillion loaves of bread in Zimbabwe</a>
* <a href="https://en.wikipedia.org/wiki/Hyperinflation_in_the_Weimar_Republic" target="_blank">German Papiermark</a>: The currency was inflated to the point of people getting paid in wheelbarrows of cash.
![Wheelbarrow of Cash](/img/hyperinflation_wheelbarrow.jpg)
* <a href="https://fee.org/articles/venezuela-cant-afford-to-print-more-money/" target="_blank">Venezuela could not afford to print money</a>
* <a href="https://www.youtube.com/watch?v=dwZ6B5kalbQ" target="_blank">This video</a> shows some recent history of inflation rates.
The US Dollar is relatively strong, but its value has still been inflated away since its inception.
If you saved a dollar in 1913, it only has about 4 cents worth of buying power now.
### Bitcoin - A Major Breakthrough
[Bitcoin](https://bitcoin.org/bitcoin.pdf) was a major breakthrough in both computing and money.
It's Proof of Work consensus algorithm is the backbone of most cryptocurrencies.
This method enables entities from around the world to agree on something.
For cryptocurrencies, that something is the possession of money.
An agreement on the ownership of about $150B has been reached every ten minutes for over a decade.
Bitcoin's ledger is completely transparent.
When a transaction is created, the sender, receiver, and amount is made public.
This can be a problem for a few reasons.
First, it allows anyone to see how much money anyone else has.
If you get a cup of coffee, you most likely wouldn't advertise your bank account balance; why do this with crypto?
Secondly, this allows entities to discriminate based on transaction history.
Some bitcoin is considered tainted if it has been involved in illegal activities.
Organizations can refuse to do business with certain tainted bitcoin addresses.
By analogy, if you find a $10 bill on the ground and pick it up, should you be tied to its history?
If that $10 was in a bank robbery last year, should it be deemed to have less than $10 in value?
### Monero - Fungible
[Monero](https://web.getmonero.org/) is cryptocurrency which was released a few years after Bitcoin.
It is [fungible](https://web.getmonero.org/resources/moneropedia/fungibility.html) unlike Bitcoin, meaning each unit of currency is of equal value as the others.
This is achieved by keeping the ledger private.
Transactions are put out in the open like Bitcoin, but the details are encrypted.
This means there is no way to discriminate against a user based on their financial history.
Monero is private by default, but has the ability to reveal transactions at your discretion.
In the case of a business, it may be required to show the "books".
This is simple with a view key that can be used to show incoming transactions.
### Be your own bank
One of the advantages to using cryptocurrency is that you are your own bank.
As long as you hold your private keys, your funds are safe.
With today's computing power, you will be long gone before [your key is guessed](https://bitcoin.stackexchange.com/questions/2847/how-long-would-it-take-a-large-computer-to-crack-a-private-key).
Credit card companies and banks get [hacked](https://www.washingtonpost.com/national-security/capital-one-data-breach-compromises-tens-of-millions-of-credit-card-applications-fbi-says/2019/07/29/72114cc2-b243-11e9-8f6c-7828e68cb15f_story.html), and when they do the consequences are serious.
When you are your own bank, there is no middle man, and it is your responsibility to secure your finances.
As mentioned earlier, the Bitcoin network has not gone down in over a decade. Monero has a similar track record.
This 24/7 availability gives you 24/7 access.
### Conclusion
I think cryptocurrencies are the future of money.
They are superior to fiat in so many ways.
There are almost no barriers to entry; Essentially anyone with internet access can use crypto.
For myself and my company, this makes it very easy to be my own bank.
We will accept crypto because we believe it is only a matter of time before the world starts converting from fiat to it.
Our preference is Monero because we see it as technologically superior.

View File

@ -0,0 +1,10 @@
---
image: /favicon.ico
title: Simplicity
author: Jeff Russo
published: Dec 7, 2019
desc: What is a simple system?
---
A simple system is an encapsulation of complexity.
It presents to the user an uncomplicated interface.

View File

@ -0,0 +1,9 @@
<template>
<v-container fluid>
<v-row class="justify-center">
<v-col cols="12" md="11" lg="10" xl="8">
<slot/>
</v-col>
</v-row>
</v-container>
</template>

View File

@ -0,0 +1,19 @@
<template>
<v-footer height="auto" color="#333">
<v-container>
<v-row class="text-center align-center justify-center">
<v-col cols="12" sm="11" md="4" lg="4" xl="4">
<contact />
</v-col>
</v-row>
</v-container>
</v-footer>
</template>
<script>
import Contact from '@/components/Contact'
export default {
components: { Contact }
}
</script>

View File

@ -0,0 +1,38 @@
<template>
<v-card dark :color="$vuetify.theme.dark ? 'blue darken-4' : 'blue'">
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-card-title class="headline justify-center">
Contact Us
</v-card-title>
<v-card-text style="cursor: pointer;" v-on="on" @click="copyEmail">
<v-icon>mail_outline</v-icon>
{{ email }}
</v-card-text>
</template>
<span v-show="!emailCopied">Click to copy!</span>
<span v-show="emailCopied">Copied to clipboard!</span>
</v-tooltip>
</v-card>
</template>
<script>
export default {
data() {
return {
email: 'info@simplesystems.tech',
emailCopied: false,
}
},
methods: {
copyEmail() {
navigator.clipboard.writeText(this.email).then(() => {
this.emailCopied = true
})
}
},
}
</script>

View File

@ -0,0 +1,37 @@
---
title: Front End Engineer
icon: desktop_mac
desc: As a front end engineer, your mission is to create meaningful web interfaces. Youll work with project leaders and back end engineers to bring projects to life.
---
# Front End Engineer
---
### About the company
Simple Systems is a software company.
Our mission is to deliver simple solutions for complex problems.
### About the job
As a front end engineer, your mission is to create meaningful web interfaces.
Youll work with project leaders and back end engineers to bring projects to life.
### Expectations
* Work with project leaders to gain understanding of their vision
* Bring that vision to the web
* Work with backend engineers to connect services to the UI
* Own the code you write
* Review code from other front end engineers
* Suggest improvements throughout codebase
* Be open to suggestions for your code
### Competencies
* Ownership mentality: Take responsibility for what you do.
* Clear communication: Software engineering is a team process. Be able to communicate with teammates.
* Constant learning: Keep up to date on technologies.
* Lazy programming: Think before you code.
* Testing: Unit tests are a must. Testing logic is important too.
* Documentation: Other engineers should be able to pick up your code without hassle.
* Currently we use Vue.js, but are more concerned with fundamentals than specific technology.
### Interested?
Email a resume and brief description about yourself to jobs@simplesystems.tech.

17
src/main.js Normal file
View File

@ -0,0 +1,17 @@
import Vue from 'vue'
import router from './plugins/vue-router'
import vuetify from './plugins/vuetify'
import AppContainer from '@/components/AppContainer'
Vue.component('app-container', AppContainer)
import App from './App'
new Vue({
el: '#app',
render: h => h(App),
router,
vuetify,
})

21
src/pages/404.vue Normal file
View File

@ -0,0 +1,21 @@
<template>
<app-container>
<v-row class="text-center pt-12">
<v-col cols="12" class="pt-12">
<v-icon size="175" color="light-blue">help</v-icon>
</v-col>
<v-col cols="12" class="pt-12">
<h1 class="display-1 mb-6">Oops...</h1>
<p>The page you requested doesn't exist.</p>
<p>Please start again from the <router-link to="/">Home Page</router-link> and let us know if this happens again.</p>
<v-btn dark large color="light-blue" class="mt-12" to="/">
Go to Home Page
<v-icon right>arrow_forward</v-icon>
</v-btn>
</v-col>
</v-row>
</app-container>
</template>

71
src/pages/About.vue Normal file
View File

@ -0,0 +1,71 @@
<template>
<app-container>
<v-row>
<v-col cols="12" class="text-center">
<p class="headline">Our mission is to deliver simple solutions for complex problems.</p>
</v-col>
</v-row>
<v-row class="justify-center">
<v-col cols="12" lg="8">
<v-card dark>
<v-card-text class="about-quote">
<v-row class="align-center">
<v-col cols="auto">
<img src="/img/rocket-512.png" width="150">
</v-col>
<v-col class="text-center">
<p class="mb-0">Any darn fool can make something complex;<br>It takes a genius to make something simple.</p>
<br>
<p class="ml-5">-- Albert Einstein</p>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col>
<v-divider/>
</v-col>
</v-row>
<v-row class="justify-center">
<v-col cols="12" class="text-center">
<h1 class="display-1">The Team</h1>
</v-col>
<v-col cols="12" lg="9">
<v-card>
<v-container>
<v-row class="align-center">
<v-col cols="12" md="3" class="text-center">
<img src="/img/jeff-snow.jpg" />
</v-col>
<v-col cols="12" md="9">
<h1>Jeff</h1>
<p class="person_desc">My name is Jeff Russo. I am the founder of Simple Systems, LLC. I've been a software engineer for about a decade, and I'm still passionate about it!</p>
<p class="person_desc">I've worked at several companies in my career. Some were three man startup teams, and some were fortune 50 enterprises. At each job, I learned many things, and now I can apply that knowledge to my own company! I pursue excellence in all that I do, and this adventure will be no different.</p>
<p class="person_desc">The biggest thing I saw at all levels of business was unnecessary complexity. It demoralizes teams and can bring your software to a crashing halt. My mission is to deliver software that is simple, to both the business, and the engineers that have to use it.</p>
</v-col>
</v-row>
</v-container>
</v-card>
</v-col>
</v-row>
</app-container>
</template>
<style>
.about-quote, .person_desc {
font-size: large;
}
.person_desc {
text-indent: 2.0em;
text-align: justify;
text-justify: inter-word;
}
</style>

94
src/pages/Blog.vue Normal file
View File

@ -0,0 +1,94 @@
<template>
<app-container>
<v-row>
<v-col cols="12" sm="auto" class="d-flex">
<h1 class="display-2">Blog</h1>
<v-spacer />
<v-btn
v-if="$vuetify.breakpoint.xsOnly"
dark fab small
color="light-blue lighten-1"
@click="toggleMobileSearch"
class="elevation-2"
>
<v-icon>search</v-icon>
</v-btn>
</v-col>
<v-spacer />
<v-col cols="12" sm="auto">
<v-text-field
v-if="$vuetify.breakpoint.smAndUp"
v-model="searchText"
label="Search"
outlined
append-icon="search"
/>
</v-col>
</v-row>
<v-expand-transition>
<v-row v-show="$vuetify.breakpoint.xsOnly && showMobileSearch">
<v-col class="pt-0">
<v-text-field v-model="searchText" placeholder="Search" ref="mobileSearchField" single-line outlined />
</v-col>
</v-row>
</v-expand-transition>
<v-row class="justify-center">
<v-col v-for="(blogPost, i) in filteredPosts" :key="i" cols="12" sm="10" md="6" lg="5">
<router-link :to="'/blog/post/' + blogPost.key">
<v-card>
<v-card-title>
<v-row class="align-center">
<v-col cols="auto" class="mr-3"><img v-if="blogPost.image" :src="blogPost.image" width="64" height="64"></v-col>
<v-col class="title">{{ blogPost.title }}</v-col>
</v-row>
</v-card-title>
<v-divider />
<v-card-text>{{ blogPost.desc }}...</v-card-text>
</v-card>
</router-link>
</v-col>
</v-row>
</app-container>
</template>
<script>
import blogPosts from '@/assets/blogPosts'
export default {
data() {
return {
posts: blogPosts.map(bPost => {
return {
key: bPost.key,
...bPost.module.attributes,
}
}),
showMobileSearch: false,
searchText: '',
}
},
computed: {
filteredPosts() {
return this.posts.filter(post => {
return this.searchText === '' || post.title.toLowerCase().includes(this.searchText.toLowerCase()) || post.desc.toLowerCase().includes(this.searchText.toLowerCase())
})
},
},
methods: {
toggleMobileSearch() {
this.showMobileSearch = !this.showMobileSearch
this.$nextTick(() => this.$refs.mobileSearchField.focus())
},
},
}
</script>

37
src/pages/BlogPost.vue Normal file
View File

@ -0,0 +1,37 @@
<template>
<v-container style="max-width: 800px">
<v-row>
<v-col class="article">
<div class="d-flex align-center mt-6">
<img v-if="image" :src="image" width="88" height="88" class="mr-6">
<h1 class="headline">{{ title }}</h1>
</div>
<div class="mt-6 grey--text text--darken-1">
by <router-link to="/about">{{ author }}</router-link>
<span class="mx-2 headline font-weight-thin grey--text text--lighten-2">|</span>
{{ published }}
</div>
<v-divider class="my-6" />
<component :is="cmpnt" />
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
props: {
cmpnt: Object,
attrs: Object,
},
data() {
return {
...this.attrs,
}
},
}
</script>

121
src/pages/Home.vue Normal file
View File

@ -0,0 +1,121 @@
<template>
<section>
<v-container class="jumbotron" :style="jumbotronStyling" fluid>
<v-row class="justify-center">
<v-col cols="12" lg="10" xl="7">
<v-row class="align-center justify-center jumbotron-content">
<v-col v-show="$vuetify.breakpoint.lgAndUp" lg="6" class="heading text-center">
<span class="display-3">Simple</span><br class="mb-8">
<span class="display-3">Systems</span>
</v-col>
<v-col cols="12" sm="9" md="7" lg="6" class="text-center">
<v-card class="pa-2" dark>
<v-card-text>
<v-icon large>business</v-icon>
<p class="mb-0 headline">We build software that businesses understand and engineers want to use.</p>
</v-card-text>
<v-divider class="mb-3 mx-auto" style="width: 75%;"></v-divider>
<v-btn :color="$vuetify.theme.dark ? 'blue darken-4' : 'blue'" href="mailto:info@simplesystems.tech" target="_blank">
<v-icon color="white" class="mr-2" left size="24">mail_outline</v-icon>
Email us: info@simplesystems.tech
</v-btn>
</v-card>
</v-col>
</v-row>
</v-col>
</v-row>
</v-container>
<app-container class="text-center">
<v-row>
<v-col>
<h1 class="desc">Software Should be Simple</h1>
<v-divider class="mt-3 mx-auto" width="50%"/>
</v-col>
</v-row>
<v-row class="justify-center">
<v-col v-for="item in ssAttrs" :key="item.icon" cols="12" sm="8" md="6">
<v-card class="simpleAttr py-3" height="100%">
<img :src="item.icon" height="100" width="100" class="mt-3 mx-auto"/>
<v-card-title class="justify-center font-weight-bold">
{{ item.headline }}
</v-card-title>
<v-card-text class="attr_desc">
{{ item.desc }}
</v-card-text>
</v-card>
</v-col>
</v-row>
</app-container>
</section>
</template>
<script>
export default {
data() {
return {
ssAttrs: [
{
headline: 'Comprehensible Interaction',
icon: '/img/interact.png',
desc: 'The interface to software should be clear without surprises. Engineers working on the project should not be deciphering other engineers\' code. Documentation is implied as part of the system, enabling all users to understand the software package better.'
},
{
headline: 'Straightforward Modification',
icon: '/img/tools.png',
desc: 'Software should handle changes smoothly. Great software feels like it was designed for future changes. The documentation will instruct an engineer\'s strategy, removing ambiguity of how something works.'
},
{
headline: 'Robust',
icon: '/img/robust.png',
desc: 'Load spikes, accidental misuse, and business growth should not bring software crashing to the ground. Systems should be designed to handle faults gracefully. If there are errors, they should be reported clearly.'
},
{
headline: 'Leveraged by Other Systems',
icon: '/img/leverage.png',
desc: 'When software simply does its job, and does it well, it will be an asset to other systems. When software becomes convoluted, it will hinder other systems.'
}
]
}
},
computed: {
jumbotronStyling() {
const gradientTop = (this.$vuetify.theme.dark) ? 'rgba(15, 15, 15, 0.55)' : 'rgba(25, 25, 25, 0.25)'
const gradientBot = (this.$vuetify.theme.dark) ? 'rgba(48, 48, 48, 0.75)' : 'rgba(250, 250, 250, 0.75)'
return {
background: 'linear-gradient(to bottom, ' + gradientTop + ', ' + gradientBot + '), url(/img/background-gray.png) center center no-repeat',
}
},
},
}
</script>
<style>
.jumbotron {
padding-top: 7rem;
padding-bottom: 7rem;
}
.jumbotron-content {
padding-top: 1rem;
padding-bottom: 1rem;
}
.simpleAttr {
display: flex;
flex-direction: column;
text-align: justify;
text-justify: inter-word;
}
@media (max-width: 1263px) {
.jumbotron {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
}
</style>

9
src/pages/JobPost.vue Normal file
View File

@ -0,0 +1,9 @@
<template>
<v-container style="max-width: 800px">
<v-row>
<v-col class="article">
<router-view />
</v-col>
</v-row>
</v-container>
</template>

57
src/pages/Jobs.vue Normal file
View File

@ -0,0 +1,57 @@
<template>
<app-container>
<v-row class="text-center mb-8">
<v-col>
<h1 class="display-2">Jobs</h1>
</v-col>
</v-row>
<v-row v-if="jobs === null || jobs.length <= 0" class="text-center">
<v-col>
No job openings at this time, but we are always open to starting a conversation. Email us at <a href="mailto:jobs@simplesystems.tech">jobs@simplesystems.tech</a>
</v-col>
</v-row>
<v-row v-else>
<v-col v-for="(j, i) in jobs" :key="i" cols="12" md="6">
<router-link :to="'/job/' + j.key">
<v-card>
<v-card-title class="grey" :class="$vuetify.theme.dark ? 'darken-2' : 'lighten-5'">
<v-icon class="mr-3">{{ j.icon }}</v-icon>
{{ j.title }}
</v-card-title>
<v-divider />
<v-card-text>{{ j.desc }}</v-card-text>
</v-card>
</router-link>
</v-col>
</v-row>
</app-container>
</template>
<script>
import jobKeys from '@/assets/jobKeys'
export default {
data() {
return {
jobs: [],
}
},
created() {
Promise.all(
jobKeys.map(async jobKey => {
return {
key: jobKey,
...await import('@/job-posts/' + jobKey + '.md').then(md => md.attributes)
}
})
).then(data => {
this.jobs = data
})
},
}
</script>

85
src/pages/Services.vue Normal file
View File

@ -0,0 +1,85 @@
<template>
<app-container>
<v-row>
<v-col cols="12" class="text-center">
<h1 class="display-2">What We Do</h1>
</v-col>
</v-row>
<v-row class="justify-center">
<v-col v-for="serv in services" :key="serv.name" class="pa-3" cols="12" sm="8" md="6">
<v-card class="service-card pt-3">
<v-card-title>
<img :src="serv.img" width="80" height="80" class="mr-4" />
<span class="headline font-weight-bold">{{ serv.name }}</span>
</v-card-title>
<v-card-text>
<p v-for="d in serv.desc" class="service_desc">{{ d }}</p>
</v-card-text>
</v-card>
</v-col>
</v-row>
</app-container>
</template>
<script>
export default {
data() {
return {
services: [
{
name: 'Software',
img: '/img/monitor.png',
desc: [
'We are passionate about creating software to solve problems. We have experience in a broad range of software environments including web, database, machine automation, and backend services.',
'Simple Systems can consult with you on a comprehensive solution that fits your business needs. Our process is flexible and will be tuned to the problem we\'re solving. Once the system is complete, we can deliver it, or manage it for you.'
]
},
{
name: 'Websites',
img: '/img/website.png',
desc: [
'Every business needs a web presence. It is one of the most effective ways to drive customers to your business.',
'It can be a deterrent if it is not high quality though! Over half of users will abandon your site if it does not load in under 3 seconds. It is crucial that the website displays quickly and looks good.',
'Simple Systems can improve your prospective clients\' experience by building a website from scratch, or cleaning up the existing one. We can handle all the hosting for you too!'
]
},
{
name: 'Data Management',
img: '/img/database.png',
desc: [
'The manner in which you store your data will affect business performance. If it is unorganized, accessing it can be slow. This can impair future upgrades and additions to your application. Make sure your data is organized and, most importantly, secured.',
'Storage systems are evolving all the time, and moving to a new one may save a lot of money. Data migrations are tricky, and can lose data if done incorrectly. It is important to have a documented process and verification everything worked.',
'Simple Systems can pick the right type of database for your needs, design it, and deploy it. After it is deployed and tested, we can maintain it as your data needs change. We can also work with you to increase the performance of your current solution, or migrate it to something better.'
]
},
{
name: 'Engineering Discipline',
img: '/img/checklist.png',
desc: [
'Sometimes it is important to move fast and get features done quickly. This mode of operation will build technical debt that must eventually be paid. Code will become fragile and unmanageable. The epitome of this development pace is rewriting a project from scratch because it has become cheaper to do so than maintain.',
'Disciplined engineers do not let this happen. They are patient, calculating, and write code deliberately. This will allow features to be released faster in the future.',
'Simple Systems can help guide your team on these practices. We have the experience of small startups all the way to fortune 50 companies.'
]
}
]
}
}
}
</script>
<style>
.service-card {
display: flex;
flex-direction: column;
height: 100%;
}
.service_desc {
text-indent: 2.0em;
font-size: medium;
text-align: justify;
text-justify: inter-word;
}
</style>

50
src/plugins/vue-router.js Normal file
View File

@ -0,0 +1,50 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import BlogPost from '@/pages/BlogPost'
import blogPosts from '@/assets/blogPosts'
const blogRoutes = blogPosts.map(bPost => {
return {
path: '/blog/post/' + bPost.key,
component: BlogPost,
props: {
cmpnt: bPost.module.vue.component,
attrs: bPost.module.attributes,
},
}
})
import jobKeys from '@/assets/jobKeys'
const childJobRoutes = [
...jobKeys.map(jobKey => {
return {
path: jobKey,
component: require('@/job-posts/' + jobKey + '.md').vue.component,
}
}),
// Redirect `/job` to the `/jobs` page.
{ path: '', redirect: '/jobs' },
]
export default new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: () => import('@/pages/Home') },
{ path: '/services', component: () => import('@/pages/Services') },
{ path: '/about', component: () => import('@/pages/About') },
{ path: '/blog', component: () => import('@/pages/Blog') },
...blogRoutes,
{ path: '/jobs', component: () => import('@/pages/Jobs') },
{ path: '/job', component: () => import('@/pages/JobPost'), children: childJobRoutes },
{ path: '*', component: () => import('@/pages/404.vue') }
],
scrollBehavior(to, from, savedPosition) {
return { x: 0, y: 0 }
},
})

48
src/plugins/vuetify.js Normal file
View File

@ -0,0 +1,48 @@
import Vue from 'vue'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import Vuetify, {
VApp, VAppBar, VContent, VNavigationDrawer, VToolbar, VFooter,
VContainer, VRow, VCol,
VCard, VCardTitle, VCardText, VCardActions,
VDialog,
VExpansionPanels, VExpansionPanel, VExpansionPanelHeader, VExpansionPanelContent,
VBtn, VChip, VIcon,
VDivider, VSpacer,
VOverlay, VTooltip,
VList, VListItem, VListItemContent, VListItemTitle, VListItemAction,
VTextField,
VExpandTransition,
} from 'vuetify/lib'
import { Intersect, Ripple } from 'vuetify/lib/directives'
Vue.use(Vuetify, {
components: {
VApp, VAppBar, VContent, VNavigationDrawer, VToolbar, VFooter,
VContainer, VRow, VCol,
VCard, VCardTitle, VCardText, VCardActions,
VDialog,
VExpansionPanels, VExpansionPanel, VExpansionPanelHeader, VExpansionPanelContent,
VBtn, VChip, VIcon,
VDivider, VSpacer,
VOverlay, VTooltip,
VList, VListItem, VListItemContent, VListItemTitle, VListItemAction,
VTextField,
VExpandTransition,
},
directives: {
Intersect,
Ripple,
},
})
export default new Vuetify({
icons: {
iconfont: 'md',
},
theme: {
dark: false,
},
})

13
vue.config.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
chainWebpack: config => {
config.module
.rule('md')
.test(/\.md$/)
.use('frontmatter-markdown-loader')
.loader('frontmatter-markdown-loader')
.tap(args => ({
mode: [ "vue-component" ],
}))
.end()
}
}

6828
yarn.lock Normal file

File diff suppressed because it is too large Load Diff