commit 0957a831a127d47a6fe103dcbfa3e6f3e8ca9abd Author: Steve Date: Mon Sep 29 09:21:47 2025 -0400 feat: init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d1cc94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# dependencies (bun install) +node_modules + +# output +out +dist +site-dist +*.tgz + +# code coverage +coverage +*.lcov + +# logs +logs +_.log +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# caches +.eslintcache +.cache +*.tsbuildinfo + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store + +# Misc +Notes.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..630114b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,107 @@ +--- + +Default to using Bun instead of Node.js. + +- Use `bun ` instead of `node ` or `ts-node ` +- Use `bun test` instead of `jest` or `vitest` +- Use `bun build ` instead of `webpack` or `esbuild` +- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install` +- Use `bun run + + +``` + +With the following `frontend.tsx`: + +```tsx#frontend.tsx +import React from "react"; + +// import .css files directly and it works +import './index.css'; + +import { createRoot } from "react-dom/client"; + +const root = createRoot(document.body); + +export default function Frontend() { + return

Hello, world!

; +} + +root.render(); +``` + +Then, run index.ts + +```sh +bun --hot ./index.ts +``` + +For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a0aa89b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Steve Simkins + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b7dae03 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# Norns + +![cover](site/og.png) + +Interoperable web components for decentralized applications + +## Overview and Reasoning + +Some of the first crypto apps we build were in React, and it's possible we might be able to resurrect some of them if we tried. However the unfortunate reality is that web dev frameworks accelerate at an alarming rate, and that goes for blockchain related libraries as well (shudders at the memory of viem v1 -> v2 and ethers v5 -> v6). It doesn't have to be like that though. + +Web components are independant pieces of Javascript that can be imported to plain HTML but also frameworks as well. They're atomic, existing on their own and able to out-last any framework as long as we keep using Javscript (unfortunately I think that is the case). Some notable existing web component libraries include [Material Web](https://github.com/material-components/material-web) and [Web Awesome](https://github.com/shoelace-style/webawesome). + +The goal of Norns is to provide the Ethereum ecosystem a set of simple yet powerful web components for building decentralized applications. The advantage we have today is that we've experienced good DX from modern frameworks, so we have the ability to build components that feel familiar to devs building UIs for smart contracts. We will start small but slowly grow the offering as we get a better feel for what devs need; check out the [Roadmap](#roadmap) for more information. + +## Local Development Setup + +1. Clone and install dependencies with [Bun](https://bun.sh) + +```bash +git clone https://github.com/stevedylandev/norns +cd norns +bun install +``` + +2. Run the dev server + +```bash +bun dev +``` + +This will run a simple server for `site/index.html` which imports components from `src/component/` + +3. Build + +After editing components and testing them in the dev server you can run the `build` command to generate the CLI from `src/index.ts` that will create a `dist` folder. This enables users to run something like `npx norns-ui@latest init` to setup a project and add components, similar to shadcn/ui. + +## Roadmap + +Still figuring this out, suggestions and examples welcome! + +**CLI** + +- [x] Implement `norns.json` initialization +- [x] Improve styles and UX of commands and help menus +- [ ] Include utility files like types in initialization and `norns.json` + +**Components** + +- [x] Connect Wallet +- [x] Contract Call +- [ ] TX Toasts? +- [ ] Contract State (similar to contract call but auto loads the state) +- [ ] Framework compatability + - [x] React + - [ ] Svelte + - [ ] Vue +- [ ] General types through JSDoc? +- [ ] Add tailwindcss class/className prop +- [ ] Styles override if shadcn present? + +## Contributing + +Norns is still in early development but definitely open to contributions! Just open an issue to get the ball rolling :) + +## Contact + +Feel free to reach out to any of my [socials](https://stevedylan.dev/links) or [shoot me an email](mailto:contact@stevedylan.dev) diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..113aa8e --- /dev/null +++ b/biome.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "tab" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "useArrowFunction": "off" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..ea45fd0 --- /dev/null +++ b/bun.lock @@ -0,0 +1,40 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "norns-ui", + "dependencies": { + "@noble/hashes": "^2.0.0", + }, + "devDependencies": { + "@types/bun": "latest", + "bun-plugin-tailwind": "^0.0.15", + "tailwindcss": "^4.1.13", + }, + "peerDependencies": { + "typescript": "^5", + }, + }, + }, + "packages": { + "@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], + + "@types/bun": ["@types/bun@1.2.22", "", { "dependencies": { "bun-types": "1.2.22" } }, "sha512-5A/KrKos2ZcN0c6ljRSOa1fYIyCKhZfIVYeuyb4snnvomnpFqC0tTsEkdqNxbAgExV384OETQ//WAjl3XbYqQA=="], + + "@types/node": ["@types/node@24.5.2", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ=="], + + "@types/react": ["@types/react@19.1.14", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-ukd93VGzaNPMAUPy0gRDSC57UuQbnH9Kussp7HBjM06YFi9uZTFhOvMSO2OKqXm1rSgzOE+pVx1k1PYHGwlc8Q=="], + + "bun-plugin-tailwind": ["bun-plugin-tailwind@0.0.15", "", { "peerDependencies": { "typescript": "^5.0.0" } }, "sha512-qtAXMNGG4R0UGGI8zWrqm2B7BdXqx48vunJXBPzfDOHPA5WkRUZdTSbE7TFwO4jLhYqSE23YMWsM9NhE6ovobw=="], + + "bun-types": ["bun-types@1.2.22", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-hwaAu8tct/Zn6Zft4U9BsZcXkYomzpHJX28ofvx7k0Zz2HNz54n1n+tDgxoWFGB4PcFvJXJQloPhaV2eP3Q6EA=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "tailwindcss": ["tailwindcss@4.1.13", "", {}, "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="], + } +} diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..de249f9 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[serve.static] +plugins = ["bun-plugin-tailwind"] diff --git a/orbiter.json b/orbiter.json new file mode 100644 index 0000000..42098e0 --- /dev/null +++ b/orbiter.json @@ -0,0 +1,6 @@ +{ + "siteId": "e4400933-efdd-4788-80d9-6a28872c3dc7", + "domain": "norns", + "buildCommand": "bun run build:site", + "buildDir": "site-dist" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4b454cb --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "blogfeeds", + "version": "0.0.1", + "description": "Webstie to promote blogfeeds", + "type": "module", + "scripts": { + "build": "bun scripts/build-site", + "dev": "bun site/index.html --console" + }, + "devDependencies": { + "@types/bun": "latest", + "bun-plugin-tailwind": "^0.0.15", + "tailwindcss": "^4.1.13" + }, + "peerDependencies": { + "typescript": "^5" + } +} diff --git a/scripts/build-site.ts b/scripts/build-site.ts new file mode 100644 index 0000000..a8564f2 --- /dev/null +++ b/scripts/build-site.ts @@ -0,0 +1,18 @@ +import { $ } from "bun"; + +// Clean up dist +await $`rm -rf site-dist`; +// Create new dist +await $`cp -r site site-dist`; +// Compile tailwindcss +await $`bunx @tailwindcss/cli -i ./site/input.css -o ./site-dist/output.css `; +// Read index file +const htmlContent = await Bun.file("site-dist/index.html").text(); +// Update script tags and css link +const updatedHtml = htmlContent + .replace( + ``, + ``, + ); +// Write file +await Bun.write("site-dist/index.html", updatedHtml); diff --git a/site/android-chrome-192x192.png b/site/android-chrome-192x192.png new file mode 100644 index 0000000..4516b5e Binary files /dev/null and b/site/android-chrome-192x192.png differ diff --git a/site/android-chrome-512x512.png b/site/android-chrome-512x512.png new file mode 100644 index 0000000..48b5c93 Binary files /dev/null and b/site/android-chrome-512x512.png differ diff --git a/site/apple-touch-icon.png b/site/apple-touch-icon.png new file mode 100644 index 0000000..71e90ca Binary files /dev/null and b/site/apple-touch-icon.png differ diff --git a/site/favicon-16x16.png b/site/favicon-16x16.png new file mode 100644 index 0000000..67b142e Binary files /dev/null and b/site/favicon-16x16.png differ diff --git a/site/favicon-32x32.png b/site/favicon-32x32.png new file mode 100644 index 0000000..29cb5ab Binary files /dev/null and b/site/favicon-32x32.png differ diff --git a/site/favicon.ico b/site/favicon.ico new file mode 100644 index 0000000..7fdeca3 Binary files /dev/null and b/site/favicon.ico differ diff --git a/site/github.svg b/site/github.svg new file mode 100644 index 0000000..3db3b85 --- /dev/null +++ b/site/github.svg @@ -0,0 +1,3 @@ + + + diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..f5a4b1c --- /dev/null +++ b/site/index.html @@ -0,0 +1,131 @@ + + + + + + Blog Feeds + + + + + + + + + + + + + + + + + + + +
+
+
+

Do you kinda hate social media?

+ +

Tired of doom scrolling through addicting feeds?

+ +

Miss the days when the web was just about connecting with people and their thoughts or ideas?

+ +

We believe there's an answer to that problem, and it's called

+

Blog Feeds

+
+
+ +
+
+

No this isn't another platform.

+

+ You don't sign up here. +

+

You just write what's on your mind, respond to an idea, post a recipe, or share a photo. It's blogs, but perhaps not in the way you would think of blogs.

+ +

It just takes three things to participate:

+
    +
  1. Blog
  2. +
  3. RSS
  4. +
  5. Feeds
  6. +
+
+
+ +
+
+

Blog

+ +

Let me reassure you, this is actually simpler than what you're probably thinking. This doesn't have to be some well polished highly viewed monetization machine. It's just a simple website where you can casually talk about whatever you want to talk about! It can be long, short, a list of small things, or just a quote. It should be how you talk with other people in your own life, or how you communicate with the outside world. It should be you on a page. Here's a few places you can make a blog that are RSS enabled:

+ +

Hosted Services

+ +

These are great if you are not quite a technical person and need everything to be simple and easy to use.

+
    +
  • Bear Blog ⭐️
  • +
  • Substack
  • +
  • Ghost
  • +
  • Wordpress
  • +
  • Squarespace
  • +
+ +

Self Hosted Frameworks

+ +

For the devs 🫡 Some of my favorite frameworks and tools for making a blog!

+
    +
  • Astro
  • +
  • Hugo
  • +
  • Zola
  • +
  • 11ty
  • +
  • Jekyll
  • +
+
+
+ +
+
+

RSS

+ +

Also known as "really simple syndication", RSS has been around for decades. In short, it's simply a list of data that can be updated and notify people when something new has been posted. This is great for blogs since you don't have to always check all the people you want to follow. When you make your blog, you want to make sure it's RSS enabled (resources are further down). You also will want to get an RSS reader, as this will allow you to create a list of people to follow and let you read posts as they are published. These can vary from hosted web platforms where you might need to pay at some point to just free apps you can download. Would highly recommend trying a few and seeing which works best!

+ +
+
+ +
+
+

Feeds

+ +

This takes us to our final point: Feeds. You can probably get away with just the first two items and then sharing it with people you already know, but what about meeting or talking to people you don't know? That's where Feeds come in. The idea is to create another page on your blog that has all the RSS feeds you're subscribed to. By keeping this public and always up to date, someone can visit your page, find someone new and follow them. Perhaps that person also has a feeds page, and the cycle continues until there is a natural and organic network of people all sharing with each other. So if you have a blog, consider making a feeds page and sharing it! If your RSS reader supports OPML file exports and imports, perhaps you can share that file as well to make it easier to share your feeds.

+
+
+ +
+
+

The best part about blog feeds? It's just an idea. There's no central authority. There's no platform. No massive tech giant trying to take your data. It's just you and the people you care about.

+
+
+ +
+
+

FAQ

+ +
    +
  • Where do I sign up?
  • +
  • How much does Blog Feeds cost?
  • +
  • Does this replace social media?
  • +
  • What about monetization?
  • +
  • What about comments or dialogue?
  • +
+
+
+
+ + diff --git a/site/input.css b/site/input.css new file mode 100644 index 0000000..f1d8c73 --- /dev/null +++ b/site/input.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/site/logo.svg b/site/logo.svg new file mode 100644 index 0000000..e8e89a3 --- /dev/null +++ b/site/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/site/og.png b/site/og.png new file mode 100644 index 0000000..78aa212 Binary files /dev/null and b/site/og.png differ diff --git a/site/site.webmanifest b/site/site.webmanifest new file mode 100644 index 0000000..45dc8a2 --- /dev/null +++ b/site/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2a68aa7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + // Environment setup & latest features + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "target": "ESNext", + "module": "Preserve", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +}