@bivabdas/sharq 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/sharq.js +4 -2
- package/lib/config.js +4 -0
- package/lib/generator.js +3 -0
- package/lib/renderer.js +1 -1
- package/lib/scaffold.js +6 -1
- package/lib/server.js +11 -0
- package/lib/styles.js +75 -0
- package/package.json +30 -24
- package/scaffold/template/public/assets/overrides.css +38 -0
- package/scaffold/template/public/assets/site.css +22 -208
- package/scaffold/template/styles/site.css +5 -0
- package/scaffold/template/templates/archive.html +6 -10
- package/scaffold/template/templates/index.html +10 -13
- package/scaffold/template/templates/post.html +10 -11
package/bin/sharq.js
CHANGED
|
@@ -29,13 +29,15 @@ Usage:
|
|
|
29
29
|
|
|
30
30
|
Commands:
|
|
31
31
|
start Start the local sharq server
|
|
32
|
-
dev
|
|
32
|
+
dev Start the local sharq server with Tailwind watching enabled
|
|
33
33
|
build Generate a deployable static site in ./sharq
|
|
34
34
|
create Scaffold a new sharq site
|
|
35
35
|
`);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
if (!command || command === "dev"
|
|
38
|
+
if (!command || command === "dev") {
|
|
39
|
+
await startServer({ watchStyles: true });
|
|
40
|
+
} else if (command === "start") {
|
|
39
41
|
await startServer();
|
|
40
42
|
} else if (command === "build") {
|
|
41
43
|
const config = await resolveConfig();
|
package/lib/config.js
CHANGED
|
@@ -13,6 +13,7 @@ export function createConfig(rootDir, overrides = {}) {
|
|
|
13
13
|
overrides.siteDescription || "A tiny publishing surface that renders posts from Markdown and serves static HTML.",
|
|
14
14
|
buildDirName,
|
|
15
15
|
contentDir: path.join(rootDir, "content"),
|
|
16
|
+
stylesDir: path.join(rootDir, "styles"),
|
|
16
17
|
templatesDir: path.join(rootDir, "templates"),
|
|
17
18
|
publicDir: path.join(rootDir, "public"),
|
|
18
19
|
blogOutputDir: path.join(rootDir, "public", "blog"),
|
|
@@ -20,6 +21,9 @@ export function createConfig(rootDir, overrides = {}) {
|
|
|
20
21
|
homePagePath: path.join(rootDir, "public", "index.html"),
|
|
21
22
|
archivePagePath: path.join(rootDir, "public", "archive.html"),
|
|
22
23
|
staticAssetsDir: path.join(rootDir, "public", "assets"),
|
|
24
|
+
tailwindInputPath: path.join(rootDir, "styles", "site.css"),
|
|
25
|
+
tailwindOutputPath: path.join(rootDir, "public", "assets", "site.css"),
|
|
26
|
+
overridesCssPath: path.join(rootDir, "public", "assets", "overrides.css"),
|
|
23
27
|
buildDir: path.join(rootDir, buildDirName)
|
|
24
28
|
};
|
|
25
29
|
}
|
package/lib/generator.js
CHANGED
|
@@ -2,10 +2,12 @@ import fs from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { generateSitemap } from "./sitemap.js";
|
|
4
4
|
import { readPostSource, renderArchivePage, renderIndexPage, renderPostPage } from "./renderer.js";
|
|
5
|
+
import { compileTailwind } from "./styles.js";
|
|
5
6
|
|
|
6
7
|
async function ensureDirectories(config) {
|
|
7
8
|
await Promise.all([
|
|
8
9
|
fs.mkdir(config.contentDir, { recursive: true }),
|
|
10
|
+
fs.mkdir(config.stylesDir, { recursive: true }),
|
|
9
11
|
fs.mkdir(config.publicDir, { recursive: true }),
|
|
10
12
|
fs.mkdir(config.blogOutputDir, { recursive: true }),
|
|
11
13
|
fs.mkdir(config.templatesDir, { recursive: true }),
|
|
@@ -121,6 +123,7 @@ function createOutputConfig(config, outputDir) {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
export async function buildStaticSite(config, outputDir = config.buildDir) {
|
|
126
|
+
await compileTailwind(config, { minify: true });
|
|
124
127
|
const outputConfig = createOutputConfig(config, outputDir);
|
|
125
128
|
|
|
126
129
|
await fs.rm(outputDir, { recursive: true, force: true });
|
package/lib/renderer.js
CHANGED
|
@@ -228,7 +228,7 @@ export async function renderPostPage(config, post) {
|
|
|
228
228
|
.join("");
|
|
229
229
|
|
|
230
230
|
return applyTemplate(template, {
|
|
231
|
-
title: escapeHtml(post.title),
|
|
231
|
+
title: escapeHtml(`${post.title} | ${config.siteTitle}`),
|
|
232
232
|
description: escapeHtml(post.description),
|
|
233
233
|
date: escapeHtml(post.date),
|
|
234
234
|
author: escapeHtml(post.author || "sharq"),
|
package/lib/scaffold.js
CHANGED
|
@@ -77,6 +77,10 @@ async function writePackageJson(projectDir, projectName, frameworkPackageName, f
|
|
|
77
77
|
},
|
|
78
78
|
dependencies: {
|
|
79
79
|
[frameworkPackageName]: frameworkDependency
|
|
80
|
+
},
|
|
81
|
+
devDependencies: {
|
|
82
|
+
tailwindcss: "^4.0.0",
|
|
83
|
+
"@tailwindcss/cli": "^4.0.0"
|
|
80
84
|
}
|
|
81
85
|
};
|
|
82
86
|
|
|
@@ -107,8 +111,9 @@ Generated with sharq.
|
|
|
107
111
|
## Structure
|
|
108
112
|
|
|
109
113
|
- \`content/\` markdown posts
|
|
114
|
+
- \`styles/site.css\` Tailwind entry file
|
|
110
115
|
- \`templates/\` page templates
|
|
111
|
-
- \`public/assets
|
|
116
|
+
- \`public/assets/overrides.css\` optional vanilla CSS overrides
|
|
112
117
|
- \`sharq/\` production build output
|
|
113
118
|
- \`sharq.config.js\` project-level settings
|
|
114
119
|
`;
|
package/lib/server.js
CHANGED
|
@@ -3,6 +3,7 @@ import http from "node:http";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { resolveConfig } from "./config.js";
|
|
5
5
|
import { ensurePostGenerated, refreshSiteArtifacts } from "./generator.js";
|
|
6
|
+
import { compileTailwind } from "./styles.js";
|
|
6
7
|
|
|
7
8
|
const contentTypes = {
|
|
8
9
|
".html": "text/html; charset=utf-8",
|
|
@@ -186,13 +187,23 @@ export async function startServer(options = {}) {
|
|
|
186
187
|
const config = await resolveConfig(rootDir);
|
|
187
188
|
const requestedPort = Number(options.port || process.env.PORT || 3000);
|
|
188
189
|
const maxPortAttempts = Number(options.maxPortAttempts || 20);
|
|
190
|
+
const watchStyles = Boolean(options.watchStyles);
|
|
189
191
|
const app = createApp(config);
|
|
192
|
+
|
|
193
|
+
await compileTailwind(config);
|
|
194
|
+
const styleWatcher = watchStyles ? await compileTailwind(config, { watch: true }) : null;
|
|
190
195
|
const { server, port } = await listenOnAvailablePort(() => app.createServer(), requestedPort, maxPortAttempts);
|
|
191
196
|
|
|
192
197
|
if (!process.env.SITE_URL) {
|
|
193
198
|
config.siteUrl = `http://localhost:${port}`;
|
|
194
199
|
}
|
|
195
200
|
|
|
201
|
+
if (styleWatcher) {
|
|
202
|
+
server.on("close", () => {
|
|
203
|
+
styleWatcher.kill();
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
196
207
|
await app.prepare();
|
|
197
208
|
console.log(`sharq running at http://localhost:${port}`);
|
|
198
209
|
return { server, port, config };
|
package/lib/styles.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
|
|
4
|
+
function getNpxCommand() {
|
|
5
|
+
return process.platform === "win32" ? "npx.cmd" : "npx";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function hasTailwindInput(config) {
|
|
9
|
+
try {
|
|
10
|
+
await fs.access(config.tailwindInputPath);
|
|
11
|
+
return true;
|
|
12
|
+
} catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function runTailwind(config, { watch = false, minify = false } = {}) {
|
|
18
|
+
const args = [
|
|
19
|
+
"@tailwindcss/cli",
|
|
20
|
+
"-i",
|
|
21
|
+
config.tailwindInputPath,
|
|
22
|
+
"-o",
|
|
23
|
+
config.tailwindOutputPath
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
if (watch) {
|
|
27
|
+
args.push("--watch");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (minify) {
|
|
31
|
+
args.push("--minify");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return spawn(getNpxCommand(), args, {
|
|
35
|
+
cwd: config.rootDir,
|
|
36
|
+
stdio: watch ? "inherit" : "pipe"
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function compileTailwind(config, options = {}) {
|
|
41
|
+
if (!(await hasTailwindInput(config))) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await fs.mkdir(config.staticAssetsDir, { recursive: true });
|
|
46
|
+
|
|
47
|
+
const child = runTailwind(config, options);
|
|
48
|
+
|
|
49
|
+
if (options.watch) {
|
|
50
|
+
return child;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let stderr = "";
|
|
54
|
+
|
|
55
|
+
if (child.stderr) {
|
|
56
|
+
child.stderr.on("data", (chunk) => {
|
|
57
|
+
stderr += chunk.toString();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
child.on("exit", (code) => {
|
|
63
|
+
if (code === 0) {
|
|
64
|
+
resolve(true);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
reject(new Error(stderr.trim() || `Tailwind build failed with exit code ${code}.`));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
child.on("error", (error) => {
|
|
72
|
+
reject(error);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
package/package.json
CHANGED
|
@@ -1,36 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bivabdas/sharq",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"static-site-generator",
|
|
8
|
-
"blog",
|
|
9
|
-
"markdown",
|
|
10
|
-
"landing-pages",
|
|
11
|
-
"publishing"
|
|
12
|
-
],
|
|
13
|
-
"engines": {
|
|
14
|
-
"node": ">=20.0.0"
|
|
15
|
-
},
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "A tiny static publishing framework for landing pages and markdown-driven sites.",
|
|
16
5
|
"type": "module",
|
|
17
|
-
"
|
|
18
|
-
".": "./index.js"
|
|
19
|
-
},
|
|
6
|
+
"main": "index.js",
|
|
20
7
|
"bin": {
|
|
21
8
|
"sharq": "./bin/sharq.js",
|
|
22
9
|
"create-sharq": "./bin/create-sharq.js"
|
|
23
10
|
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"start": "node ./bin/sharq.js start",
|
|
26
|
-
"dev": "node --watch ./bin/sharq.js dev",
|
|
27
|
-
"build": "node ./bin/sharq.js build",
|
|
28
|
-
"test": "node --input-type=module -e \"import('./index.js').then((m) => console.log('exports:', Object.keys(m).sort().join(', ')))\""
|
|
29
|
-
},
|
|
30
11
|
"files": [
|
|
31
12
|
"bin",
|
|
13
|
+
"index.js",
|
|
32
14
|
"lib",
|
|
33
15
|
"scaffold",
|
|
34
|
-
"
|
|
35
|
-
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "node --input-type=module -e \"import('./index.js').then((m) => console.log('exports:', Object.keys(m).sort().join(', ')))\""
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"static-site-generator",
|
|
24
|
+
"markdown",
|
|
25
|
+
"landing-pages",
|
|
26
|
+
"blog",
|
|
27
|
+
"tailwindcss"
|
|
28
|
+
],
|
|
29
|
+
"author": "Bivab Das",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"homepage": "https://www.sharq.site",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/Bivab0/sharq.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/Bivab0/sharq/issues"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18"
|
|
41
|
+
}
|
|
36
42
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background-color: #f6f4ee;
|
|
3
|
+
background-image:
|
|
4
|
+
linear-gradient(rgba(16, 16, 16, 0.08) 1px, transparent 1px),
|
|
5
|
+
linear-gradient(90deg, rgba(16, 16, 16, 0.08) 1px, transparent 1px),
|
|
6
|
+
radial-gradient(circle at top center, rgba(16, 16, 16, 0.045), transparent 36%);
|
|
7
|
+
background-size: 126px 126px, 126px 126px, auto;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.article-content h2,
|
|
11
|
+
.article-content h3 {
|
|
12
|
+
margin-top: 2.2rem;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.article-content pre {
|
|
16
|
+
overflow-x: auto;
|
|
17
|
+
border-radius: 1rem;
|
|
18
|
+
background: #121212;
|
|
19
|
+
color: #f6f6f3;
|
|
20
|
+
padding: 1rem 1.125rem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.article-content blockquote {
|
|
24
|
+
margin: 1.5rem 0;
|
|
25
|
+
padding-left: 1rem;
|
|
26
|
+
border-left: 3px solid rgba(16, 16, 16, 0.16);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.tag {
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
border: 1px solid rgba(16, 16, 16, 0.1);
|
|
33
|
+
border-radius: 999px;
|
|
34
|
+
background: rgba(16, 16, 16, 0.04);
|
|
35
|
+
padding: 0.42rem 0.9rem;
|
|
36
|
+
font-size: 0.86rem;
|
|
37
|
+
color: #66645d;
|
|
38
|
+
}
|
|
@@ -1,224 +1,38 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
color-scheme: light;
|
|
3
|
-
--bg: #efe6d6;
|
|
4
|
-
--bg-deep: #ddd3c4;
|
|
5
|
-
--panel: rgba(255, 251, 245, 0.9);
|
|
6
|
-
--panel-strong: #fff8ef;
|
|
7
|
-
--text: #221d18;
|
|
8
|
-
--muted: #6d645b;
|
|
9
|
-
--accent: #0f766e;
|
|
10
|
-
--accent-strong: #9a3412;
|
|
11
|
-
--border: rgba(108, 92, 76, 0.16);
|
|
12
|
-
--shadow: 0 18px 45px rgba(64, 40, 20, 0.08);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
* {
|
|
16
|
-
box-sizing: border-box;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
html {
|
|
20
|
-
font-size: 16px;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
1
|
body {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
radial-gradient(circle at 80% 20%, rgba(154, 52, 18, 0.14), transparent 22%),
|
|
31
|
-
linear-gradient(180deg, var(--bg-deep) 0%, var(--bg) 100%);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
a {
|
|
35
|
-
color: var(--accent);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.button-link {
|
|
39
|
-
display: inline-flex;
|
|
40
|
-
align-items: center;
|
|
41
|
-
padding: 0.7rem 1rem;
|
|
42
|
-
border-radius: 999px;
|
|
43
|
-
background: var(--accent);
|
|
44
|
-
color: #f8fbfb;
|
|
45
|
-
text-decoration: none;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.shell {
|
|
49
|
-
max-width: 920px;
|
|
50
|
-
margin: 0 auto;
|
|
51
|
-
padding: 56px 20px 80px;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.eyebrow {
|
|
55
|
-
margin: 0 0 12px;
|
|
56
|
-
letter-spacing: 0.08em;
|
|
57
|
-
text-transform: uppercase;
|
|
58
|
-
color: var(--accent-strong);
|
|
59
|
-
font-size: 0.8rem;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.hero {
|
|
63
|
-
margin-bottom: 28px;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.hero h1 {
|
|
67
|
-
margin: 0;
|
|
68
|
-
font-size: clamp(3rem, 9vw, 5.5rem);
|
|
69
|
-
line-height: 0.95;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.hero p:last-child {
|
|
73
|
-
max-width: 58ch;
|
|
74
|
-
color: var(--muted);
|
|
75
|
-
line-height: 1.8;
|
|
76
|
-
font-size: 1.04rem;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.panel,
|
|
80
|
-
.article-card {
|
|
81
|
-
background: var(--panel);
|
|
82
|
-
border: 1px solid var(--border);
|
|
83
|
-
border-radius: 24px;
|
|
84
|
-
box-shadow: var(--shadow);
|
|
85
|
-
backdrop-filter: blur(10px);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.panel {
|
|
89
|
-
padding: 24px;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.article-card {
|
|
93
|
-
padding: 32px;
|
|
94
|
-
background: var(--panel-strong);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.post-list {
|
|
98
|
-
list-style: none;
|
|
99
|
-
padding: 0;
|
|
100
|
-
margin: 0;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.post-list li {
|
|
104
|
-
display: flex;
|
|
105
|
-
justify-content: space-between;
|
|
106
|
-
align-items: baseline;
|
|
107
|
-
gap: 20px;
|
|
108
|
-
padding: 18px 0;
|
|
109
|
-
border-bottom: 1px solid var(--border);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.post-list li:last-child {
|
|
113
|
-
border-bottom: 0;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.post-list a {
|
|
117
|
-
text-decoration: none;
|
|
118
|
-
font-size: 1.15rem;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.post-list p {
|
|
122
|
-
margin: 0.45rem 0 0;
|
|
123
|
-
color: var(--muted);
|
|
124
|
-
line-height: 1.7;
|
|
125
|
-
max-width: 52ch;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.post-list span,
|
|
129
|
-
.meta {
|
|
130
|
-
color: var(--muted);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.tag-list {
|
|
134
|
-
display: flex;
|
|
135
|
-
flex-wrap: wrap;
|
|
136
|
-
gap: 0.5rem;
|
|
137
|
-
list-style: none;
|
|
138
|
-
padding: 0;
|
|
139
|
-
margin: 0 0 1.25rem;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.tag {
|
|
143
|
-
padding: 0.35rem 0.7rem;
|
|
144
|
-
border-radius: 999px;
|
|
145
|
-
background: rgba(15, 118, 110, 0.1);
|
|
146
|
-
color: var(--accent);
|
|
147
|
-
font-size: 0.85rem;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.article-content p,
|
|
151
|
-
.article-content li {
|
|
152
|
-
line-height: 1.8;
|
|
2
|
+
background-color: #f6f4ee;
|
|
3
|
+
background-image:
|
|
4
|
+
linear-gradient(rgba(16, 16, 16, 0.08) 1px, transparent 1px),
|
|
5
|
+
linear-gradient(90deg, rgba(16, 16, 16, 0.08) 1px, transparent 1px),
|
|
6
|
+
radial-gradient(circle at top center, rgba(16, 16, 16, 0.045), transparent 36%);
|
|
7
|
+
background-size: 126px 126px, 126px 126px, auto;
|
|
153
8
|
}
|
|
154
9
|
|
|
155
10
|
.article-content h2,
|
|
156
11
|
.article-content h3 {
|
|
157
|
-
margin-top: 2rem;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.article-content ul,
|
|
161
|
-
.article-content ol {
|
|
162
|
-
padding-left: 1.2rem;
|
|
12
|
+
margin-top: 2.2rem;
|
|
163
13
|
}
|
|
164
14
|
|
|
165
15
|
.article-content pre {
|
|
166
16
|
overflow-x: auto;
|
|
167
|
-
|
|
168
|
-
background: #
|
|
169
|
-
color: #
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.article-content code {
|
|
174
|
-
font-family: "SFMono-Regular", Consolas, monospace;
|
|
17
|
+
border-radius: 1rem;
|
|
18
|
+
background: #121212;
|
|
19
|
+
color: #f6f6f3;
|
|
20
|
+
padding: 1rem 1.125rem;
|
|
175
21
|
}
|
|
176
22
|
|
|
177
23
|
.article-content blockquote {
|
|
178
24
|
margin: 1.5rem 0;
|
|
179
|
-
padding:
|
|
180
|
-
border-left:
|
|
181
|
-
color: var(--muted);
|
|
25
|
+
padding-left: 1rem;
|
|
26
|
+
border-left: 3px solid rgba(16, 16, 16, 0.16);
|
|
182
27
|
}
|
|
183
28
|
|
|
184
|
-
.
|
|
185
|
-
display:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
.
|
|
190
|
-
padding:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
.archive-item:last-child {
|
|
195
|
-
border-bottom: 0;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.archive-item h2 {
|
|
199
|
-
margin: 0;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
.archive-item p {
|
|
203
|
-
margin: 0.5rem 0 0;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.archive-meta {
|
|
207
|
-
color: var(--muted);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
@media (max-width: 640px) {
|
|
211
|
-
.shell {
|
|
212
|
-
padding-top: 40px;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
.article-card,
|
|
216
|
-
.panel {
|
|
217
|
-
padding: 22px;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
.post-list li {
|
|
221
|
-
flex-direction: column;
|
|
222
|
-
align-items: flex-start;
|
|
223
|
-
}
|
|
29
|
+
.tag {
|
|
30
|
+
display: inline-flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
border: 1px solid rgba(16, 16, 16, 0.1);
|
|
33
|
+
border-radius: 999px;
|
|
34
|
+
background: rgba(16, 16, 16, 0.04);
|
|
35
|
+
padding: 0.42rem 0.9rem;
|
|
36
|
+
font-size: 0.86rem;
|
|
37
|
+
color: #66645d;
|
|
224
38
|
}
|
|
@@ -6,17 +6,13 @@
|
|
|
6
6
|
<title>{{title}}</title>
|
|
7
7
|
<meta name="description" content="{{description}}">
|
|
8
8
|
<link rel="stylesheet" href="/assets/site.css">
|
|
9
|
+
<link rel="stylesheet" href="/assets/overrides.css">
|
|
9
10
|
</head>
|
|
10
|
-
<body class="
|
|
11
|
-
<main class="
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<p>Everything currently discoverable in the content folder, sorted newest first.</p>
|
|
16
|
-
</section>
|
|
17
|
-
<section class="panel archive-list">
|
|
18
|
-
{{content}}
|
|
19
|
-
</section>
|
|
11
|
+
<body class="bg-[#f6f4ee] px-4 py-4 text-[#101010] antialiased sm:px-6 lg:px-8">
|
|
12
|
+
<main class="mx-auto w-full max-w-6xl rounded-[2rem] border border-black/10 bg-white/70 px-6 py-8 shadow-[0_24px_70px_rgba(17,17,17,0.06)] backdrop-blur-xl sm:px-10">
|
|
13
|
+
<p class="mb-3 text-[0.72rem] uppercase tracking-[0.22em] text-[#66645d]">Archive</p>
|
|
14
|
+
<h1 class="max-w-[12ch] text-balance text-[clamp(2.2rem,4vw,3.6rem)] font-semibold leading-[0.98] tracking-[-0.08em] text-[#101010]">Everything currently published.</h1>
|
|
15
|
+
<div class="mt-8 space-y-4">{{content}}</div>
|
|
20
16
|
</main>
|
|
21
17
|
</body>
|
|
22
18
|
</html>
|
|
@@ -6,20 +6,17 @@
|
|
|
6
6
|
<title>{{title}}</title>
|
|
7
7
|
<meta name="description" content="{{description}}">
|
|
8
8
|
<link rel="stylesheet" href="/assets/site.css">
|
|
9
|
+
<link rel="stylesheet" href="/assets/overrides.css">
|
|
9
10
|
</head>
|
|
10
|
-
<body class="
|
|
11
|
-
<main class="
|
|
12
|
-
<section class="
|
|
13
|
-
<p class="
|
|
14
|
-
<h1>{{title}}</h1>
|
|
15
|
-
<p>{{description}}</p>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<section class="panel">
|
|
20
|
-
<ul class="post-list">
|
|
21
|
-
{{content}}
|
|
22
|
-
</ul>
|
|
11
|
+
<body class="bg-[#f6f4ee] text-[#101010] antialiased">
|
|
12
|
+
<main class="mx-auto flex min-h-screen w-full max-w-6xl items-center px-4 py-4 sm:px-6 lg:px-8">
|
|
13
|
+
<section class="w-full rounded-[2rem] border border-black/10 bg-white/70 px-6 py-10 text-center shadow-[0_24px_70px_rgba(17,17,17,0.06)] backdrop-blur-xl sm:px-10 lg:px-16">
|
|
14
|
+
<p class="mb-4 text-[0.72rem] uppercase tracking-[0.22em] text-[#66645d]">Tailwind first</p>
|
|
15
|
+
<h1 class="mx-auto max-w-[80%] text-balance text-[clamp(2.35rem,5vw,4.2rem)] font-semibold leading-[0.98] tracking-[-0.08em] text-[#101010]">{{title}}</h1>
|
|
16
|
+
<p class="mx-auto mt-5 max-w-[70%] text-balance text-[clamp(0.98rem,1.25vw,1.05rem)] leading-7 text-[#66645d]">{{description}}</p>
|
|
17
|
+
<div class="mt-8 rounded-full border border-black/10 px-4 py-2 text-sm text-[#66645d]">
|
|
18
|
+
Edit Tailwind utilities in the templates and use <code class="font-mono text-[#101010]">public/assets/overrides.css</code> for custom CSS.
|
|
19
|
+
</div>
|
|
23
20
|
</section>
|
|
24
21
|
</main>
|
|
25
22
|
</body>
|
|
@@ -6,18 +6,17 @@
|
|
|
6
6
|
<title>{{title}}</title>
|
|
7
7
|
<meta name="description" content="{{description}}">
|
|
8
8
|
<link rel="stylesheet" href="/assets/site.css">
|
|
9
|
+
<link rel="stylesheet" href="/assets/overrides.css">
|
|
9
10
|
</head>
|
|
10
|
-
<body class="
|
|
11
|
-
<main class="
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</div>
|
|
20
|
-
</article>
|
|
11
|
+
<body class="bg-[#f6f4ee] px-4 py-4 text-[#101010] antialiased sm:px-6 lg:px-8">
|
|
12
|
+
<main class="mx-auto w-full max-w-5xl rounded-[2rem] border border-black/10 bg-white/85 px-6 py-8 shadow-[0_24px_70px_rgba(17,17,17,0.06)] backdrop-blur-xl sm:px-10">
|
|
13
|
+
<p class="mb-4 text-[0.72rem] uppercase tracking-[0.22em] text-[#66645d]"><a class="transition hover:text-[#101010]" href="/">Back to home</a></p>
|
|
14
|
+
<h1 class="max-w-[12ch] text-balance text-[clamp(2.2rem,4vw,3.8rem)] font-semibold leading-[0.98] tracking-[-0.08em] text-[#101010]">{{title}}</h1>
|
|
15
|
+
<p class="mt-4 text-sm text-[#66645d]">{{date}} · {{author}}</p>
|
|
16
|
+
<ul class="mb-7 mt-4 flex flex-wrap gap-2">{{tags}}</ul>
|
|
17
|
+
<div class="article-content max-w-none">
|
|
18
|
+
{{content}}
|
|
19
|
+
</div>
|
|
21
20
|
</main>
|
|
22
21
|
</body>
|
|
23
22
|
</html>
|