Browse Source

Created an MVP for an in browser webpage generator

This handles the rough architecture to stitch together a fully
standalone webpage that can be download, customized, and uploaded to any
host that can serve static files.
main
Tyler Childs 2 years ago
parent
commit
67f9e1ccde
  1. 28
      config.json
  2. 92
      default.html
  3. 321
      engine/bases/cutestrap.css
  4. 4
      engine/bases/default.css
  5. 349
      engine/bases/normalize.css
  6. 48
      engine/bases/reset.css
  7. 34
      engine/boilerplates/default.html
  8. 0
      engine/layouts/default.css
  9. 24
      engine/layouts/landing.css
  10. 31
      engine/layouts/sidebar.css
  11. 0
      engine/null.txt
  12. 0
      engine/palettes/default.css
  13. 22
      engine/skins/dark.css
  14. 0
      engine/skins/default.css
  15. 3
      engine/skins/foobar.css
  16. 14
      engine/skins/legalpad.css
  17. 20
      engine/templates/about.html
  18. 47
      engine/templates/default.html
  19. 239
      index.html
  20. 33
      options.json

28
config.json

@ -0,0 +1,28 @@
{
"title": "Hello World",
"header": "<h1>Untitled</h1>",
"footer": "This generated code is licensed under the MIT License. That basically means you're free to do whatever you'd like with it, enjoy!",
"navigation": [
{
"title": "About",
"href": "#about"
},
{
"title": "Features",
"href": "#features"
},
{
"title": "Contact",
"href": "#contact"
}
],
"boilerplate": "/engine/boilerplates/default.html",
"base": "/engine/bases/default.css",
"palette": "/engine/palettes/default.css",
"layout": "/engine/layouts/default.css",
"skin": "/engine/skins/default.css",
"template": "/engine/templates/default.html",
"embed": true,
"styles": [],
"scripts": []
}

92
default.html

@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Hello World</title>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-touch-fullscreen" content="yes">
<style>* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<header id="header">
<h1>Untitled</h1>
</header>
<aside id="aside">
<nav><a href="#about">About</a><a href="#features">Features</a><a href="#contact">Contact</a></nav>
</aside>
<main id="main">
<a name="about"></a>
<h2>About</h2>
<p>
This is a fully standalone webpage that was dynamically generated. You
can right-click anywhere and select "Save as..." or "Save Page As..."
to download it. To showcase your webpage to anyone else online, you'll
need to find a hosting provider.
</p>
<p>
The source code of this webpage can be changed with a plain text editor.
</p>
<a name="features"></a>
<h2>Features</h2>
<p>
This webpage was designed to be mixed and matched with compatible configurations, kind of like ordering a burrito.
</p>
<h3>Configurations</h3>
<dl>
<dt>Boilerplate</dt>
<dd>The general skeleton of the webpage. Most pages on any given site should share the same boilerplate for consistency.</dd>
<dt>Base</dt>
<dd>The underlying design principles for the webpage. The details are subtle, but provide a certain natural polish to all content.</dd>
<dt>Palette</dt>
<dd>All of the available colors to use for the page's design.</dd>
<dt>Layout</dt>
<dd>The general structure and design of a webpage. This also is responsible to mediate the design between the palette and the skin.</dd>
<dt>Skin</dt>
<dd>The opinionated preference for each design element. The same palette can be used to generate a variety of skins.</dd>
<dt>Template</dt>
<dd>Example content or feature that is unique to a given webpage. This
could be anything from a wall of text to a fully functional photo
gallery.</dd>
</dl>
<a name="contact"></a>
<h2>Contact</h2>
<p>
To stay up to date with the latest updates, please consider subscribing to the <a href="https://css.ceo/rss.xml">RSS Feed</a> or by <a href="mailto:list@css.ceo?subject=Request+to+join+mailing+list&amp;body=Please+subscribe+me">joining the mailing list</a>
</p>
<p>
For any additional questions, please reach out to <a href="mailto:support@css.ceo?subject=Support+Question&amp;body=I+have+a+question+about+...">Support</a>. As this is a volunteer project, it may take time to respond, but serious inquiries will eventually receive a response.
</p>
</main>
<footer id="footer">
This generated code is licensed under the MIT License. That
basically means you're free to do whatever you'd like with it, enjoy!
</footer>
</body></html>

321
engine/bases/cutestrap.css

@ -0,0 +1,321 @@
html {
--border-radius: 4px;
--color-primary-tint1: hsl(350, 80%, 60%);
--color-primary: hsl(350, 80%, 45%);
--color-primary-shade1: hsl(350, 80%, 35%);
--color-accent-tint1: hsl(170, 80%, 60%);
--color-accent: hsl(170, 80%, 45%);
--color-accent-shade1: hsl(170, 80%, 35%);
--color-link: hsl(230, 60%, 50%);
--color-link-visited: hsl(290, 60%, 50%);
--color-link-hover: hsl(230, 80%, 60%);
--color-link-active: hsl(350, 60%, 50%);
--color-neutral-tint4: hsl(170, 10%, 98%);
--color-neutral-tint3: hsl(170, 10%, 94%);
--color-neutral-tint2: hsl(170, 10%, 85%);
--color-neutral-tint1: hsl(170, 10%, 68%);
--color-neutral: hsl(170, 10%, 55%);
--color-neutral-shade1: hsl(170, 10%, 41%);
--color-neutral-shade2: hsl(170, 10%, 30%);
--color-neutral-shade3: hsl(170, 10%, 18%);
--color-neutral-shade4: hsl(170, 10%, 2%);
--focus-outline: .1rem dotted var(--color-primary-tint1);
--focus-outline-offset: .1rem;
--font-family: 'Avenir', 'Avenir Next', 'Helvetica Neue', 'Segoe UI', 'Verdana', sans-serif;
--font-mono: 'Consolas', 'Monaco', 'Courier New', monospace;
--font-heading: var(--font-family);
--font-body: var(--font-family);
}
body {
font-size: 1.5rem;
line-height: 2rem;
}
* {
border: 0;
font: inherit;
margin: 0;
padding: 0;
text-rendering: geometricPrecision;
}
:focus {
outline: var(--focus-outline);
outline-offset: var(--focus-outline-offset);
}
html {
overflow-x: hidden;
}
html,
body {
box-sizing: border-box;
min-height: 100%;
}
body {
background-color: var(--color-neutral-tint4);
color: var(--color-neutral-shade4);
font-family: var(--font-body);
position: relative;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-heading);
margin: 2rem 0;
}
h1 {
font-size: 4rem;
font-weight: 700;
line-height: 6rem;
margin-bottom: 2rem;
}
h2 {
font-size: 3rem;
line-height: 5rem;
}
h3 {
font-size: 2.5rem;
font-weight: 700;
line-height: 3rem;
}
h4 {
font-size: 2rem;
font-weight: 700;
}
h5 {
font-weight: 700;
}
p {
margin-bottom: 2rem;
}
form {
margin: 2rem 0;
}
pre,
code,
samp,
kbd {
background-color: var(--color-neutral-tint3);
font-size: var(--font-size);
color: var(--color-primary-shade1);
font-family: var(--font-mono);
line-height: 1;
}
code,
samp,
kbd {
border-radius: var(--border-radius);
overflow-y: hidden;
overflow-x: auto;
padding: .5rem;
}
pre {
border-radius: var(--border-radius);
line-height: var(--line-height);
overflow-y: hidden;
overflow-x: auto;
padding: 1rem;
margin: 0 0 2rem;
}
pre code,
pre samp,
pre kbd {
background-color: transparent;
border: none;
border-radius: 0;
padding: 0;
}
a:link {
color: var(--color-link);
}
a:visited {
color: var(--color-link-visited);
}
a:hover,
a:focus {
color: var(--color-link-hover);
}
a:active {
color: var(--color-link-active);
}
img,
video {
max-width: 100%;
vertical-align: top;
}
hr {
height: 4rem;
margin-bottom: 2rem;
position: relative;
}
hr::before {
background-color: var(--color-neutral-tint1);
content: '';
height: 1px;
left: 0;
position: absolute;
top: 50%;
width: 100%;
}
ol,
ul {
margin: 0 0 2rem 2rem;
}
ol {
list-style-type: decimal;
}
ol ol {
margin-bottom: 0;
}
ul {
list-style-type: disc;
}
ul ul {
margin-bottom: 0;
}
dt {
font-style: italic;
}
dd {
margin-left: 2rem;
}
blockquote {
margin: 0 0 2rem 1rem;
border-left: .25rem solid var(--color-neutral-tint1);
padding: 2rem 1rem;
}
blockquote p:last-child {
margin-bottom: 0;
}
figure {
margin: 0 auto 2rem;
}
small,
sub,
sup,
caption,
figcaption {
font-size: 1.5rem;
vertical-align: top;
}
sub,
sup {
position: relative;
}
sub {
top: 1.5rem;
}
sup {
bottom: 1.5rem;
}
caption,
figcaption {
font-style: italic;
text-align: center;
}
em,
cite,
i {
font-style: italic;
}
strong,
var,
b {
font-weight: bold;
}
q::before {
content: "'";
}
q::after {
content: "'";
}
q > q {
font-style: italic;
}
dfn,
abbr {
border-bottom: .1rem dotted var(--color-neutral-shade2);
cursor: default;
}
table {
border-radius: var(--border-radius);
border-collapse: separate;
border-spacing: 0;
margin-bottom: 2rem;
width: 100%;
}
table th {
text-align: left;
}
table th,
table td {
padding: 0 .5rem;
}
input,
label,
select,
button,
textarea {
color: var(--color-neutral-shade4);
display: block;
padding: 1rem;
resize: none;
-webkit-appearance: none;
-moz-appearance: none;
}
label {
color: var(--color-neutral-shade1);
padding: 0;
}

4
engine/bases/default.css

@ -0,0 +1,4 @@
* {
margin: 0;
padding: 0;
}

349
engine/bases/normalize.css

@ -0,0 +1,349 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

48
engine/bases/reset.css

@ -0,0 +1,48 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

34
engine/boilerplates/default.html

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title><!--title--></title>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-touch-fullscreen" content="yes">
<!--styles-->
</head>
<body>
<header id="header">
<!--header-->
</header>
<aside id="aside">
<!--aside-->
</aside>
<main id="main">
<!--main-->
</main>
<footer id="footer">
<!--footer-->
</footer>
<!--scripts-->
</body>
</html>

0
engine/layouts/default.css

24
engine/layouts/landing.css

@ -0,0 +1,24 @@
body{
padding: var(--rhythm) var(--rhythm-half);
margin: 0 auto;
max-width: 65rem;
}
.header {
text-align: center;
}
.navigation {
text-align: center;
}
.navigation ul {
display: flex;
list-style-type: none;
margin-left: 0;
justify-content: center;
}
.navigation li {
padding: 0 var(--rhythm-half);
}

31
engine/layouts/sidebar.css

@ -0,0 +1,31 @@
body {
display: grid;
grid-template-areas:
"header header"
"aside main"
"footer footer";
grid-template-columns: 10em 1fr;
}
#header {
grid-area: header;
padding: 0 var(--rhythm-half);
}
#aside {
grid-area: aside;
padding: var(--rhythm-double) var(--rhythm-half) var(--rhythm);
}
#main {
grid-area: main;
min-width: 0;
padding: 0 var(--rhythm-half);
}
#footer {
grid-area: footer;
min-width: 0;
padding: var(--rhythm);
}

0
engine/null.txt

0
engine/palettes/default.css

22
engine/skins/dark.css

@ -0,0 +1,22 @@
html {
--color-primary-shade1: hsl(350, 80%, 60%);
--color-primary: hsl(350, 80%, 45%);
--color-primary-tint1: hsl(350, 80%, 35%);
--color-accent-shade1: hsl(170, 80%, 60%);
--color-accent: hsl(170, 80%, 45%);
--color-accent-tint1: hsl(170, 80%, 35%);
--color-link: hsl(230, 80%, 60%);
--color-link-visited: hsl(290, 80%, 60%);
--color-link-hover: hsl(230, 60%, 50%);
--color-link-active: hsl(350, 60%, 50%);
--color-neutral-shade4: hsl(170, 10%, 98%);
--color-neutral-shade3: hsl(170, 10%, 94%);
--color-neutral-shade2: hsl(170, 10%, 85%);
--color-neutral-shade1: hsl(170, 10%, 68%);
--color-neutral: hsl(170, 10%, 55%);
--color-neutral-tint1: hsl(170, 10%, 41%);
--color-neutral-tint2: hsl(170, 10%, 30%);
--color-neutral-tint3: hsl(170, 10%, 18%);
--color-neutral-tint4: hsl(170, 10%, 2%);
}

0
engine/skins/default.css

3
engine/skins/foobar.css

@ -0,0 +1,3 @@
body {
background-color: red;
}

14
engine/skins/legalpad.css

@ -0,0 +1,14 @@
html {
--color-primary-shade1: hsl(200, 80%, 60%);
--color-primary: hsl(200, 80%, 45%);
--color-primary-tint1: hsl(200, 80%, 35%);
--color-accent-shade1: hsl(50, 80%, 60%);
--color-accent: hsl(50, 80%, 45%);
--color-accent-tint1: hsl(50, 80%, 35%);
}
body {
background: hsl(50, 50%, 90%);
color: hsl(200, 50%, 10%);
}

20
engine/templates/about.html

@ -0,0 +1,20 @@
<h2>About</h2>
<p>
When using a CSS Framework, it's really easy to make your website look identical to every other website that uses that framework.
</p>
<p>
Cutestrap aims to provide simple ways to leverage the framework, compared to fighting it, to achieve your design requirements.
</p>
<p>
The Customizer quickly gives you a boilerplate with:
</p>
<ul>
<li>Theme</li>
<li>Layout</li>
<li>Baseline Grid</li>
<li>Line Height</li>
</ul>
<p>
Layouts are not actually part of Cutestrap because they will likely be the most unique part of your design. CSS Grid is very powerful and the Customizer highlights how the same markup can be used in conjunction with CSS Grid and Cutestrap to give your website flexibility when you need to redesign.
</p>

47
engine/templates/default.html

@ -0,0 +1,47 @@
<a name="about"></a>
<h2>About</h2>
<p>
This is a fully standalone webpage that was dynamically generated. You can right-click anywhere and select "Save as..." or "Save Page As..." to download it. To showcase your webpage to anyone else online, you'll need to find a hosting provider.
</p>
<p>
The source code of this webpage can be changed with a plain text editor.
</p>
<a name="features"></a>
<h2>Features</h2>
<p>
This webpage was designed to be mixed and matched with compatible configurations, kind of like ordering a burrito.
</p>
<h3>Configurations</h3>
<dl>
<dt>Boilerplate</dt>
<dd>The general skeleton of the webpage. Most pages on any given site should share the same boilerplate for consistency.</dd>
<dt>Base</dt>
<dd>The underlying design principles for the webpage. The details are subtle, but provide a certain natural polish to all content.</dd>
<dt>Palette</dt>
<dd>All of the available colors to use for the page's design.</dd>
<dt>Layout</dt>
<dd>The general structure and design of a webpage. This also is responsible to mediate the design between the palette and the skin.</dd>
<dt>Skin</dt>
<dd>The opinionated preference for each design element. The same palette can be used to generate a variety of skins.</dd>
<dt>Template</dt>
<dd>Example content or feature that is unique to a given webpage. This could be anything from a wall of text to a fully functional photo gallery.</dd>
</dl>
<a name="contact"></a>
<h2>Contact</h2>
<p>
To stay up to date with the latest updates, please consider subscribing to the <a href="https://css.ceo/rss.xml">RSS Feed</a> or by <a href="mailto:list@css.ceo?subject=Request+to+join+mailing+list&body=Please+subscribe+me">joining the mailing list</a>
</p>
<p>
For any additional questions, please reach out to <a href="mailto:support@css.ceo?subject=Support+Question&body=I+have+a+question+about+...">Support</a>. As this is a volunteer project, it may take time to respond, but serious inquiries will eventually receive a response.
</p>

239
index.html

@ -1,24 +1,231 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>The Office of the Chief Exective Officer of Cascading Style Sheets</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Need a webpage?</title>
<meta name="description" content="A configurable webpage generator to quickly bootstrap your online presence">
<link rel="stylesheet" href="/engine/bases/default.css" />
<style>
body {
text-align: center;
}
form {
display: grid;
grid-template-columns: auto 1fr;
gap: 1rem;
padding: 2rem;
margin: 0 auto;
max-width: 600px;
}
form label {
text-align: right;
}
.button {
display: inline-block;
padding: 1rem;
border: 1px solid blue;
border-radius: 4px;
font-weight: bold;
margin: 1rem;
text-decoration: none;
transition: all 250ms ease-in-out;
}
.button:hover,
.button:focus {
color: white;
background: blue;
}
</style>
</head>
<body>
<h1>The CEO of CSS</h1>
<img src="https://www.fillmurray.com/600/800" alt="Picture of Bill Murray until I select a mugshot of myself" />
<p>
Beginning with MySpace in 2004, the CEO began his curious journey of customizing the web. In 2008, he published his first website, <a href="https://tylerchilds.com">tylerchilds.com</a>. He rode the wave of Web 2.0 to land a gig at Netflix in 2018. Through his more than half decade in Silicon Valley, he discovered what we've all assumed all along, big tech doesn't actually care about us.
</p>
<p>
With a looming presidential election and a global pandemic, he found himself virtually surrounded by a bunch of downers. This led him to begin quitting GAFAM, aka the PRISM crew, and find people that believe in a brighter future. In this better world, you can find his personal interests at <a href="https://tychi.com">tychi.me</a>, where his words and actions do not reflect the opinions or matters of the CEO.
</p>
<h2>About this site</h2>
<p>
By 2030, this website will be my primary source of income. It will only ever be a static, hand-crafted web experience that will serve as a juxtapostion to the over-engineered technological catastrophes that will become the bane of your existence before too long. By following along with the progression of this site, hopefully you'll be inspired and see a path to create a better world of your own.
</p>
<header id="header">
<h1>Webpage Generator</h1>
</header>
<aside id="aside">
</aside>
<main id="main">
<noscript>
Out of respect for your preferences, the engine has pre-compiled an example output file based on the default configuration options. To unlock the full customization engine, you'll need to enable JavaScript.
<br/><br/>
If you'd first like to peruse the source code for this website, it's <a href="http://git.tychi.com/tychi/css-ceo">available in full here</a>. You can also view-source, since nothing is minified or obfuscated.
</noscript>
<fieldset>
<legend>Customization Options</legend>
<form id="customization-form">
<label for="boilerplate">
Boilerplate
</label>
<select id="boilerplate">
<option selected="selected" value="/engine/boilerplates/default.html">
Default
</option>
</select>
<label for="base">
Base
</label>
<select id="base">
<option selected="selected" value="/engine/bases/default.css">
Default
</option>
</select>
<label for="palette">
Palette
</label>
<select id="palette">
<option selected="selected" value="/engine/palettes/default.css">
Default
</option>
</select>
<label for="layout">
Layout
</label>
<select id="layout">
<option selected="selected" value="/engine/layouts/default.css">
Default
</option>
</select>
<label for="skin">
Skin
</label>
<select id="skin">
<option selected="selected" value="/engine/skins/default.css">
Default
</option>
</select>
<label for="template">
Template
</label>
<select id="template">
<option selected="selected" value="/engine/templates/default.html">
Default
</option>
</select>
</form>
</fieldset>
<a class="button" href="/default.html" id="customizer-demo">
Preview
</a>
</main>
<footer id="footer">
</footer>
<script>
(function() {
let config = {};
init();
async function download(url) {
return await fetch(url)
.then(r => r.status < 300 ? r.text() : '' )
.catch(console.error);
}
async function init() {
config = JSON.parse(await download('/config.json'));
const options = JSON.parse(await download('/options.json'));
const inputs = [...document.querySelectorAll('select, input')];
inputs.map(el => {
options[el.id].forEach(option => {
const node = document.createElement('option');
node.value = option.value;
node.innerText = option.label;
el.appendChild(node);
});
el.addEventListener('change', updateConfig)
el.addEventListener('change', render)
});
const fields = inputs.filter(el => Object.keys(config).includes(el.id));
render();
}
function updateConfig(el) {
config[el.target.id] = el.target.value;
}
async function render() {
const boilerplate = download(config.boilerplate);
const base = download(config.base);
const palette = download(config.palette);
const layout = download(config.layout);
const skin = download(config.skin);
const template = download(config.template);
const webpage = await Promise.all([
boilerplate,
base,
palette,
layout,
skin,
template
]).then(composeWebpage);
const blob = new Blob([webpage], { type: 'text/html' });
document.getElementById('customizer-demo').href = URL.createObjectURL(blob);
}
function composeWebpage(
[
boilerplate,
base,
palette,
layout,
skin,
template
] = promises
) {
const slugs = {
title: config.title,
styles: ((a, b, c, d, styles) => {
const external = '';
return `<style>${a}${b}${c}${d}</style>${external}`;
})(base, palette, layout, skin, config.styles),
header: config.header,
aside: ((items) => {
const list = items.reduce((nav, item) => {
return `${nav}<a href=${item.href}>${item.title}</a>`;
}, '');
return `<nav>${list}</nav>`
})(config.navigation),
main: template,
footer: config.footer,
scripts: ((scripts) => {
return '';
})(config.scripts),
};
return Object.keys(slugs).reduce((page, key) => {
return page.replace(`<!--${key}-->`, slugs[key]);
}, boilerplate);
}
})();
</script>
</body>
</html>

33
options.json

@ -0,0 +1,33 @@
{
"boilerplate": [],
"base": [
{
"value": "/engine/bases/reset.css",
"label": "reset.css"
},
{
"value": "/engine/bases/cutestrap.css",
"label": "cutestrap.css"
},
{
"value": "/engine/bases/normalize.css",
"label": "normalize.css"
}
],
"palette": [
],
"layout": [
{
"value": "/engine/layouts/landing.css",
"label": "Landing"
},
{
"value": "/engine/layouts/sidebar.css",
"label": "Sidebar"
}
],
"skin": [
],
"template": [
]
}
Loading…
Cancel
Save