Public: anyone can read this; the crew can change it.

feat: thoughts and first thought #2

opened this view on origin

Check · Review · Land · Live — It conflicts with its base. Next: builder, it conflicts with its base.

Conflicts with main

feat/thoughts → main 3 commits

  • Can't merge. Conflicts in 1 file: src/components/FloatingNavigation.tsx. Merge main into the branch and push again.

    Check faileddeploy 32c390c

A guest

This pull comes from a guest: its preview runs without the app's variables or a forge token until a person who can write here approves it.

This pull cannot land as it is, whatever its review says, because it changes guarded paths: package.json (release machinery).

Review

Sign in to review this change.
10 files changed +631 −1
package-lock.json +146
@@ -24,6 +24,7 @@
2424 "class-variance-authority": "^0.7.0",
2525 "clsx": "^2.1.1",
2626 "framer-motion": "^11.5.4",
27 "gray-matter": "^4.0.3",
2728 "lucide-react": "^0.439.0",
2829 "next": "14.2.9",
2930 "octokit": "^4.0.2",
@@ -35,7 +36,9 @@
3536 "react-syntax-highlighter": "^15.5.0",
3637 "react-type-animation": "^3.2.0",
3738 "rehype-raw": "^7.0.0",
39 "remark": "^15.0.1",
3840 "remark-gfm": "^4.0.0",
41 "remark-html": "^16.0.1",
3942 "tailwind-merge": "^2.5.2",
4043 "tailwindcss-animate": "^1.0.7",
4144 "three": "^0.168.0"
@@ -3739,6 +3742,18 @@
37393742 "url": "https://opencollective.com/eslint"
37403743 }
37413744 },
3745 "node_modules/esprima": {
3746 "version": "4.0.1",
3747 "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
3748 "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
3749 "bin": {
3750 "esparse": "bin/esparse.js",
3751 "esvalidate": "bin/esvalidate.js"
3752 },
3753 "engines": {
3754 "node": ">=4"
3755 }
3756 },
37423757 "node_modules/esquery": {
37433758 "version": "1.6.0",
37443759 "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
@@ -3795,6 +3810,17 @@
37953810 "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
37963811 "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
37973812 },
3813 "node_modules/extend-shallow": {
3814 "version": "2.0.1",
3815 "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
3816 "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
3817 "dependencies": {
3818 "is-extendable": "^0.1.0"
3819 },
3820 "engines": {
3821 "node": ">=0.10.0"
3822 }
3823 },
37983824 "node_modules/fast-deep-equal": {
37993825 "version": "3.1.3",
38003826 "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -4222,6 +4248,40 @@
42224248 "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
42234249 "dev": true
42244250 },
4251 "node_modules/gray-matter": {
4252 "version": "4.0.3",
4253 "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
4254 "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
4255 "dependencies": {
4256 "js-yaml": "^3.13.1",
4257 "kind-of": "^6.0.2",
4258 "section-matter": "^1.0.0",
4259 "strip-bom-string": "^1.0.0"
4260 },
4261 "engines": {
4262 "node": ">=6.0"
4263 }
4264 },
4265 "node_modules/gray-matter/node_modules/argparse": {
4266 "version": "1.0.10",
4267 "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
4268 "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
4269 "dependencies": {
4270 "sprintf-js": "~1.0.2"
4271 }
4272 },
4273 "node_modules/gray-matter/node_modules/js-yaml": {
4274 "version": "3.14.1",
4275 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
4276 "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
4277 "dependencies": {
4278 "argparse": "^1.0.7",
4279 "esprima": "^4.0.0"
4280 },
4281 "bin": {
4282 "js-yaml": "bin/js-yaml.js"
4283 }
4284 },
42254285 "node_modules/has-bigints": {
42264286 "version": "1.0.2",
42274287 "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
@@ -4413,6 +4473,20 @@
44134473 "url": "https://opencollective.com/unified"
44144474 }
44154475 },
4476 "node_modules/hast-util-sanitize": {
4477 "version": "5.0.1",
4478 "resolved": "https://registry.npmjs.org/hast-util-sanitize/-/hast-util-sanitize-5.0.1.tgz",
4479 "integrity": "sha512-IGrgWLuip4O2nq5CugXy4GI2V8kx4sFVy5Hd4vF7AR2gxS0N9s7nEAVUyeMtZKZvzrxVsHt73XdTsno1tClIkQ==",
4480 "dependencies": {
4481 "@types/hast": "^3.0.0",
4482 "@ungap/structured-clone": "^1.2.0",
4483 "unist-util-position": "^5.0.0"
4484 },
4485 "funding": {
4486 "type": "opencollective",
4487 "url": "https://opencollective.com/unified"
4488 }
4489 },
44164490 "node_modules/hast-util-to-html": {
44174491 "version": "9.0.2",
44184492 "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.2.tgz",
@@ -4869,6 +4943,14 @@
48694943 "url": "https://github.com/sponsors/wooorm"
48704944 }
48714945 },
4946 "node_modules/is-extendable": {
4947 "version": "0.1.1",
4948 "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
4949 "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
4950 "engines": {
4951 "node": ">=0.10.0"
4952 }
4953 },
48724954 "node_modules/is-extglob": {
48734955 "version": "2.1.1",
48744956 "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -5271,6 +5353,14 @@
52715353 "json-buffer": "3.0.1"
52725354 }
52735355 },
5356 "node_modules/kind-of": {
5357 "version": "6.0.3",
5358 "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
5359 "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
5360 "engines": {
5361 "node": ">=0.10.0"
5362 }
5363 },
52745364 "node_modules/language-subtag-registry": {
52755365 "version": "0.3.23",
52765366 "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
@@ -7851,6 +7941,21 @@
78517941 "url": "https://opencollective.com/unified"
78527942 }
78537943 },
7944 "node_modules/remark": {
7945 "version": "15.0.1",
7946 "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz",
7947 "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==",
7948 "dependencies": {
7949 "@types/mdast": "^4.0.0",
7950 "remark-parse": "^11.0.0",
7951 "remark-stringify": "^11.0.0",
7952 "unified": "^11.0.0"
7953 },
7954 "funding": {
7955 "type": "opencollective",
7956 "url": "https://opencollective.com/unified"
7957 }
7958 },
78547959 "node_modules/remark-gfm": {
78557960 "version": "4.0.0",
78567961 "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz",
@@ -7868,6 +7973,22 @@
78687973 "url": "https://opencollective.com/unified"
78697974 }
78707975 },
7976 "node_modules/remark-html": {
7977 "version": "16.0.1",
7978 "resolved": "https://registry.npmjs.org/remark-html/-/remark-html-16.0.1.tgz",
7979 "integrity": "sha512-B9JqA5i0qZe0Nsf49q3OXyGvyXuZFDzAP2iOFLEumymuYJITVpiH1IgsTEwTpdptDmZlMDMWeDmSawdaJIGCXQ==",
7980 "dependencies": {
7981 "@types/mdast": "^4.0.0",
7982 "hast-util-sanitize": "^5.0.0",
7983 "hast-util-to-html": "^9.0.0",
7984 "mdast-util-to-hast": "^13.0.0",
7985 "unified": "^11.0.0"
7986 },
7987 "funding": {
7988 "type": "opencollective",
7989 "url": "https://opencollective.com/unified"
7990 }
7991 },
78717992 "node_modules/remark-parse": {
78727993 "version": "11.0.0",
78737994 "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
@@ -8066,6 +8187,18 @@
80668187 "loose-envify": "^1.1.0"
80678188 }
80688189 },
8190 "node_modules/section-matter": {
8191 "version": "1.0.0",
8192 "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
8193 "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
8194 "dependencies": {
8195 "extend-shallow": "^2.0.1",
8196 "kind-of": "^6.0.0"
8197 },
8198 "engines": {
8199 "node": ">=4"
8200 }
8201 },
80698202 "node_modules/semver": {
80708203 "version": "7.6.3",
80718204 "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -8184,6 +8317,11 @@
81848317 "url": "https://github.com/sponsors/wooorm"
81858318 }
81868319 },
8320 "node_modules/sprintf-js": {
8321 "version": "1.0.3",
8322 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
8323 "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
8324 },
81878325 "node_modules/stats-gl": {
81888326 "version": "2.2.8",
81898327 "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.2.8.tgz",
@@ -8429,6 +8567,14 @@
84298567 "node": ">=4"
84308568 }
84318569 },
8570 "node_modules/strip-bom-string": {
8571 "version": "1.0.0",
8572 "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
8573 "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==",
8574 "engines": {
8575 "node": ">=0.10.0"
8576 }
8577 },
84328578 "node_modules/strip-json-comments": {
84338579 "version": "3.1.1",
84348580 "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
package.json +3
@@ -25,6 +25,7 @@
2525 "class-variance-authority": "^0.7.0",
2626 "clsx": "^2.1.1",
2727 "framer-motion": "^11.5.4",
28 "gray-matter": "^4.0.3",
2829 "lucide-react": "^0.439.0",
2930 "next": "14.2.9",
3031 "octokit": "^4.0.2",
@@ -36,7 +37,9 @@
3637 "react-syntax-highlighter": "^15.5.0",
3738 "react-type-animation": "^3.2.0",
3839 "rehype-raw": "^7.0.0",
40 "remark": "^15.0.1",
3941 "remark-gfm": "^4.0.0",
42 "remark-html": "^16.0.1",
4043 "tailwind-merge": "^2.5.2",
4144 "tailwindcss-animate": "^1.0.7",
4245 "three": "^0.168.0"
public/thoughts/why.md added +54
@@ -0,0 +1,54 @@
1 ---
2 name: why
3 title: Why trevato.dev?
4 subtitle: The reason for this site and what it stands for.
5 creationDate: 2024-10-18
6 ---
7
8 # Why trevato.dev?
9
10 *The reason for this site and what it stands for.*
11
12 ![the built by trevato.dev logo](../trevato.png)
13
14 ## The Digital Canvas
15
16 I've been a builder my whole life. With a computer and internet access, I've had an infinite digital canvas to paint on. But until now, I didn't have a fridge to hang up my creations. My life's goal has always been to build things that solve problems for others. It's a cliché, sure, but ask anyone who knows me – they'll tell you how often I repeat this motto.
17
18 ## Starting Small, Dreaming Big
19
20 Here's a truth bomb: Frank Ocean's first song wasn't "Nights," and Michael Jordan's first game wasn't an NBA championship. Nobody does something truly remarkable without starting small. So, that's exactly what I decided to do.
21
22 Instead of obsessing over building only "remarkable" things and fearing wasted time, I chose to get really good at creating anything and everything. My logic? When I find that truly remarkable project, I'll already be a skilled builder.
23
24 One hurdle I faced was avoiding overcomplication. Starting a new project is thrilling because of all the possibilities, but finishing it? That's a different beast. It feels like homework, which I never enjoyed. But here's the kicker: completing projects is exactly what successful people have mastered.
25
26 So, I shifted gears. I focused on small, manageable projects. I'd clearly define what I wanted to build, create only that, and then release it to the world. Some projects land on GitHub, others are out there serving a purpose. Now, I'm juggling multiple active projects, and setting up analytics has become a 30-second task. This shift from doing something once to doing it multiple times? That's where the magic happens.
27
28 ## Lego Blocks and Universe Building
29
30 > "If you wish to make an apple pie from scratch, you must first invent the universe." - Carl Sagan
31
32 Modern software development is like playing with Legos. We're not manufacturing the pieces; we're assembling them in creative ways. It's all about layering design decisions, pulling code from here and there, and connecting the dots. The beauty? Anyone can create something amazing without needing to understand how each piece is made.
33
34 Here's a secret: good software isn't about complexity. It's about simplicity. The best systems are easy to extend, debug, and maintain. When your code is straightforward, you spend less time fixing issues and more time building cool stuff. It's like writing a new page in the universe's book – once that code exists, it changes what's possible.
35
36 Let me share a mind-blowing moment I had with AI. In college, my roommate and I were testing GitHub Copilot. We needed to embed a YouTube video in a simple webpage. Instead of searching, we let the AI generate the URL. The result? [This classic](https://www.youtube.com/watch?v=dQw4w9WgXcQ). We clicked, laughed, and then it hit us – the world of possibilities had just exploded.
37
38 It's wild to think that the tech behind ChatGPT was actually developed by Google in 2017. It took years for the average person to get a taste of this future. This gap between invention and widespread use? That's the moat surrounding the castle of great software.
39
40 That's where trevato.dev comes in. It's my bridge across that moat. When I want to write a blog post, I don't want to fuss over link colors or font choices – I just want to write. I'm aiming to build big things, and big things are made of lots of small things. This site is my way of making concrete design decisions and creating a framework. It's turning those once-crazy ideas into something just within reach.
41
42 ## The Art of Generating Value
43
44 Imagine I showed you a single photo of a baseball in mid-air and asked, "Which way is it flying?" You'd be guessing. But give you two photos taken a split second apart, and suddenly it's obvious.
45
46 Building things works the same way. Everyone has ideas, but an idea from someone who doesn't build is like trying to predict chaos from a single snapshot. To generate valuable ideas that align with reality, you need a gallery of past experiences. That's when your subconscious starts cooking up ideas that are both realistic and valuable.
47
48 As you build more, the quantity of ideas increases. Then comes the challenge of prioritization – assigning value to different tasks or projects. That's where I am now. I've got plenty of irons in the fire, so I'm not just focused on getting more done, but on generating the most value with my time.
49
50 ## A Work in Progress
51
52 Maybe these thoughts aren't groundbreaking. Maybe I'm off-base on some points. Maybe this whole post is a cosmic mistake. But you know what? This is something I've wanted to start for a long time, and now I can say I've done it. If I'm right about anything I've said here, eventually I'll have something truly meaningful to share.
53
54 So here's to building, learning, and hopefully, making something that matters. Welcome to trevato.dev – let's see where this goes.
src/app/thoughts/[thought]/page.tsx added +53
@@ -0,0 +1,53 @@
1 import Link from 'next/link';
2 import { getAllThoughts } from '@/lib/thoughts';
3 import { markdownToHtml, getThoughtData } from '@/lib/markdownToHtml';
4 import './styles.css';
5
6 export async function generateStaticParams() {
7 const thoughts = getAllThoughts();
8 return thoughts.map((thought) => ({
9 thought: thought.id,
10 }));
11 }
12
13 export default async function ThoughtPage({ params }: { params: { thought: string } }) {
14 const thoughts = getAllThoughts();
15 const thought = thoughts.find((t) => t.id === params.thought);
16
17 if (!thought) {
18 return <div>Thought not found</div>;
19 }
20
21 const { content, data } = getThoughtData(thought.content);
22 const contentHtml = await markdownToHtml(content);
23
24 return (
25 <>
26 <div className="fixed top-0 left-0 right-0 z-10 backdrop-blur-sm py-4">
27 <div className="container mx-auto px-4">
28 <Link href="/thoughts">
29 <button className="px-4 py-2 rounded-lg backdrop-blur-sm bg-transparent hover:bg-white/10 transition-all duration-300 border border-white/20 hover:border-white/40 text-white/80 hover:text-white flex items-center space-x-2">
30 <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
31 <path fillRule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clipRule="evenodd" />
32 </svg>
33 <span>Back to Thoughts</span>
34 </button>
35 </Link>
36 </div>
37 </div>
38 <div className="container mx-auto px-4 pt-20">
39 <h1 className="text-3xl font-bold mb-8">{data.title}</h1>
40 <div className="prose prose-invert custom-markdown" dangerouslySetInnerHTML={{ __html: contentHtml }} />
41 <div className="mt-4 text-sm text-gray-400">
42 {thought.creationDate
43 ? new Date(thought.creationDate).toLocaleDateString('en-US', {
44 year: 'numeric',
45 month: 'long',
46 day: 'numeric'
47 })
48 : 'Date not available'}
49 </div>
50 </div>
51 </>
52 );
53 }
src/app/thoughts/[thought]/styles.css added +261
@@ -0,0 +1,261 @@
1 .custom-markdown {
2 color: #e0f7ff;
3 line-height: 1.8;
4 font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
5 font-size: 1.1rem;
6 max-width: 800px;
7 margin: 0 auto;
8 padding: 2.5rem;
9 background: linear-gradient(to bottom, rgba(10, 25, 41, 0.75), rgba(5, 15, 25, 0.85));
10 border-radius: 16px;
11 box-shadow: 0 4px 30px rgba(0, 255, 255, 0.2);
12 backdrop-filter: blur(10px);
13 -webkit-backdrop-filter: blur(10px);
14 border: 1px solid rgba(255, 255, 255, 0.1);
15 transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
16 }
17
18 .custom-markdown:hover {
19 box-shadow: 0 6px 40px rgba(0, 255, 255, 0.3);
20 transform: translateY(-8px);
21 background: linear-gradient(to bottom, rgba(10, 25, 41, 0.8), rgba(5, 15, 25, 0.9));
22 }
23
24 .custom-markdown h1,
25 .custom-markdown h2,
26 .custom-markdown h3,
27 .custom-markdown h4,
28 .custom-markdown h5,
29 .custom-markdown h6 {
30 font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
31 color: #ffffff;
32 margin-top: 2.2em;
33 margin-bottom: 1em;
34 line-height: 1.2;
35 text-shadow: 0 0 8px rgba(255, 255, 255, 0.2);
36 }
37
38 .custom-markdown h1 {
39 font-size: 2.8em;
40 border-bottom: 2px solid #4b92f6;
41 padding-bottom: 0.4em;
42 text-transform: uppercase;
43 letter-spacing: 3px;
44 background: linear-gradient(45deg, #4b92f6, #00ffff);
45 -webkit-background-clip: text;
46 -webkit-text-fill-color: transparent;
47 }
48
49 .custom-markdown h2 {
50 font-size: 2.2em;
51 color: #f0f0f0;
52 }
53
54 .custom-markdown h3 {
55 font-size: 1.7em;
56 color: #e0e0e0;
57 }
58
59 @media (max-width: 768px) {
60 .custom-markdown h1 {
61 font-size: 2em;
62 letter-spacing: 2px;
63 }
64
65 .custom-markdown h2 {
66 font-size: 1.8em;
67 }
68
69 .custom-markdown h3 {
70 font-size: 1.5em;
71 }
72 }
73
74 .custom-markdown p {
75 margin-bottom: 1.8em;
76 color: #c0c0c0;
77 text-shadow: 0 0 3px rgba(192, 192, 192, 0.2);
78 }
79
80 .custom-markdown a {
81 color: #4b92f6;
82 text-decoration: none;
83 border-bottom: 1px solid rgba(75, 146, 246, 0.3);
84 transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
85 position: relative;
86 padding: 0 2px;
87 }
88
89 .custom-markdown a:hover {
90 color: #70b5fa;
91 border-bottom-color: transparent;
92 text-shadow: 0 0 12px rgba(75, 146, 246, 0.6);
93 background-color: rgba(75, 146, 246, 0.1);
94 border-radius: 3px;
95 }
96
97 .custom-markdown a::after {
98 content: '';
99 position: absolute;
100 width: 100%;
101 height: 2px;
102 bottom: -2px;
103 left: 0;
104 background: linear-gradient(90deg, #4b92f6, #00ffff);
105 transform: scaleX(0);
106 transform-origin: bottom right;
107 transition: transform 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
108 }
109
110 .custom-markdown a:hover::after {
111 transform: scaleX(1);
112 transform-origin: bottom left;
113 }
114
115 .custom-markdown strong {
116 color: #ffffff;
117 font-weight: 700;
118 text-shadow: 0 0 5px rgba(255, 255, 255, 0.5);
119 }
120
121 .custom-markdown ul,
122 .custom-markdown ol {
123 margin-left: 1.8em;
124 margin-bottom: 1.8em;
125 padding-left: 1.2em;
126 }
127
128 .custom-markdown ul {
129 list-style-type: none;
130 }
131
132 .custom-markdown ol {
133 list-style-type: decimal;
134 }
135
136 .custom-markdown li {
137 margin-bottom: 0.9em;
138 position: relative;
139 color: #c0c0c0;
140 padding-left: 0.7em;
141 }
142
143 .custom-markdown ul > li::before {
144 content: '•';
145 position: absolute;
146 left: -1.4em;
147 color: #4b92f6;
148 font-weight: bold;
149 font-size: 1.3em;
150 text-shadow: 0 0 8px rgba(75, 146, 246, 0.6);
151 }
152
153 .custom-markdown ol > li::marker {
154 color: #4b92f6;
155 font-weight: bold;
156 text-shadow: 0 0 8px rgba(75, 146, 246, 0.6);
157 }
158
159 .custom-markdown blockquote {
160 border-left: 4px solid rgba(59, 130, 246, 0.6);
161 padding: 0.5em 1em;
162 margin: 1.5em 0;
163 background-color: rgba(59, 130, 246, 0.1);
164 font-style: italic;
165 color: #d0d0d0;
166 box-shadow: 0 0 10px rgba(59, 130, 246, 0.1);
167 backdrop-filter: blur(5px);
168 -webkit-backdrop-filter: blur(5px);
169 }
170
171 .custom-markdown code {
172 background-color: rgba(59, 130, 246, 0.15);
173 padding: 0.2em 0.4em;
174 border-radius: 0.25em;
175 font-size: 0.9em;
176 font-family: 'Fira Code', 'Source Code Pro', monospace;
177 color: #4b92f6;
178 }
179
180 .custom-markdown pre {
181 background-color: rgba(0, 0, 0, 0.6);
182 padding: 1.5em;
183 border-radius: 0.5em;
184 overflow-x: auto;
185 margin: 1.5em 0;
186 box-shadow: 0 0 20px rgba(59, 130, 246, 0.15);
187 border: 1px solid rgba(59, 130, 246, 0.3);
188 backdrop-filter: blur(5px);
189 -webkit-backdrop-filter: blur(5px);
190 }
191
192 .custom-markdown pre code {
193 background-color: transparent;
194 padding: 0;
195 font-size: 0.95em;
196 color: #a0a0a0;
197 }
198
199 .custom-markdown img {
200 max-width: 100%;
201 height: auto;
202 border-radius: 0.5em;
203 margin: 1.5em 0;
204 box-shadow: 0 0 20px rgba(0, 255, 255, 0.2);
205 border: 1px solid rgba(0, 255, 255, 0.3);
206 transition: transform 0.3s ease, box-shadow 0.3s ease;
207 }
208
209 .custom-markdown img:hover {
210 transform: scale(1.02);
211 box-shadow: 0 0 30px rgba(0, 255, 255, 0.3);
212 }
213
214 .custom-markdown hr {
215 border: 0;
216 height: 1px;
217 background: linear-gradient(to right, transparent, #00ffff, transparent);
218 margin: 2em 0;
219 }
220
221 .custom-markdown table {
222 width: 100%;
223 border-collapse: collapse;
224 margin: 2em 0;
225 background: rgba(0, 0, 0, 0.7);
226 border-radius: 10px;
227 overflow: hidden;
228 box-shadow: 0 0 20px rgba(0, 255, 255, 0.2);
229 }
230
231 .custom-markdown table th,
232 .custom-markdown table td {
233 padding: 0.75em 1em;
234 text-align: left;
235 border: 1px solid rgba(59, 130, 246, 0.3);
236 }
237
238 .custom-markdown table th {
239 background-color: rgba(59, 130, 246, 0.3);
240 color: #ffffff;
241 font-weight: bold;
242 text-transform: uppercase;
243 letter-spacing: 1px;
244 font-size: 0.9em;
245 }
246
247 .custom-markdown table td {
248 color: #d0d0d0;
249 }
250
251 .custom-markdown table tr:nth-child(even) {
252 background-color: rgba(0, 0, 0, 0.5);
253 }
254
255 .custom-markdown table tr:nth-child(odd) {
256 background-color: rgba(0, 0, 0, 0.6);
257 }
258
259 .custom-markdown table tr:hover {
260 background-color: rgba(59, 130, 246, 0.2);
261 }
src/app/thoughts/page.tsx added +42
@@ -0,0 +1,42 @@
1 import { Card } from "@/components/ui/card";
2 import Link from "next/link";
3 import { getAllThoughts } from "@/lib/thoughts";
4
5 export default function Page() {
6 const thoughts = getAllThoughts();
7 return (
8 <div className="flex flex-col space-y-8 p-6">
9 <header className="text-center">
10 <h1 className="text-3xl font-bold text-gray-100 mb-4">My Thoughts</h1>
11 <p className="text-lg text-gray-300 max-w-2xl mx-auto">
12 Welcome to my collection of thoughts and ideas! Here you&apos;ll find a variety of topics I&apos;ve been pondering,
13 from technology trends to personal reflections. Each post represents a moment of insight or curiosity.
14 Feel free to explore and engage with these ideas. Happy reading!
15 </p>
16 </header>
17 <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
18 {thoughts.map(({ id, title, subtitle, creationDate }) => (
19 <Card key={id} className="group overflow-hidden rounded-lg backdrop-blur-sm bg-black/10 hover:bg-black/20 transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105">
20 <Link href={`/thoughts/${id}`} className="block p-6">
21 <div className="flex items-center mb-2">
22 <span className="text-2xl mr-2" role="img" aria-label="Thought icon">
23 💭
24 </span>
25 <h3 className="text-lg font-semibold text-gray-200 group-hover:text-white transition-colors duration-300">
26 {title}
27 </h3>
28 </div>
29 <p className="text-sm text-gray-400 group-hover:text-gray-300 transition-colors duration-300 mb-2">
30 {subtitle}
31 </p>
32 <p className="text-xs text-gray-500 group-hover:text-gray-400 transition-colors duration-300 mb-4">
33 {new Date(creationDate).toLocaleDateString()}
34 </p>
35 <div className="w-12 h-1 bg-blue-500 group-hover:w-full transition-all duration-500 ease-in-out"></div>
36 </Link>
37 </Card>
38 ))}
39 </div>
40 </div>
41 );
42 }
src/components/FloatingNavigation.tsx +1
@@ -10,6 +10,7 @@ const navItems = [
1010 { href: '/', label: 'Home' },
1111 { href: '/playground', label: 'Playground' },
1212 { href: '/projects', label: 'Side Projects' },
13 { href: '/thoughts', label: 'Thoughts' },
1314 { href: 'https://codewear.dev', label: 'CodeWear' },
1415 ]
1516
src/components/Trevato.tsx +1 −1
@@ -22,7 +22,7 @@ export function Trevato() {
2222
2323 return (
2424 <motion.div
25 className="fixed bottom-6 right-6 z-50 hover:opacity-100 transition-opacity duration-300"
25 className="fixed bottom-6 right-6 z-50 hover:opacity-100 transition-opacity duration-300 select-none"
2626 animate={{ opacity }}
2727 transition={{ duration: 0.3 }}
2828 >
src/lib/markdownToHtml.ts added +20
@@ -0,0 +1,20 @@
1 import { remark } from 'remark';
2 import html from 'remark-html';
3 import gfm from 'remark-gfm';
4 import matter from 'gray-matter';
5
6 export async function markdownToHtml(markdown: string) {
7 const result = await remark()
8 .use(gfm)
9 .use(html, { sanitize: false }) // Allow HTML in the markdown
10 .process(markdown);
11 return result.toString();
12 }
13
14 export function getThoughtData(markdown: string) {
15 const matterResult = matter(markdown);
16 return {
17 content: matterResult.content,
18 data: matterResult.data as { title: string; date: string }
19 };
20 }
src/lib/thoughts.ts added +50
@@ -0,0 +1,50 @@
1 import fs from 'fs';
2 import path from 'path';
3 import matter from 'gray-matter';
4
5 export interface Thought {
6 id: string;
7 title: string;
8 name: string;
9 subtitle: string;
10 creationDate: Date;
11 content: string;
12 }
13
14 let thoughts: Thought[] = [];
15
16 function readThoughtsFromFiles(): Thought[] {
17 const thoughtsDirectory = path.join(process.cwd(), 'public', 'thoughts');
18 const fileNames = fs.readdirSync(thoughtsDirectory);
19
20 return fileNames.map(fileName => {
21 const id = fileName.replace(/\.md$/, '');
22 const fullPath = path.join(thoughtsDirectory, fileName);
23 const fileContents = fs.readFileSync(fullPath, 'utf8');
24 const { data, content } = matter(fileContents);
25
26 return {
27 id,
28 title: data.title,
29 name: data.name,
30 subtitle: data.subtitle,
31 creationDate: new Date(data.creationDate),
32 content,
33 };
34 });
35 }
36
37 export function getAllThoughts(): Thought[] {
38 return thoughts;
39 }
40
41 export function getThoughtById(id: string): Thought | undefined {
42 return thoughts.find(thought => thought.id === id);
43 }
44
45 function createInitialThoughts() {
46 thoughts = readThoughtsFromFiles();
47 }
48
49 // Create initial thoughts when the module is imported
50 createInitialThoughts();

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs