diff --git a/apps/docs/.eslintrc.js b/apps/docs/.eslintrc.js
deleted file mode 100644
index 7d644a4..0000000
--- a/apps/docs/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/** @type {import("eslint").Linter.Config} */
-module.exports = {
- root: true,
- extends: ["@repo/eslint-config/next.js"],
- parser: "@typescript-eslint/parser",
- parserOptions: {
- project: true,
- },
-};
diff --git a/apps/docs/README.md b/apps/docs/README.md
deleted file mode 100644
index d364535..0000000
--- a/apps/docs/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-## Getting Started
-
-First, run the development server:
-
-```bash
-yarn dev
-```
-
-Open [http://localhost:3001](http://localhost:3001) with your browser to see the result.
-
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
-
-To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello).
-
-## Learn More
-
-To learn more about Next.js, take a look at the following resources:
-
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.
-
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
-
-## Deploy on Vercel
-
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
-
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/apps/docs/app/favicon.ico b/apps/docs/app/favicon.ico
deleted file mode 100644
index 3f804c0..0000000
Binary files a/apps/docs/app/favicon.ico and /dev/null differ
diff --git a/apps/docs/app/globals.css b/apps/docs/app/globals.css
deleted file mode 100644
index 8eee6cb..0000000
--- a/apps/docs/app/globals.css
+++ /dev/null
@@ -1,50 +0,0 @@
-:root {
- --max-width: 1100px;
- --border-radius: 12px;
- --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
- "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
- "Fira Mono", "Droid Sans Mono", "Courier New", monospace;
-
- --foreground-rgb: 255, 255, 255;
- --background-start-rgb: 0, 0, 0;
- --background-end-rgb: 0, 0, 0;
-
- --callout-rgb: 20, 20, 20;
- --callout-border-rgb: 108, 108, 108;
- --card-rgb: 100, 100, 100;
- --card-border-rgb: 200, 200, 200;
-
- --glow-conic: conic-gradient(
- from 180deg at 50% 50%,
- #2a8af6 0deg,
- #a853ba 180deg,
- #e92a67 360deg
- );
-}
-
-* {
- box-sizing: border-box;
- padding: 0;
- margin: 0;
-}
-
-html,
-body {
- max-width: 100vw;
- overflow-x: hidden;
-}
-
-body {
- color: rgb(var(--foreground-rgb));
- background: linear-gradient(
- to bottom,
- transparent,
- rgb(var(--background-end-rgb))
- )
- rgb(var(--background-start-rgb));
-}
-
-a {
- color: inherit;
- text-decoration: none;
-}
diff --git a/apps/docs/app/page.module.css b/apps/docs/app/page.module.css
deleted file mode 100644
index 98481c6..0000000
--- a/apps/docs/app/page.module.css
+++ /dev/null
@@ -1,335 +0,0 @@
-.main {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- align-items: center;
- padding: 6rem;
- min-height: 100vh;
-}
-
-.vercelLogo {
- filter: invert(1);
-}
-
-.description {
- display: inherit;
- justify-content: inherit;
- align-items: inherit;
- font-size: 0.85rem;
- max-width: var(--max-width);
- width: 100%;
- z-index: 2;
- font-family: var(--font-mono);
-}
-
-.description a {
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 0.5rem;
-}
-
-.description p {
- position: relative;
- margin: 0;
- padding: 1rem;
- background-color: rgba(var(--callout-rgb), 0.5);
- border: 1px solid rgba(var(--callout-border-rgb), 0.3);
- border-radius: var(--border-radius);
-}
-
-.code {
- font-weight: 700;
- font-family: var(--font-mono);
-}
-
-.hero {
- display: flex;
- position: relative;
- place-items: center;
-}
-
-.heroContent {
- display: flex;
- position: relative;
- z-index: 0;
- padding-bottom: 4rem;
- flex-direction: column;
- gap: 2rem;
- justify-content: space-between;
- align-items: center;
- width: auto;
- font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial,
- "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
- "Segoe UI Symbol", "Noto Color Emoji";
- padding-top: 48px;
-
- @media (min-width: 768px) {
- padding-top: 4rem;
- padding-bottom: 6rem;
- }
- @media (min-width: 1024px) {
- padding-top: 5rem;
- padding-bottom: 8rem;
- }
-}
-
-.logos {
- display: flex;
- z-index: 50;
- justify-content: center;
- align-items: center;
- width: 100%;
-}
-
-.grid {
- display: grid;
- grid-template-columns: repeat(4, minmax(25%, auto));
- max-width: 100%;
- width: var(--max-width);
-}
-
-.card {
- padding: 1rem 1.2rem;
- border-radius: var(--border-radius);
- background: rgba(var(--card-rgb), 0);
- border: 1px solid rgba(var(--card-border-rgb), 0);
- transition: background 200ms, border 200ms;
-}
-
-.card span {
- display: inline-block;
- transition: transform 200ms;
-}
-
-.card h2 {
- font-weight: 600;
- margin-bottom: 0.7rem;
-}
-
-.card p {
- margin: 0;
- opacity: 0.6;
- font-size: 0.9rem;
- line-height: 1.5;
- max-width: 30ch;
-}
-
-@media (prefers-reduced-motion) {
- .card:hover span {
- transform: none;
- }
-}
-
-/* Mobile */
-@media (max-width: 700px) {
- .content {
- padding: 4rem;
- }
-
- .grid {
- grid-template-columns: 1fr;
- margin-bottom: 120px;
- max-width: 320px;
- text-align: center;
- }
-
- .card {
- padding: 1rem 2.5rem;
- }
-
- .card h2 {
- margin-bottom: 0.5rem;
- }
-
- .center {
- padding: 8rem 0 6rem;
- }
-
- .center::before {
- transform: none;
- height: 300px;
- }
-
- .description {
- font-size: 0.8rem;
- }
-
- .description a {
- padding: 1rem;
- }
-
- .description p,
- .description div {
- display: flex;
- justify-content: center;
- position: fixed;
- width: 100%;
- }
-
- .description p {
- align-items: center;
- inset: 0 0 auto;
- padding: 2rem 1rem 1.4rem;
- border-radius: 0;
- border: none;
- border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
- background: linear-gradient(
- to bottom,
- rgba(var(--background-start-rgb), 1),
- rgba(var(--callout-rgb), 0.5)
- );
- background-clip: padding-box;
- backdrop-filter: blur(24px);
- }
-
- .description div {
- align-items: flex-end;
- pointer-events: none;
- inset: auto 0 0;
- padding: 2rem;
- height: 200px;
- background: linear-gradient(
- to bottom,
- transparent 0%,
- rgb(var(--background-end-rgb)) 40%
- );
- z-index: 1;
- }
-}
-
-/* Enable hover only on non-touch devices */
-@media (hover: hover) and (pointer: fine) {
- .card:hover {
- background: rgba(var(--card-rgb), 0.1);
- border: 1px solid rgba(var(--card-border-rgb), 0.15);
- }
-
- .card:hover span {
- transform: translateX(4px);
- }
-}
-
-.circles {
- position: absolute;
- min-width: 614px;
- min-height: 614px;
- pointer-events: none;
-}
-
-.logo {
- z-index: 50;
- width: 120px;
- height: 120px;
-}
-
-.logoGradientContainer {
- display: flex;
- position: absolute;
- z-index: 50;
- justify-content: center;
- align-items: center;
- width: 16rem;
- height: 16rem;
-}
-
-.turborepoWordmarkContainer {
- display: flex;
- z-index: 50;
- padding-left: 1.5rem;
- padding-right: 1.5rem;
- flex-direction: column;
- gap: 1.25rem;
- justify-content: center;
- align-items: center;
- text-align: center;
-
- @media (min-width: 1024px) {
- gap: 1.5rem;
- }
-}
-
-.turborepoWordmark {
- width: 160px;
- fill: white;
-
- @media (min-width: 768px) {
- width: 200px;
- }
-}
-
-.code {
- font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
- monospace;
- font-weight: 700;
-}
-
-/* Tablet and Smaller Desktop */
-@media (min-width: 701px) and (max-width: 1120px) {
- .grid {
- grid-template-columns: repeat(2, 50%);
- }
-}
-
-/* Gradients */
-.gradient {
- position: absolute;
- mix-blend-mode: normal;
- will-change: filter;
- pointer-events: none;
-}
-
-.gradientSmall {
- filter: blur(32px);
-}
-
-.gradientLarge {
- filter: blur(75px);
-}
-
-.glowConic {
- background-image: var(--glow-conic);
-}
-
-.logoGradient {
- opacity: 0.9;
- width: 120px;
- height: 120px;
-}
-
-.backgroundGradient {
- top: -500px;
- width: 1000px;
- height: 1000px;
- opacity: 0.15;
-}
-
-.button {
- background-color: #ffffff;
- border-radius: 8px;
- border-style: none;
- box-sizing: border-box;
- color: #000000;
- cursor: pointer;
- display: inline-block;
- font-size: 16px;
- height: 40px;
- line-height: 20px;
- list-style: none;
- margin: 0;
- outline: none;
- padding: 10px 16px;
- position: relative;
- text-align: center;
- text-decoration: none;
- transition: color 100ms;
- vertical-align: baseline;
- user-select: none;
- -webkit-user-select: none;
- touch-action: manipulation;
-}
-
-.button:hover,
-.button:focus {
- background-color: #e5e4e2;
-}
diff --git a/apps/docs/app/page.tsx b/apps/docs/app/page.tsx
deleted file mode 100644
index 5ca2020..0000000
--- a/apps/docs/app/page.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import Image from "next/image";
-import { Card } from "@repo/ui/card";
-import { Code } from "@repo/ui/code";
-import styles from "./page.module.css";
-import { Button } from "@repo/ui/button";
-
-function Gradient({
- conic,
- className,
- small,
-}: {
- small?: boolean;
- conic?: boolean;
- className?: string;
-}): JSX.Element {
- return (
-
- );
-}
-
-const LINKS = [
- {
- title: "Docs",
- href: "https://turbo.build/repo/docs",
- description: "Find in-depth information about Turborepo features and API.",
- },
- {
- title: "Learn",
- href: "https://turbo.build/repo/docs/handbook",
- description: "Learn more about monorepos with our handbook.",
- },
- {
- title: "Templates",
- href: "https://turbo.build/repo/docs/getting-started/from-example",
- description: "Choose from over 15 examples and deploy with a single click.",
- },
- {
- title: "Deploy",
- href: "https://vercel.com/new",
- description:
- "Instantly deploy your Turborepo to a shareable URL with Vercel.",
- },
-];
-
-export default function Page(): JSX.Element {
- return (
-
-
-
- examples/basic
- docs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {LINKS.map(({ title, href, description }) => (
-
- {description}
-
- ))}
-
-
- );
-}
diff --git a/apps/docs/next-env.d.ts b/apps/docs/next-env.d.ts
deleted file mode 100644
index 4f11a03..0000000
--- a/apps/docs/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/apps/docs/next.config.js b/apps/docs/next.config.js
deleted file mode 100644
index a5b0aec..0000000
--- a/apps/docs/next.config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/** @type {import('next').NextConfig} */
-module.exports = {
- transpilePackages: ["@repo/ui"],
-};
diff --git a/apps/docs/package.json b/apps/docs/package.json
deleted file mode 100644
index ad719a3..0000000
--- a/apps/docs/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "docs",
- "version": "1.0.0",
- "private": true,
- "scripts": {
- "dev": "next dev --port 3001",
- "build": "next build",
- "start": "next start",
- "lint": "eslint . --max-warnings 0"
- },
- "dependencies": {
- "@repo/ui": "*",
- "next": "^14.0.4",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@next/eslint-plugin-next": "^14.0.4",
- "@repo/eslint-config": "*",
- "@repo/typescript-config": "*",
- "@types/eslint": "^8.56.1",
- "@types/node": "^20.10.6",
- "@types/react": "^18.2.46",
- "@types/react-dom": "^18.2.18",
- "eslint": "^8.56.0",
- "typescript": "^5.3.3"
- }
-}
diff --git a/apps/docs/public/circles.svg b/apps/docs/public/circles.svg
deleted file mode 100644
index 6533be5..0000000
--- a/apps/docs/public/circles.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
\ No newline at end of file
diff --git a/apps/docs/public/turborepo.svg b/apps/docs/public/turborepo.svg
deleted file mode 100644
index 2f9aa1f..0000000
--- a/apps/docs/public/turborepo.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-
diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json
deleted file mode 100644
index 24e7548..0000000
--- a/apps/docs/tsconfig.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "extends": "@repo/typescript-config/nextjs.json",
- "compilerOptions": {
- "plugins": [
- {
- "name": "next"
- }
- ]
- },
- "include": [
- "next-env.d.ts",
- "next.config.js",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": ["node_modules"]
-}
diff --git a/apps/web/.eslintrc.js b/apps/web/.eslintrc.js
deleted file mode 100644
index 7d644a4..0000000
--- a/apps/web/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/** @type {import("eslint").Linter.Config} */
-module.exports = {
- root: true,
- extends: ["@repo/eslint-config/next.js"],
- parser: "@typescript-eslint/parser",
- parserOptions: {
- project: true,
- },
-};
diff --git a/apps/web/app/favicon.ico b/apps/web/app/favicon.ico
deleted file mode 100644
index 3f804c0..0000000
Binary files a/apps/web/app/favicon.ico and /dev/null differ
diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css
deleted file mode 100644
index 8eee6cb..0000000
--- a/apps/web/app/globals.css
+++ /dev/null
@@ -1,50 +0,0 @@
-:root {
- --max-width: 1100px;
- --border-radius: 12px;
- --font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
- "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
- "Fira Mono", "Droid Sans Mono", "Courier New", monospace;
-
- --foreground-rgb: 255, 255, 255;
- --background-start-rgb: 0, 0, 0;
- --background-end-rgb: 0, 0, 0;
-
- --callout-rgb: 20, 20, 20;
- --callout-border-rgb: 108, 108, 108;
- --card-rgb: 100, 100, 100;
- --card-border-rgb: 200, 200, 200;
-
- --glow-conic: conic-gradient(
- from 180deg at 50% 50%,
- #2a8af6 0deg,
- #a853ba 180deg,
- #e92a67 360deg
- );
-}
-
-* {
- box-sizing: border-box;
- padding: 0;
- margin: 0;
-}
-
-html,
-body {
- max-width: 100vw;
- overflow-x: hidden;
-}
-
-body {
- color: rgb(var(--foreground-rgb));
- background: linear-gradient(
- to bottom,
- transparent,
- rgb(var(--background-end-rgb))
- )
- rgb(var(--background-start-rgb));
-}
-
-a {
- color: inherit;
- text-decoration: none;
-}
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
deleted file mode 100644
index 5f90d11..0000000
--- a/apps/web/app/layout.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import "./globals.css";
-import type { Metadata } from "next";
-import { Inter } from "next/font/google";
-
-const inter = Inter({ subsets: ["latin"] });
-
-export const metadata: Metadata = {
- title: "Create Turborepo",
- description: "Generated by create turbo",
-};
-
-export default function RootLayout({
- children,
-}: {
- children: React.ReactNode;
-}): JSX.Element {
- return (
-
-
{children}
-
- );
-}
diff --git a/apps/web/app/page.module.css b/apps/web/app/page.module.css
deleted file mode 100644
index 98481c6..0000000
--- a/apps/web/app/page.module.css
+++ /dev/null
@@ -1,335 +0,0 @@
-.main {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- align-items: center;
- padding: 6rem;
- min-height: 100vh;
-}
-
-.vercelLogo {
- filter: invert(1);
-}
-
-.description {
- display: inherit;
- justify-content: inherit;
- align-items: inherit;
- font-size: 0.85rem;
- max-width: var(--max-width);
- width: 100%;
- z-index: 2;
- font-family: var(--font-mono);
-}
-
-.description a {
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 0.5rem;
-}
-
-.description p {
- position: relative;
- margin: 0;
- padding: 1rem;
- background-color: rgba(var(--callout-rgb), 0.5);
- border: 1px solid rgba(var(--callout-border-rgb), 0.3);
- border-radius: var(--border-radius);
-}
-
-.code {
- font-weight: 700;
- font-family: var(--font-mono);
-}
-
-.hero {
- display: flex;
- position: relative;
- place-items: center;
-}
-
-.heroContent {
- display: flex;
- position: relative;
- z-index: 0;
- padding-bottom: 4rem;
- flex-direction: column;
- gap: 2rem;
- justify-content: space-between;
- align-items: center;
- width: auto;
- font-family: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial,
- "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
- "Segoe UI Symbol", "Noto Color Emoji";
- padding-top: 48px;
-
- @media (min-width: 768px) {
- padding-top: 4rem;
- padding-bottom: 6rem;
- }
- @media (min-width: 1024px) {
- padding-top: 5rem;
- padding-bottom: 8rem;
- }
-}
-
-.logos {
- display: flex;
- z-index: 50;
- justify-content: center;
- align-items: center;
- width: 100%;
-}
-
-.grid {
- display: grid;
- grid-template-columns: repeat(4, minmax(25%, auto));
- max-width: 100%;
- width: var(--max-width);
-}
-
-.card {
- padding: 1rem 1.2rem;
- border-radius: var(--border-radius);
- background: rgba(var(--card-rgb), 0);
- border: 1px solid rgba(var(--card-border-rgb), 0);
- transition: background 200ms, border 200ms;
-}
-
-.card span {
- display: inline-block;
- transition: transform 200ms;
-}
-
-.card h2 {
- font-weight: 600;
- margin-bottom: 0.7rem;
-}
-
-.card p {
- margin: 0;
- opacity: 0.6;
- font-size: 0.9rem;
- line-height: 1.5;
- max-width: 30ch;
-}
-
-@media (prefers-reduced-motion) {
- .card:hover span {
- transform: none;
- }
-}
-
-/* Mobile */
-@media (max-width: 700px) {
- .content {
- padding: 4rem;
- }
-
- .grid {
- grid-template-columns: 1fr;
- margin-bottom: 120px;
- max-width: 320px;
- text-align: center;
- }
-
- .card {
- padding: 1rem 2.5rem;
- }
-
- .card h2 {
- margin-bottom: 0.5rem;
- }
-
- .center {
- padding: 8rem 0 6rem;
- }
-
- .center::before {
- transform: none;
- height: 300px;
- }
-
- .description {
- font-size: 0.8rem;
- }
-
- .description a {
- padding: 1rem;
- }
-
- .description p,
- .description div {
- display: flex;
- justify-content: center;
- position: fixed;
- width: 100%;
- }
-
- .description p {
- align-items: center;
- inset: 0 0 auto;
- padding: 2rem 1rem 1.4rem;
- border-radius: 0;
- border: none;
- border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
- background: linear-gradient(
- to bottom,
- rgba(var(--background-start-rgb), 1),
- rgba(var(--callout-rgb), 0.5)
- );
- background-clip: padding-box;
- backdrop-filter: blur(24px);
- }
-
- .description div {
- align-items: flex-end;
- pointer-events: none;
- inset: auto 0 0;
- padding: 2rem;
- height: 200px;
- background: linear-gradient(
- to bottom,
- transparent 0%,
- rgb(var(--background-end-rgb)) 40%
- );
- z-index: 1;
- }
-}
-
-/* Enable hover only on non-touch devices */
-@media (hover: hover) and (pointer: fine) {
- .card:hover {
- background: rgba(var(--card-rgb), 0.1);
- border: 1px solid rgba(var(--card-border-rgb), 0.15);
- }
-
- .card:hover span {
- transform: translateX(4px);
- }
-}
-
-.circles {
- position: absolute;
- min-width: 614px;
- min-height: 614px;
- pointer-events: none;
-}
-
-.logo {
- z-index: 50;
- width: 120px;
- height: 120px;
-}
-
-.logoGradientContainer {
- display: flex;
- position: absolute;
- z-index: 50;
- justify-content: center;
- align-items: center;
- width: 16rem;
- height: 16rem;
-}
-
-.turborepoWordmarkContainer {
- display: flex;
- z-index: 50;
- padding-left: 1.5rem;
- padding-right: 1.5rem;
- flex-direction: column;
- gap: 1.25rem;
- justify-content: center;
- align-items: center;
- text-align: center;
-
- @media (min-width: 1024px) {
- gap: 1.5rem;
- }
-}
-
-.turborepoWordmark {
- width: 160px;
- fill: white;
-
- @media (min-width: 768px) {
- width: 200px;
- }
-}
-
-.code {
- font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
- monospace;
- font-weight: 700;
-}
-
-/* Tablet and Smaller Desktop */
-@media (min-width: 701px) and (max-width: 1120px) {
- .grid {
- grid-template-columns: repeat(2, 50%);
- }
-}
-
-/* Gradients */
-.gradient {
- position: absolute;
- mix-blend-mode: normal;
- will-change: filter;
- pointer-events: none;
-}
-
-.gradientSmall {
- filter: blur(32px);
-}
-
-.gradientLarge {
- filter: blur(75px);
-}
-
-.glowConic {
- background-image: var(--glow-conic);
-}
-
-.logoGradient {
- opacity: 0.9;
- width: 120px;
- height: 120px;
-}
-
-.backgroundGradient {
- top: -500px;
- width: 1000px;
- height: 1000px;
- opacity: 0.15;
-}
-
-.button {
- background-color: #ffffff;
- border-radius: 8px;
- border-style: none;
- box-sizing: border-box;
- color: #000000;
- cursor: pointer;
- display: inline-block;
- font-size: 16px;
- height: 40px;
- line-height: 20px;
- list-style: none;
- margin: 0;
- outline: none;
- padding: 10px 16px;
- position: relative;
- text-align: center;
- text-decoration: none;
- transition: color 100ms;
- vertical-align: baseline;
- user-select: none;
- -webkit-user-select: none;
- touch-action: manipulation;
-}
-
-.button:hover,
-.button:focus {
- background-color: #e5e4e2;
-}
diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx
deleted file mode 100644
index 95186e8..0000000
--- a/apps/web/app/page.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import Image from "next/image";
-import { Card } from "@repo/ui/card";
-import { Code } from "@repo/ui/code";
-import styles from "./page.module.css";
-import { Button } from "@repo/ui/button";
-
-function Gradient({
- conic,
- className,
- small,
-}: {
- small?: boolean;
- conic?: boolean;
- className?: string;
-}): JSX.Element {
- return (
-
- );
-}
-
-const LINKS = [
- {
- title: "Docs",
- href: "https://turbo.build/repo/docs",
- description: "Find in-depth information about Turborepo features and API.",
- },
- {
- title: "Learn",
- href: "https://turbo.build/repo/docs/handbook",
- description: "Learn more about monorepos with our handbook.",
- },
- {
- title: "Templates",
- href: "https://turbo.build/repo/docs/getting-started/from-example",
- description: "Choose from over 15 examples and deploy with a single click.",
- },
- {
- title: "Deploy",
- href: "https://vercel.com/new",
- description:
- "Instantly deploy your Turborepo to a shareable URL with Vercel.",
- },
-];
-
-export default function Page(): JSX.Element {
- return (
-
-
-
- examples/basic
- web
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {LINKS.map(({ title, href, description }) => (
-
- {description}
-
- ))}
-
-
- );
-}
diff --git a/apps/web/next-env.d.ts b/apps/web/next-env.d.ts
deleted file mode 100644
index 4f11a03..0000000
--- a/apps/web/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/apps/web/next.config.js b/apps/web/next.config.js
deleted file mode 100644
index a5b0aec..0000000
--- a/apps/web/next.config.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/** @type {import('next').NextConfig} */
-module.exports = {
- transpilePackages: ["@repo/ui"],
-};
diff --git a/apps/web/package.json b/apps/web/package.json
deleted file mode 100644
index cd92122..0000000
--- a/apps/web/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "web",
- "version": "1.0.0",
- "private": true,
- "scripts": {
- "dev": "next dev",
- "build": "next build",
- "start": "next start",
- "lint": "eslint . --max-warnings 0"
- },
- "dependencies": {
- "@repo/ui": "*",
- "next": "^14.0.4",
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
- },
- "devDependencies": {
- "@next/eslint-plugin-next": "^14.0.4",
- "@repo/eslint-config": "*",
- "@repo/typescript-config": "*",
- "@types/eslint": "^8.56.1",
- "@types/node": "^20.10.6",
- "@types/react": "^18.2.46",
- "@types/react-dom": "^18.2.18",
- "eslint": "^8.56.0",
- "typescript": "^5.3.3"
- }
-}
diff --git a/apps/web/public/circles.svg b/apps/web/public/circles.svg
deleted file mode 100644
index 6533be5..0000000
--- a/apps/web/public/circles.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
\ No newline at end of file
diff --git a/apps/web/public/next.svg b/apps/web/public/next.svg
deleted file mode 100644
index 5174b28..0000000
--- a/apps/web/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/apps/web/public/turborepo.svg b/apps/web/public/turborepo.svg
deleted file mode 100644
index 2f9aa1f..0000000
--- a/apps/web/public/turborepo.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-
diff --git a/apps/web/public/vercel.svg b/apps/web/public/vercel.svg
deleted file mode 100644
index d2f8422..0000000
--- a/apps/web/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
deleted file mode 100644
index 24e7548..0000000
--- a/apps/web/tsconfig.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "extends": "@repo/typescript-config/nextjs.json",
- "compilerOptions": {
- "plugins": [
- {
- "name": "next"
- }
- ]
- },
- "include": [
- "next-env.d.ts",
- "next.config.js",
- "**/*.ts",
- "**/*.tsx",
- ".next/types/**/*.ts"
- ],
- "exclude": ["node_modules"]
-}
diff --git a/bun.lockb b/bun.lockb
index 8640756..35aa7a1 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/examples/with-next-and-wagmi/.gitignore b/examples/with-next-and-wagmi/.gitignore
new file mode 100644
index 0000000..8f322f0
--- /dev/null
+++ b/examples/with-next-and-wagmi/.gitignore
@@ -0,0 +1,35 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/examples/with-next-and-wagmi/README.md b/examples/with-next-and-wagmi/README.md
new file mode 100644
index 0000000..bd3aa7b
--- /dev/null
+++ b/examples/with-next-and-wagmi/README.md
@@ -0,0 +1 @@
+This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-wagmi`](https://github.com/wevm/wagmi/tree/main/packages/create-wagmi).
diff --git a/examples/with-next-and-wagmi/next.config.js b/examples/with-next-and-wagmi/next.config.js
new file mode 100644
index 0000000..767719f
--- /dev/null
+++ b/examples/with-next-and-wagmi/next.config.js
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {}
+
+module.exports = nextConfig
diff --git a/examples/with-next-and-wagmi/package.json b/examples/with-next-and-wagmi/package.json
new file mode 100644
index 0000000..9d4a693
--- /dev/null
+++ b/examples/with-next-and-wagmi/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "with-next-and-wagmi",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@tanstack/react-query": "5.0.5",
+ "next": "13.5.3",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "viem": "latest",
+ "wagmi": "latest"
+ },
+ "devDependencies": {
+ "@evmos/dappstore-sdk": "workspace:*",
+ "@types/node": "^20.7.2",
+ "@types/react": "^18.2.22",
+ "@types/react-dom": "^18.2.7",
+ "@wagmi/cli": "latest",
+ "bufferutil": "^4.0.7",
+ "encoding": "^0.1.13",
+ "lokijs": "^1.5.12",
+ "pino-pretty": "^10.2.0",
+ "supports-color": "^9.4.0",
+ "typescript": "^5.2.2",
+ "utf-8-validate": "^6.0.3"
+ }
+}
diff --git a/examples/with-next-and-wagmi/src/app/globals.css b/examples/with-next-and-wagmi/src/app/globals.css
new file mode 100644
index 0000000..0733a7e
--- /dev/null
+++ b/examples/with-next-and-wagmi/src/app/globals.css
@@ -0,0 +1,21 @@
+:root {
+ background-color: #181818;
+ color: rgba(255, 255, 255, 0.87);
+ color-scheme: light dark;
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ font-synthesis: none;
+ font-weight: 400;
+ line-height: 1.5;
+ text-rendering: optimizeLegibility;
+
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ background-color: #f8f8f8;
+ color: #181818;
+ }
+}
diff --git a/examples/with-next-and-wagmi/src/app/layout.tsx b/examples/with-next-and-wagmi/src/app/layout.tsx
new file mode 100644
index 0000000..c591052
--- /dev/null
+++ b/examples/with-next-and-wagmi/src/app/layout.tsx
@@ -0,0 +1,23 @@
+import "./globals.css";
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import { Suspense, type ReactNode } from "react";
+
+import { Providers } from "./providers";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "Create Wagmi",
+ description: "Generated by create-wagmi",
+};
+
+export default function RootLayout(props: { children: ReactNode }) {
+ return (
+
+
+ {props.children}
+
+
+ );
+}
diff --git a/examples/with-next-and-wagmi/src/app/page.tsx b/examples/with-next-and-wagmi/src/app/page.tsx
new file mode 100644
index 0000000..2670194
--- /dev/null
+++ b/examples/with-next-and-wagmi/src/app/page.tsx
@@ -0,0 +1,93 @@
+"use client";
+
+import { client, dAppstoreClient, provider } from "@/wagmi";
+import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
+import { useEffect, useState, useSyncExternalStore } from "react";
+const createAccountStore = () => {
+ let accounts: string[] = [];
+ const listeners = new Set<(accounts: string[]) => void>();
+ provider.request({ method: "eth_requestAccounts" }).then((_accounts) => {
+ accounts = _accounts;
+ console.log("eth_accounts", _accounts);
+ listeners.forEach((listener) => listener(_accounts));
+ });
+
+ provider.on("accountsChanged", (_accounts) => {
+ console.log("accountsChanged", _accounts);
+ accounts = _accounts;
+ listeners.forEach((listener) => listener(_accounts));
+ });
+ return {
+ getAccounts: () => accounts,
+ subscribe: (callback: (accounts: string[]) => void) => {
+ listeners.add(callback);
+ return () => {
+ listeners.delete(callback);
+ };
+ },
+ };
+};
+const accountStore = createAccountStore();
+// const useAccount = () => {
+// const [accounts, setAccounts] = useState([]);
+// useEffect(() => {
+// provider.request({ method: "eth_accounts" }).then((accounts) => {
+// setAccounts(accounts);
+// });
+// const listener = (accounts: string[]) => {
+// setAccounts(accounts);
+// };
+// provider.on("accountsChanged", listener);
+
+// return () => {
+// provider.removeListener("accountsChanged", listener);
+// };
+// }, []);
+// return accounts;
+// };
+
+const useChainId = () => {
+ const [chainId, setChainId] = useState(null);
+ useEffect(() => {
+ provider.request({ method: "eth_chainId" }).then((chainId) => {
+ setChainId(chainId);
+ });
+
+ const listener = (chainId: string) => {
+ setChainId(chainId);
+ };
+ provider.on("chainChanged", listener);
+
+ return () => {
+ provider.removeListener("chainChanged", listener);
+ };
+ }, []);
+ return chainId;
+};
+
+function App() {
+ const accounts = useSyncExternalStore(
+ accountStore.subscribe,
+ accountStore.getAccounts,
+ accountStore.getAccounts
+ );
+ const chainId = useChainId();
+
+ return (
+ <>
+
+
Account
+
+ Address:{" "}
+ {accounts
+ ?.map((address) => `${address.slice(0, 4)}...${address.slice(-8)}`)
+ .join(", ")}
+
+ Chain ID: {chainId}
+
+
+ >
+ );
+}
+
+export default App;
diff --git a/examples/with-next-and-wagmi/src/app/providers.tsx b/examples/with-next-and-wagmi/src/app/providers.tsx
new file mode 100644
index 0000000..d4ba95f
--- /dev/null
+++ b/examples/with-next-and-wagmi/src/app/providers.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { useState, type ReactNode } from "react";
+import { WagmiProvider } from "wagmi";
+
+import {} from "@/wagmi";
+
+export function Providers(props: { children: ReactNode }) {
+ const [queryClient] = useState(
+ () =>
+ new QueryClient({
+ defaultOptions: {
+ queries: {
+ refetchOnMount: true,
+ },
+ },
+ })
+ );
+
+ return (
+
+ {props.children}
+
+ );
+}
diff --git a/examples/with-next-and-wagmi/src/wagmi.ts b/examples/with-next-and-wagmi/src/wagmi.ts
new file mode 100644
index 0000000..92c4563
--- /dev/null
+++ b/examples/with-next-and-wagmi/src/wagmi.ts
@@ -0,0 +1,7 @@
+import { createDAppstoreClient } from "@evmos/dappstore-sdk";
+import { createWalletClient, custom } from "viem";
+export const dAppstoreClient = createDAppstoreClient();
+export const provider = dAppstoreClient.provider;
+export const client = createWalletClient({
+ transport: custom(provider),
+});
diff --git a/examples/with-next-and-wagmi/tsconfig.json b/examples/with-next-and-wagmi/tsconfig.json
new file mode 100644
index 0000000..e59724b
--- /dev/null
+++ b/examples/with-next-and-wagmi/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/examples/with-next/.gitignore b/examples/with-next/.gitignore
new file mode 100644
index 0000000..fd3dbb5
--- /dev/null
+++ b/examples/with-next/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/apps/web/README.md b/examples/with-next/README.md
similarity index 55%
rename from apps/web/README.md
rename to examples/with-next/README.md
index 3d7b63a..c403366 100644
--- a/apps/web/README.md
+++ b/examples/with-next/README.md
@@ -1,28 +1,36 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
## Getting Started
First, run the development server:
```bash
+npm run dev
+# or
yarn dev
+# or
+pnpm dev
+# or
+bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
-To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello).
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/examples/with-next/next.config.mjs b/examples/with-next/next.config.mjs
new file mode 100644
index 0000000..4678774
--- /dev/null
+++ b/examples/with-next/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/examples/with-next/package.json b/examples/with-next/package.json
new file mode 100644
index 0000000..7a2b06d
--- /dev/null
+++ b/examples/with-next/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "with-next",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "react": "^18",
+ "react-dom": "^18",
+ "next": "14.1.0"
+ },
+ "devDependencies": {
+ "@evmos/dappstore-sdk": "workspace:*",
+ "typescript": "^5",
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "autoprefixer": "^10.0.1",
+ "postcss": "^8",
+ "tailwindcss": "^3.3.0"
+ }
+}
diff --git a/examples/with-next/postcss.config.js b/examples/with-next/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/examples/with-next/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/apps/docs/public/next.svg b/examples/with-next/public/next.svg
similarity index 100%
rename from apps/docs/public/next.svg
rename to examples/with-next/public/next.svg
diff --git a/apps/docs/public/vercel.svg b/examples/with-next/public/vercel.svg
similarity index 100%
rename from apps/docs/public/vercel.svg
rename to examples/with-next/public/vercel.svg
diff --git a/examples/with-next/src/app/favicon.ico b/examples/with-next/src/app/favicon.ico
new file mode 100644
index 0000000..718d6fe
Binary files /dev/null and b/examples/with-next/src/app/favicon.ico differ
diff --git a/examples/with-next/src/app/globals.css b/examples/with-next/src/app/globals.css
new file mode 100644
index 0000000..875c01e
--- /dev/null
+++ b/examples/with-next/src/app/globals.css
@@ -0,0 +1,33 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+ --foreground-rgb: 0, 0, 0;
+ --background-start-rgb: 214, 219, 220;
+ --background-end-rgb: 255, 255, 255;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --foreground-rgb: 255, 255, 255;
+ --background-start-rgb: 0, 0, 0;
+ --background-end-rgb: 0, 0, 0;
+ }
+}
+
+body {
+ color: rgb(var(--foreground-rgb));
+ background: linear-gradient(
+ to bottom,
+ transparent,
+ rgb(var(--background-end-rgb))
+ )
+ rgb(var(--background-start-rgb));
+}
+
+@layer utilities {
+ .text-balance {
+ text-wrap: balance;
+ }
+}
diff --git a/apps/docs/app/layout.tsx b/examples/with-next/src/app/layout.tsx
similarity index 79%
rename from apps/docs/app/layout.tsx
rename to examples/with-next/src/app/layout.tsx
index 5f90d11..3314e47 100644
--- a/apps/docs/app/layout.tsx
+++ b/examples/with-next/src/app/layout.tsx
@@ -1,19 +1,19 @@
-import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
+import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
- title: "Create Turborepo",
- description: "Generated by create turbo",
+ title: "Create Next App",
+ description: "Generated by create next app",
};
export default function RootLayout({
children,
-}: {
+}: Readonly<{
children: React.ReactNode;
-}): JSX.Element {
+}>) {
return (
{children}
diff --git a/examples/with-next/src/app/page.tsx b/examples/with-next/src/app/page.tsx
new file mode 100644
index 0000000..09d4d1a
--- /dev/null
+++ b/examples/with-next/src/app/page.tsx
@@ -0,0 +1,40 @@
+"use client";
+import Image from "next/image";
+import { createDAppstoreClient } from "@evmos/dappstore-sdk";
+
+const client = createDAppstoreClient();
+function App() {
+ // const [host, setState] = useState(0);
+
+ return (
+
+
+
+ );
+}
+
+export default function Home() {
+ return (
+
+
+
+ );
+}
diff --git a/examples/with-next/tailwind.config.ts b/examples/with-next/tailwind.config.ts
new file mode 100644
index 0000000..e9a0944
--- /dev/null
+++ b/examples/with-next/tailwind.config.ts
@@ -0,0 +1,20 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ content: [
+ "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
+ "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
+ "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: {
+ backgroundImage: {
+ "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
+ "gradient-conic":
+ "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
+ },
+ },
+ },
+ plugins: [],
+};
+export default config;
diff --git a/examples/with-next/tsconfig.json b/examples/with-next/tsconfig.json
new file mode 100644
index 0000000..7b28589
--- /dev/null
+++ b/examples/with-next/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/examples/with-tailwind/.gitignore b/examples/with-tailwind/.gitignore
new file mode 100644
index 0000000..468f82a
--- /dev/null
+++ b/examples/with-tailwind/.gitignore
@@ -0,0 +1,175 @@
+# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
+
+# Logs
+
+logs
+_.log
+npm-debug.log_
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+.pnpm-debug.log*
+
+# Caches
+
+.cache
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+
+report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
+
+# Runtime data
+
+pids
+_.pid
+_.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+
+lib-cov
+
+# Coverage directory used by tools like istanbul
+
+coverage
+*.lcov
+
+# nyc test coverage
+
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+
+bower_components
+
+# node-waf configuration
+
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+
+build/Release
+
+# Dependency directories
+
+node_modules/
+jspm_packages/
+
+# Snowpack dependency directory (https://snowpack.dev/)
+
+web_modules/
+
+# TypeScript cache
+
+*.tsbuildinfo
+
+# Optional npm cache directory
+
+.npm
+
+# Optional eslint cache
+
+.eslintcache
+
+# Optional stylelint cache
+
+.stylelintcache
+
+# Microbundle cache
+
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+
+.node_repl_history
+
+# Output of 'npm pack'
+
+*.tgz
+
+# Yarn Integrity file
+
+.yarn-integrity
+
+# dotenv environment variable files
+
+.env
+.env.development.local
+.env.test.local
+.env.production.local
+.env.local
+
+# parcel-bundler cache (https://parceljs.org/)
+
+.parcel-cache
+
+# Next.js build output
+
+.next
+out
+
+# Nuxt.js build / generate output
+
+.nuxt
+dist
+
+# Gatsby files
+
+# Comment in the public line in if your project uses Gatsby and not Next.js
+
+# https://nextjs.org/blog/next-9-1#public-directory-support
+
+# public
+
+# vuepress build output
+
+.vuepress/dist
+
+# vuepress v2.x temp and cache directory
+
+.temp
+
+# Docusaurus cache and generated files
+
+.docusaurus
+
+# Serverless directories
+
+.serverless/
+
+# FuseBox cache
+
+.fusebox/
+
+# DynamoDB Local files
+
+.dynamodb/
+
+# TernJS port file
+
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+
+.vscode-test
+
+# yarn v2
+
+.yarn/cache
+.yarn/unplugged
+.yarn/build-state.yml
+.yarn/install-state.gz
+.pnp.*
+
+# IntelliJ based IDEs
+.idea
+
+# Finder (MacOS) folder config
+.DS_Store
diff --git a/examples/with-tailwind/README.md b/examples/with-tailwind/README.md
new file mode 100644
index 0000000..b5a0e62
--- /dev/null
+++ b/examples/with-tailwind/README.md
@@ -0,0 +1,15 @@
+# @evmos/demo-with-tailwind
+
+To install dependencies:
+
+```bash
+bun install
+```
+
+To run:
+
+```bash
+bun run index.ts
+```
+
+This project was created using `bun init` in bun v1.0.25. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
diff --git a/examples/with-tailwind/package.json b/examples/with-tailwind/package.json
new file mode 100644
index 0000000..d42b168
--- /dev/null
+++ b/examples/with-tailwind/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "@evmos/demo-with-tailwind",
+ "type": "module",
+ "devDependencies": {},
+ "peerDependencies": {
+ "typescript": "^5.0.0"
+ },
+ "dependencies": {
+ "autoprefixer": "^10.4.17",
+ "postcss": "^8.4.34",
+ "tailwindcss": "^3.4.1"
+ }
+}
diff --git a/examples/with-tailwind/postcss.config.js b/examples/with-tailwind/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/examples/with-tailwind/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/examples/with-tailwind/src/index.css b/examples/with-tailwind/src/index.css
new file mode 100644
index 0000000..65dd5f6
--- /dev/null
+++ b/examples/with-tailwind/src/index.css
@@ -0,0 +1 @@
+@tailwind utilities;
diff --git a/examples/with-tailwind/src/index.tsx b/examples/with-tailwind/src/index.tsx
new file mode 100644
index 0000000..1d8a0f9
--- /dev/null
+++ b/examples/with-tailwind/src/index.tsx
@@ -0,0 +1,54 @@
+import "./index.css";
+import { useEffect } from "react";
+import { useAccount, useReadContracts } from "wagmi";
+import { erc20Abi, formatUnits } from "viem";
+// import { createClient } from "@evmos/dappstore-sdk";
+const EVMOS_ERC20_ADDRESS = "0xD4949664cD82660AaE99bEdc034a0deA8A0bd517";
+// const client = createClient();
+export default function Widget() {
+ const { address, isConnected } = useAccount();
+
+ const {
+ data: ercTokenBalance,
+ error,
+ isFetching,
+ } = useReadContracts({
+ allowFailure: false,
+ contracts: [
+ {
+ address: EVMOS_ERC20_ADDRESS,
+ abi: erc20Abi,
+ functionName: "balanceOf",
+ args: address ? [address] : undefined,
+ },
+ {
+ address: EVMOS_ERC20_ADDRESS,
+ abi: erc20Abi,
+ functionName: "decimals",
+ },
+ ],
+ });
+
+ // useEffect(() => {
+ // // console.log(client);
+ // client.request("ping");
+ // return client.subscribe();
+ // }, []);
+ const shortenedAddress = address
+ ? `${address.slice(0, 4)}...${address.slice(-4)}`
+ : null;
+
+ return (
+
+
Hello, {isConnected ? shortenedAddress : "World!"}
+ {isFetching &&
Loading balance
}
+ {ercTokenBalance && (
+
+ Your Evmos Balance is:{" "}
+ {formatUnits(ercTokenBalance[0], ercTokenBalance[1])}
+
+ )}
+ {error &&
Error: {error.name}
}
+
+ );
+}
diff --git a/examples/with-tailwind/tailwind.config.js b/examples/with-tailwind/tailwind.config.js
new file mode 100644
index 0000000..cb70e6e
--- /dev/null
+++ b/examples/with-tailwind/tailwind.config.js
@@ -0,0 +1,14 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ prefix: "wg-",
+ content: ["./src/**/*.{js,ts,jsx,tsx}"],
+ theme: {
+ extend: {
+ colors: {
+ testcolor: "purple",
+ },
+ },
+ },
+
+ plugins: [],
+};
diff --git a/examples/with-tailwind/tsconfig.json b/examples/with-tailwind/tsconfig.json
new file mode 100644
index 0000000..0ac23d5
--- /dev/null
+++ b/examples/with-tailwind/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "target": "ESNext",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "noUncheckedIndexedAccess": true,
+ "declaration": true,
+ "declarationMap": true,
+
+ "isolatedModules": true,
+ "outDir": "dist",
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist"],
+}
diff --git a/examples/with-vite/.eslintrc.cjs b/examples/with-vite/.eslintrc.cjs
new file mode 100644
index 0000000..d6c9537
--- /dev/null
+++ b/examples/with-vite/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/examples/with-vite/.gitignore b/examples/with-vite/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/examples/with-vite/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/with-vite/README.md b/examples/with-vite/README.md
new file mode 100644
index 0000000..0d6babe
--- /dev/null
+++ b/examples/with-vite/README.md
@@ -0,0 +1,30 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default {
+ // other rules...
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+}
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/examples/with-vite/index.html b/examples/with-vite/index.html
new file mode 100644
index 0000000..e4b78ea
--- /dev/null
+++ b/examples/with-vite/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/examples/with-vite/package.json b/examples/with-vite/package.json
new file mode 100644
index 0000000..1f20c60
--- /dev/null
+++ b/examples/with-vite/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "with-vite",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@evmos/dappstore-sdk": "workspace:*",
+ "@types/react": "^18.2.55",
+ "@types/react-dom": "^18.2.19",
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
+ "@typescript-eslint/parser": "^6.21.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "eslint": "^8.56.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "typescript": "^5.2.2",
+ "vite": "^5.1.0"
+ }
+}
diff --git a/examples/with-vite/public/vite.svg b/examples/with-vite/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/examples/with-vite/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/with-vite/src/App.css b/examples/with-vite/src/App.css
new file mode 100644
index 0000000..b9d355d
--- /dev/null
+++ b/examples/with-vite/src/App.css
@@ -0,0 +1,42 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/examples/with-vite/src/App.tsx b/examples/with-vite/src/App.tsx
new file mode 100644
index 0000000..17e6cc6
--- /dev/null
+++ b/examples/with-vite/src/App.tsx
@@ -0,0 +1,25 @@
+import { useState } from "react";
+import reactLogo from "./assets/react.svg";
+import viteLogo from "/vite.svg";
+import "./App.css";
+import { trpcClient } from "@evmos/dappstore-sdk-router/client";
+function App() {
+ const [count, setCount] = useState(0);
+
+ return (
+
+
+
+ );
+}
+
+export default App;
diff --git a/examples/with-vite/src/assets/react.svg b/examples/with-vite/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/examples/with-vite/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/with-vite/src/index.css b/examples/with-vite/src/index.css
new file mode 100644
index 0000000..6119ad9
--- /dev/null
+++ b/examples/with-vite/src/index.css
@@ -0,0 +1,68 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/examples/with-vite/src/main.tsx b/examples/with-vite/src/main.tsx
new file mode 100644
index 0000000..3d7150d
--- /dev/null
+++ b/examples/with-vite/src/main.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/examples/with-vite/src/vite-env.d.ts b/examples/with-vite/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/examples/with-vite/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/with-vite/tsconfig.json b/examples/with-vite/tsconfig.json
new file mode 100644
index 0000000..a7fc6fb
--- /dev/null
+++ b/examples/with-vite/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/examples/with-vite/tsconfig.node.json b/examples/with-vite/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/examples/with-vite/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/examples/with-vite/vite.config.ts b/examples/with-vite/vite.config.ts
new file mode 100644
index 0000000..5a33944
--- /dev/null
+++ b/examples/with-vite/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/package.json b/package.json
index db783f9..50c4cd4 100644
--- a/package.json
+++ b/package.json
@@ -1,24 +1,34 @@
{
- "name": "dappstore",
+ "name": "dappstore-sdk",
"private": true,
"scripts": {
- "build": "turbo build",
+ "build": "turbo build --filter=./packages/*",
"dev": "turbo dev",
"lint": "turbo lint",
- "format": "prettier --write \"**/*.{ts,tsx,md}\""
+ "format": "prettier --write \"**/*.{ts,tsx,md}\"",
+ "dev:setup-cli": "npm link"
},
"devDependencies": {
- "@repo/eslint-config": "*",
- "@repo/typescript-config": "*",
+ "@evmos/dappstore-cli": "workspace:*",
+ "@evmos/config": "workspace:*",
+ "@types/bun": "^1.0.4",
+ "autoprefixer": "^10.4.17",
+ "postcss": "^8.4.35",
"prettier": "^3.1.1",
+ "tailwindcss": "^3.4.1",
"turbo": "latest"
},
"engines": {
"node": ">=18"
},
- "packageManager": "bun@1.0.25",
+ "bin": {
+ "dappstore": "./"
+ },
"workspaces": [
- "apps/*",
- "packages/*"
- ]
+ "packages/*",
+ "examples/*"
+ ],
+ "dependencies": {
+ "next": "^14.1.0"
+ }
}
diff --git a/packages/dappstore-cli/build.ts b/packages/dappstore-cli/build.ts
new file mode 100644
index 0000000..ec3dcea
--- /dev/null
+++ b/packages/dappstore-cli/build.ts
@@ -0,0 +1,30 @@
+// @ts-nocheck
+import Bun from "bun";
+import { dependencies, peerDependencies } from "./package.json";
+import { version } from "./package.json";
+import { watch } from "node:fs";
+export const build = async () =>
+ await Bun.build({
+ entrypoints: ["./src/index.ts"],
+ target: "node",
+ format: "esm",
+ external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)],
+ outdir: "./dist",
+ });
+const test = await build();
+
+if (process.argv.includes("--watch")) {
+ const srcWatcher = watch(
+ `${import.meta.dir}/src`,
+ { recursive: true },
+ async (event, filename) => {
+ await build();
+
+ console.log(`Detected ${event} in ${filename} (src)`);
+ }
+ );
+ process.on("SIGINT", () => {
+ srcWatcher.close();
+ process.exit(0);
+ });
+}
diff --git a/packages/dappstore-cli/package.json b/packages/dappstore-cli/package.json
new file mode 100644
index 0000000..d46b81d
--- /dev/null
+++ b/packages/dappstore-cli/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "@evmos/dappstore-cli",
+ "version": "0.0.0",
+ "private": false,
+ "type": "module",
+ "main": "dist/index.js",
+ "scripts": {
+ "build": "bun run ./build.ts"
+ },
+ "bin": {
+ "dappstore": "./dist/index.js"
+ },
+ "peerDependencies": {},
+ "devDependencies": {
+ "@evmos/dappstore-sdk": "workspace:*",
+ "@evmos/config": "workspace:*",
+ "@types/eslint": "^8.56.1",
+ "@types/node": "^20.10.6",
+ "@types/react": "^18.2.46",
+ "@types/react-dom": "^18.2.18",
+ "eslint": "^8.56.0",
+ "react": "^18.2.0",
+ "typescript": "^5.3.3",
+ "@commander-js/extra-typings": "^11.1.0"
+ },
+ "dependencies": {
+ "@evmos/dev-wrapper": "workspace:*",
+ "@types/express": "^4.17.21",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.17",
+ "chalk": "^5.3.0",
+ "clsx": "^2.1.0",
+ "express": "^4.18.2",
+ "glob": "^10.3.10",
+ "postcss": "^8.4.33",
+ "postcss-scopify": "^0.1.10",
+ "react-dom": "^18.2.0",
+ "tailwindcss": "^3.4.1",
+ "ts-dedent": "^2.2.0",
+ "vite": "^5.0.12"
+ }
+}
diff --git a/packages/dappstore-cli/postcss.config.js b/packages/dappstore-cli/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/packages/dappstore-cli/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/packages/dappstore-cli/src/dev.ts b/packages/dappstore-cli/src/dev.ts
new file mode 100644
index 0000000..70afdc7
--- /dev/null
+++ b/packages/dappstore-cli/src/dev.ts
@@ -0,0 +1,20 @@
+import { program } from "@commander-js/extra-typings";
+import { serve } from "@evmos/dev-wrapper/serve/serve.js";
+
+program
+ .command("dev")
+ .option("-p, --port ", "Development server port", "1337")
+ .option(
+ "-t, --target ",
+ "The port or url of your widget server",
+ "3000"
+ )
+
+ .action(async ({ port, target }) => {
+ const app = serve({
+ target,
+ });
+ app.listen(port, () => {
+ console.log(`Example app listening on port http://localhost:${port}`);
+ });
+ });
diff --git a/packages/dappstore-cli/src/index.d.ts b/packages/dappstore-cli/src/index.d.ts
new file mode 100644
index 0000000..636e1e3
--- /dev/null
+++ b/packages/dappstore-cli/src/index.d.ts
@@ -0,0 +1,4 @@
+#!/usr/bin/env node
+import "./dev.js";
+import "./build.js";
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/packages/dappstore-cli/src/index.ts b/packages/dappstore-cli/src/index.ts
new file mode 100644
index 0000000..a1ca3c7
--- /dev/null
+++ b/packages/dappstore-cli/src/index.ts
@@ -0,0 +1,5 @@
+#!/usr/bin/env node
+import "./dev";
+
+import { program } from "@commander-js/extra-typings";
+program.parseAsync(process.argv);
diff --git a/packages/dappstore-cli/tailwind.config.js b/packages/dappstore-cli/tailwind.config.js
new file mode 100644
index 0000000..93d0b65
--- /dev/null
+++ b/packages/dappstore-cli/tailwind.config.js
@@ -0,0 +1,33 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ["./src/**/*.{js,jsx,ts,tsx}"],
+ theme: {
+ extend: {
+ colors: {
+ background: {
+ // background: rgba(10, 10, 10, 1);
+ DEFAULT: "rgba(10 10 10 / )",
+ },
+ foreground: {
+ // background: rgba(237, 224, 220, 1);
+ DEFAULT: "rgba(237 224 220 / )",
+ },
+ surface: {
+ // rgba(20, 17, 15, 1)
+ DEFAULT: "rgba(20 17 15 / )",
+ },
+ primary: {
+ DEFAULT: "rgba(208 75 0 / )",
+ container: "rgba(250 92 0 / )",
+ },
+ body: {
+ DEFAULT: "rgba(180 169 165 / )",
+ },
+ heading: {
+ DEFAULT: "rgba(250 239 235 / )",
+ },
+ },
+ },
+ },
+ plugins: [],
+};
diff --git a/packages/dappstore-cli/tsconfig.json b/packages/dappstore-cli/tsconfig.json
new file mode 100644
index 0000000..0ca48f0
--- /dev/null
+++ b/packages/dappstore-cli/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "@evmos/config/base.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "emitDeclarationOnly": true,
+
+ "target": "ESNext",
+ "moduleResolution": "NodeNext",
+ "module": "NodeNext"
+ },
+ "include": ["./src/**/*", "./src/**/*.d.ts"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/packages/dappstore-sdk/build.ts b/packages/dappstore-sdk/build.ts
new file mode 100644
index 0000000..e1a9aac
--- /dev/null
+++ b/packages/dappstore-sdk/build.ts
@@ -0,0 +1,35 @@
+// @ts-nocheck
+import Bun from "bun";
+import { dependencies, peerDependencies } from "./package.json";
+import { version } from "./package.json";
+import { watch } from "node:fs";
+export const build = async () =>
+ await Bun.build({
+ entrypoints: ["./src/index.ts", "./src/host.ts"],
+ target: "browser",
+ format: "esm",
+ external: [...Object.keys(dependencies), ...Object.keys(peerDependencies)],
+ define: {
+ ["process.env.npm_package_version"]: JSON.stringify(version),
+ },
+ outdir: "./dist",
+ });
+
+await build();
+if (process.argv.includes("--watch")) {
+ const srcWatcher = watch(
+ `${import.meta.dir}/src`,
+ { recursive: true },
+ async (event, filename) => {
+ await build();
+
+ console.log(`Detected ${event} in ${filename} (src)`);
+ }
+ );
+ process.on("SIGINT", () => {
+ srcWatcher.close();
+ process.exit(0);
+ });
+} else {
+ await build();
+}
diff --git a/packages/dappstore-sdk/package.json b/packages/dappstore-sdk/package.json
new file mode 100644
index 0000000..78de921
--- /dev/null
+++ b/packages/dappstore-sdk/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "@evmos/dappstore-sdk",
+ "version": "0.0.0",
+ "type": "module",
+ "sideEffects": false,
+ "private": false,
+ "scripts": {
+ "build:types": "tsc -p ./tsconfig.json",
+ "dev:types": "tsc -p ./tsconfig.json --watch",
+ "dev": "bun run --watch ./build.ts --watch & bun run dev:types",
+ "build": "bun run ./build.ts & tsc"
+ },
+ "exports": {
+ ".": {
+ "import": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ }
+ },
+ "./internal/host": {
+ "types": "./dist/host.d.ts",
+ "import": "./dist/host.js"
+ }
+ },
+ "devDependencies": {
+ "@evmos/config": "workspace:*",
+ "@types/node": "^20.10.6",
+ "@types/react": "^18.2.46",
+ "@types/react-dom": "^18.2.18",
+ "typescript": "^5.3.3",
+ "@trpc/client": "next",
+ "@trpc/react-query": "next",
+ "@trpc/server": "next",
+ "@types/lodash-es": "^4.17.12",
+ "@types/uuid": "^9.0.8",
+ "lodash-es": "^4.17.21",
+ "uuid": "^9.0.1"
+ },
+ "peerDependencies": {
+ "viem": ">=2.5",
+ "wagmi": ">=2.5",
+ "zod": ">=3"
+ },
+ "dependencies": {}
+}
diff --git a/packages/dappstore-sdk/src/client.ts b/packages/dappstore-sdk/src/client.ts
new file mode 100644
index 0000000..8b68045
--- /dev/null
+++ b/packages/dappstore-sdk/src/client.ts
@@ -0,0 +1,168 @@
+import { createHost } from "./host";
+import { trpcClient } from "./trpc/client";
+
+import {
+ EIP1193Provider,
+ ProviderConnectInfo,
+ ProviderRpcError,
+ ProviderMessage,
+} from "./types/EIP1193Provider";
+import { Hex, EIP1193Provider as StronglyTypedEIP1193Provider } from "viem";
+class SDKProvider implements StronglyTypedEIP1193Provider {
+ unsubscribers: Record> = {};
+ on(
+ event: "accountsChanged",
+ listener: (accounts: string[]) => void
+ ): SDKProvider;
+ on(event: "chainChanged", listener: (chainId: string) => void): SDKProvider;
+ on(
+ event: "connect",
+ listener: (connectInfo: ProviderConnectInfo) => void
+ ): SDKProvider;
+ on(
+ event: "disconnect",
+ listener: (error: ProviderRpcError) => void
+ ): SDKProvider;
+ on(
+ event: "message",
+ listener: (message: ProviderMessage) => void
+ ): SDKProvider;
+ on(event: string, listener: (...args: any[]) => void): SDKProvider {
+ if (
+ event === "accountsChanged" ||
+ event === "chainChanged" ||
+ event === "connect"
+ // event === "disconnect" ||
+ // event === "message"
+ ) {
+ const { unsubscribe } = trpcClient.provider.on[event].subscribe(
+ undefined,
+ {
+ onData(data) {
+ listener(data);
+ },
+ }
+ );
+ const unsubMap = this.unsubscribers[event] || new Map();
+ unsubMap.set(listener, unsubscribe);
+ this.unsubscribers[event] = unsubMap;
+ }
+
+ return this;
+ }
+
+ removeListener(
+ event: string,
+ callback: (...args: any[]) => void
+ ): EIP1193Provider {
+ this.unsubscribers[event]?.get(callback)?.();
+ this.unsubscribers[event]?.delete(callback);
+ return this;
+ }
+ request: StronglyTypedEIP1193Provider["request"] = (args) => {
+ if (typeof window === "undefined") {
+ throw new Error("Cannot call request outside of browser");
+ }
+ return trpcClient.provider.request.mutate(args as never) as never;
+ };
+}
+
+class Client {
+ private _host: null | ReturnType = null;
+ private _listeners: Record> = {};
+ private _provider = new SDKProvider();
+ private _ready = false;
+ private _chainId: Hex | null = null;
+ private _accounts: Hex[] = [];
+ private _state: "uninitialized" | "ready" | "error" = "uninitialized";
+ get ready() {
+ return this._ready;
+ }
+ get accounts() {
+ return this._accounts;
+ }
+ get chainId() {
+ return this._chainId;
+ }
+
+ get provider() {
+ return this._provider;
+ }
+ private get isInsideIframe() {
+ try {
+ return window.self !== window.top;
+ } catch (e) {
+ return true;
+ }
+ }
+ init() {
+ if (this.isInsideIframe === false) {
+ throw new Error("Cannot use DAppstore SDK outside of an iframe");
+ }
+ this.ack();
+ const unsubAccounts = trpcClient.provider.on.accountsChanged.subscribe(
+ undefined,
+ {
+ onData: (data) => {
+ this._accounts = data;
+ if (this._listeners.accountsChanged) {
+ this._listeners.accountsChanged.forEach((listener) => {
+ listener(data);
+ });
+ }
+ },
+ }
+ );
+
+ const unsubChain = trpcClient.provider.on.chainChanged.subscribe(
+ undefined,
+ {
+ onData: (data) => {
+ this._chainId = data;
+ if (this._listeners.chainChanged) {
+ this._listeners.chainChanged.forEach((listener) => {
+ listener(data);
+ });
+ }
+ },
+ }
+ );
+ return () => {
+ unsubAccounts.unsubscribe();
+ unsubChain.unsubscribe();
+ };
+ }
+ onAccountsChange(cb: (accounts: string[]) => void) {
+ if (!this._listeners.accountsChanged) {
+ this._listeners.accountsChanged = new Set();
+ }
+ this._listeners.accountsChanged.add(cb);
+ return () => {
+ this._listeners.accountsChanged?.delete(cb);
+ };
+ }
+
+ onChainChange(cb: (chainId: string) => void) {
+ if (!this._listeners.chainChanged) {
+ this._listeners.chainChanged = new Set();
+ }
+ this._listeners.chainChanged.add(cb);
+ return () => {
+ this._listeners.chainChanged?.delete(cb);
+ };
+ }
+ async ack() {
+ const { state } = await trpcClient.ack.query({
+ version: process.env.npm_package_version as string,
+ });
+ this._state = "ready";
+ this._accounts = state.accounts;
+ this._chainId = state.chainId;
+ }
+}
+
+export const createDAppstoreClient = ({ autoInit = true } = {}) => {
+ const client = new Client();
+ if (autoInit) client.init();
+ return client;
+};
diff --git a/packages/dappstore-sdk/src/host.ts b/packages/dappstore-sdk/src/host.ts
new file mode 100644
index 0000000..fba5e8f
--- /dev/null
+++ b/packages/dappstore-sdk/src/host.ts
@@ -0,0 +1,13 @@
+import { createPostMessageHost } from "./post-message-integration/create-post-message-host";
+import { createHostRouter } from "./trpc/host";
+
+type Config = {
+ target: Window;
+ provider: unknown;
+};
+export const createHost = ({ provider, target }: Config) => {
+ return createPostMessageHost({
+ target,
+ router: createHostRouter(provider),
+ });
+};
diff --git a/packages/dappstore-sdk/src/index.ts b/packages/dappstore-sdk/src/index.ts
new file mode 100644
index 0000000..52ed12b
--- /dev/null
+++ b/packages/dappstore-sdk/src/index.ts
@@ -0,0 +1,2 @@
+export { createDAppstoreClient } from "./client";
+export * from "./types/EIP1193Provider";
diff --git a/packages/dappstore-sdk/src/post-message-integration/create-post-message-host.ts b/packages/dappstore-sdk/src/post-message-integration/create-post-message-host.ts
new file mode 100644
index 0000000..34bb6bb
--- /dev/null
+++ b/packages/dappstore-sdk/src/post-message-integration/create-post-message-host.ts
@@ -0,0 +1,261 @@
+import {
+ AnyRouter,
+ TRPCError,
+ callProcedure,
+ getErrorShape,
+ getTRPCErrorFromUnknown,
+ transformTRPCResponse,
+} from "@trpc/server";
+import {
+ TRPCClientOutgoingMessage,
+ TRPCRequestMessage,
+ TRPCResponseMessage,
+ parseTRPCMessage,
+} from "@trpc/server/rpc";
+import { isString } from "lodash-es";
+import { z } from "zod";
+import { isObservable } from "@trpc/server/observable";
+
+export const createPostMessageHost = ({
+ router,
+ target,
+}: {
+ router: TRouter;
+ target: Window;
+}) => {
+ const { transformer } = router._def._config;
+
+ function respond(targetId: string, untransformedJSON: TRPCResponseMessage) {
+ target.postMessage(
+ {
+ source: "dappstore-sdk-router",
+ target: targetId,
+ messages: [
+ transformTRPCResponse(router._def._config, untransformedJSON),
+ ],
+ },
+ "*"
+ );
+ }
+ async function handleSubsription(
+ targetId: string,
+ msg: TRPCClientOutgoingMessage
+ ) {
+ const { id, jsonrpc } = msg;
+ if (msg.method === "subscription.stop") {
+ // TODO: "handle stop";
+
+ respond(targetId, {
+ id,
+ jsonrpc,
+ result: {
+ type: "stopped",
+ },
+ });
+ return;
+ }
+
+ const { path, input } = msg.params;
+ const type = msg.method;
+
+ try {
+ const result = await callProcedure({
+ procedures: router._def.procedures,
+ path,
+ getRawInput: async () => input,
+ ctx: {},
+ type,
+ });
+ if (!isObservable(result)) {
+ throw new TRPCError({
+ message: `Subscription ${path} did not return an observable`,
+ code: "INTERNAL_SERVER_ERROR",
+ });
+ }
+
+ const observable = result;
+ // TODO: Do we ever need to manually unsubscribe here?
+ const subscription = observable.subscribe({
+ next(data) {
+ respond(targetId, {
+ id,
+ jsonrpc,
+ result: {
+ type: "data",
+ data,
+ },
+ });
+ },
+ error(err) {
+ const error = getTRPCErrorFromUnknown(err);
+
+ respond(targetId, {
+ id,
+ jsonrpc,
+ error: getErrorShape({
+ config: router._def._config,
+ error,
+ type,
+ path,
+ input,
+ ctx: {},
+ }),
+ });
+ },
+ complete() {
+ respond(targetId, {
+ id,
+ jsonrpc,
+ result: {
+ type: "stopped",
+ },
+ });
+ },
+ });
+
+ respond(targetId, {
+ id,
+ jsonrpc,
+ result: {
+ type: "started",
+ },
+ });
+ } catch (cause) {
+ const error = getTRPCErrorFromUnknown(cause);
+
+ respond(targetId, {
+ id,
+ jsonrpc,
+ error: getErrorShape({
+ config: router._def._config,
+ error,
+ type,
+ path,
+ input,
+ ctx: {},
+ }),
+ });
+ }
+ }
+ async function handleMessage(
+ targetId: string,
+ msg: TRPCClientOutgoingMessage
+ ) {
+ // const { id, jsonrpc } = msg;
+ if (msg.id === null) {
+ throw new TRPCError({
+ code: "BAD_REQUEST",
+ message: "`id` is required",
+ });
+ }
+
+ if (msg.method === "subscription" || msg.method === "subscription.stop") {
+ return handleSubsription(targetId, msg);
+ }
+ handleRequest(targetId, msg);
+ }
+ async function handleRequest(targetId: string, msg: TRPCRequestMessage) {
+ const { id, jsonrpc } = msg;
+
+ const { path, input } = msg.params;
+ const type = msg.method;
+
+ try {
+ // await ctxPromise;
+ const result = await callProcedure({
+ procedures: router._def.procedures,
+ path,
+ getRawInput: async () => input,
+ ctx: {},
+ type,
+ });
+
+ respond(targetId, {
+ id,
+ jsonrpc,
+ result: {
+ type: "data",
+ data: result,
+ },
+ });
+ return;
+ } catch (cause) {
+ const error = getTRPCErrorFromUnknown(cause);
+ // opts.onError?.({ error, path, type, ctx, req, input });
+ respond(targetId, {
+ id,
+ jsonrpc,
+ error: getErrorShape({
+ config: router._def._config,
+ error,
+ type,
+ path,
+ input,
+ ctx: {},
+ }),
+ });
+ }
+ }
+
+ const listener = async (event: MessageEvent) => {
+ if (
+ event.data?.source === "react-devtools-content-script" ||
+ event.data?.target === "metamask-inpage"
+ )
+ return;
+ if (event.source !== target) {
+ return;
+ }
+ const targetId = event.data?.clientId;
+
+ if (!isString(targetId)) {
+ return;
+ }
+
+ try {
+ const parsed = z
+ .object({
+ target: z.literal("dappstore-sdk-router"),
+ clientId: z.string(),
+ messages: z.array(z.unknown()),
+ })
+ .safeParse(event.data);
+
+ if (!parsed.success) return;
+
+ const message = parsed.data.messages;
+
+ const promises = message
+ .map((raw) => parseTRPCMessage(raw, transformer))
+ .map((message) => handleMessage(targetId, message));
+ await Promise.all(promises);
+ } catch (cause) {
+ const error = new TRPCError({
+ code: "PARSE_ERROR",
+ cause,
+ });
+
+ respond(targetId, {
+ id: null,
+ error: getErrorShape({
+ config: router._def._config,
+ error,
+ type: "unknown",
+ path: undefined,
+ input: undefined,
+ ctx: undefined,
+ }),
+ });
+ }
+ };
+
+ if (typeof window === "undefined") {
+ return () => {};
+ }
+
+ window.addEventListener("message", listener, false);
+
+ return () => {
+ window.removeEventListener("message", listener);
+ };
+};
diff --git a/packages/dappstore-sdk/src/post-message-integration/post-message-link.ts b/packages/dappstore-sdk/src/post-message-integration/post-message-link.ts
new file mode 100644
index 0000000..463b60e
--- /dev/null
+++ b/packages/dappstore-sdk/src/post-message-integration/post-message-link.ts
@@ -0,0 +1,178 @@
+import { Operation, TRPCClientError, TRPCLink } from "@trpc/client";
+import { observable } from "@trpc/server/observable";
+import type { CombinedDataTransformer } from "@trpc/server";
+/**
+ * TRPC doesn't recommend importing unstable-core-do-not-import,
+ * but unfortunately, they also don't offer an official API for creating custom links.
+ * we need to be mindful on updates, but I imagine typescript checks would report any major change.
+ */
+import {
+ type TRPCClientIncomingRequest,
+ type TRPCResponseMessage,
+ type AnyRouter,
+ type DataTransformerOptions,
+ type TRPCClientOutgoingMessage,
+ type TRPCRequestMessage,
+ transformResult,
+} from "@trpc/server/unstable-core-do-not-import";
+import { getTransformer } from "@trpc/client/unstable-internals";
+
+import { v4 } from "uuid";
+import { debounce } from "lodash-es";
+import { z } from "zod";
+
+type PostMessageOptions = {
+ transformer?: DataTransformerOptions;
+};
+class PostMessageClient {
+ id = v4();
+
+ outgoing: TRPCClientOutgoingMessage[] = [];
+ pendingRequests: Map<
+ TRPCRequestMessage["id"],
+ (data: TRPCResponseMessage) => void
+ > = new Map();
+
+ constructor() {}
+ request = (
+ op: Operation,
+ resolve: (data: TRPCResponseMessage) => void,
+ observer: {
+ complete: () => void;
+ }
+ ) => {
+ const { type, input, path, id } = op;
+
+ const envelope: TRPCRequestMessage = {
+ id: v4(),
+ method: type,
+ params: {
+ input,
+ path,
+ },
+ };
+ this.pendingRequests.set(envelope.id, resolve);
+ this.outgoing.push(envelope);
+
+ this.dispatch();
+
+ return () => {
+ this.outgoing = this.outgoing.filter((msg) => msg.id !== envelope.id);
+ observer.complete();
+ if (op.type === "subscription") {
+ this.outgoing.push({
+ id,
+ method: "subscription.stop",
+ });
+ this.dispatch();
+ }
+ };
+ };
+
+ dispatch = debounce(
+ () => {
+ if (typeof window === "undefined") return;
+ window.parent.postMessage(
+ {
+ target: "dappstore-sdk-router",
+ clientId: this.id,
+ messages: this.outgoing,
+ },
+ "*"
+ );
+ console.log("dispatched", this.outgoing);
+
+ this.outgoing = [];
+ },
+ 100,
+ {
+ maxWait: 300,
+ }
+ );
+
+ handleIncomingRequest = (request: TRPCClientIncomingRequest) => {
+ // TODO: handle incoming request
+ throw new Error("Not implemented");
+ };
+ handleIncomingResponse = (response: TRPCResponseMessage) => {
+ const resolve = this.pendingRequests.get(response.id);
+ if (!resolve) {
+ return;
+ }
+
+ resolve(response);
+ };
+ subscribe = () => {
+ const listener = (event: MessageEvent) => {
+ const parsed = z
+ .object({
+ source: z.literal("dappstore-sdk-router"),
+ target: z.string(),
+ messages: z.array(z.unknown()),
+ })
+ .safeParse(event.data);
+
+ if (!parsed.success || parsed.data.target !== this.id) {
+ return;
+ }
+
+ parsed.data.messages.forEach((message: any) => {
+ if ("method" in message) {
+ this.handleIncomingRequest(message);
+ } else {
+ this.handleIncomingResponse(message);
+ }
+ });
+ };
+ if (typeof window === "undefined") return () => {};
+
+ window.addEventListener("message", listener, false);
+ return () => {
+ window.removeEventListener("message", listener);
+ };
+ };
+}
+
+export const postMessageLink = (
+ opts: PostMessageOptions = {}
+): TRPCLink => {
+ const transformer = getTransformer(opts.transformer);
+ const client = new PostMessageClient();
+ client.subscribe();
+ return () => {
+ return ({ op }) => {
+ const { type, path, id, context } = op;
+
+ const input = transformer.input.serialize(op.input);
+
+ return observable((observer) => {
+ const unsubscribe = client.request(
+ {
+ type,
+ path,
+ input,
+ id,
+ context,
+ },
+ (data) => {
+ const transformed = transformResult(
+ data,
+ transformer.output
+ );
+
+ if (!transformed.ok) {
+ observer.error(TRPCClientError.from(transformed.error));
+ return;
+ }
+ observer.next(transformed);
+ if (op.type === "subscription") return;
+ observer.complete();
+ unsubscribe();
+ },
+ observer
+ );
+ return unsubscribe;
+ });
+ };
+ };
+};
diff --git a/packages/dappstore-sdk/src/trpc/client.ts b/packages/dappstore-sdk/src/trpc/client.ts
new file mode 100644
index 0000000..0ab9795
--- /dev/null
+++ b/packages/dappstore-sdk/src/trpc/client.ts
@@ -0,0 +1,10 @@
+import { createTRPCClient } from "@trpc/client";
+import type { CreateTRPCClient } from "@trpc/client";
+
+import type { HostRouter } from "./host.js";
+
+import { postMessageLink } from "../post-message-integration/post-message-link.js";
+export const trpcClient: CreateTRPCClient =
+ createTRPCClient({
+ links: [postMessageLink({})],
+ });
diff --git a/packages/dappstore-sdk/src/trpc/host.ts b/packages/dappstore-sdk/src/trpc/host.ts
new file mode 100644
index 0000000..21e3175
--- /dev/null
+++ b/packages/dappstore-sdk/src/trpc/host.ts
@@ -0,0 +1,77 @@
+import { initTRPC } from "@trpc/server";
+import { z } from "zod";
+import { observable } from "@trpc/server/observable";
+import { EIP1193Provider, Hex, ProviderConnectInfo } from "viem";
+
+const t = initTRPC.create({
+ allowOutsideOfServer: true,
+});
+
+export const createHostRouter = (provider: unknown) => {
+ const _provider: EIP1193Provider = provider as EIP1193Provider;
+ const providerRouter = t.router({
+ on: t.router({
+ accountsChanged: t.procedure.subscription((a) => {
+ return observable((emit) => {
+ _provider.on("accountsChanged", (accounts) => {
+ emit.next(accounts);
+ });
+ });
+ }),
+
+ chainChanged: t.procedure.subscription((a) => {
+ return observable((emit) => {
+ _provider.on("chainChanged", (chainId) => {
+ emit.next(chainId as Hex);
+ });
+ });
+ }),
+ connect: t.procedure.subscription((a) => {
+ return observable((emit) => {
+ _provider.on("connect", (...args) => {
+ emit.next(...args);
+ });
+ });
+ }),
+ }),
+
+ request: t.procedure
+ .input(
+ z
+ .object({
+ method: z.string(),
+ params: z.array(z.unknown()).or(z.object({})).optional(),
+ })
+ .readonly()
+ )
+ .mutation((opts) => {
+ return _provider.request(opts.input as never);
+ }),
+ });
+
+ return t.router({
+ ack: t.procedure
+ .input(
+ z.object({
+ version: z.string(),
+ })
+ )
+ .query(async () => {
+ const accounts = await _provider.request({
+ method: "eth_requestAccounts",
+ });
+ const chainId = await _provider.request({ method: "eth_chainId" });
+ return {
+ version: process.env.npm_package_version as string,
+ state: {
+ accounts,
+ chainId,
+ },
+ };
+ }),
+
+ provider: providerRouter,
+ });
+};
+
+export type HostRouter = ReturnType;
diff --git a/packages/dappstore-sdk/src/types/EIP1193Provider.ts b/packages/dappstore-sdk/src/types/EIP1193Provider.ts
new file mode 100644
index 0000000..a50281d
--- /dev/null
+++ b/packages/dappstore-sdk/src/types/EIP1193Provider.ts
@@ -0,0 +1,45 @@
+export interface RequestArguments {
+ readonly method: string;
+ readonly params?: readonly unknown[] | object;
+}
+export interface ProviderConnectInfo {
+ readonly chainId: string;
+}
+export interface ProviderRpcError extends Error {
+ message: string;
+ code: number;
+ data?: unknown;
+}
+export interface ProviderMessage {
+ readonly type: string;
+ readonly data: unknown;
+}
+export type ProviderChainChangedListener = (chainId: string) => void;
+export type ProviderAccountsChangedListener = (accounts: string[]) => void;
+export type ProviderConnectListener = (
+ connectInfo: ProviderConnectInfo
+) => void;
+export type ProviderDisconnectListener = (error: ProviderRpcError) => void;
+export type ProviderMessageListener = (message: ProviderMessage) => void;
+export interface EIP1193Provider {
+ on(
+ event: "accountsChanged",
+ listener: ProviderAccountsChangedListener
+ ): EIP1193Provider;
+ on(
+ event: "chainChanged",
+ listener: ProviderChainChangedListener
+ ): EIP1193Provider;
+ on(event: "connect", listener: ProviderConnectListener): EIP1193Provider;
+ on(
+ event: "disconnect",
+ listener: ProviderDisconnectListener
+ ): EIP1193Provider;
+ on(event: "message", listener: ProviderMessageListener): EIP1193Provider;
+
+ removeListener(
+ event: string,
+ callback: (data: unknown) => void
+ ): EIP1193Provider;
+ request(args: RequestArguments): Promise;
+}
diff --git a/packages/dappstore-sdk/tsconfig.json b/packages/dappstore-sdk/tsconfig.json
new file mode 100644
index 0000000..66bd5b8
--- /dev/null
+++ b/packages/dappstore-sdk/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "@evmos/config/base.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "emitDeclarationOnly": true,
+ "declaration": true,
+ "declarationMap": true
+ },
+ "include": ["./src/**/*"],
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/packages/dev-wrapper/.eslintrc.cjs b/packages/dev-wrapper/.eslintrc.cjs
new file mode 100644
index 0000000..d6c9537
--- /dev/null
+++ b/packages/dev-wrapper/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/packages/dev-wrapper/.gitignore b/packages/dev-wrapper/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/packages/dev-wrapper/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/packages/dev-wrapper/README.md b/packages/dev-wrapper/README.md
new file mode 100644
index 0000000..0d6babe
--- /dev/null
+++ b/packages/dev-wrapper/README.md
@@ -0,0 +1,30 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
+
+- Configure the top-level `parserOptions` property like this:
+
+```js
+export default {
+ // other rules...
+ parserOptions: {
+ ecmaVersion: 'latest',
+ sourceType: 'module',
+ project: ['./tsconfig.json', './tsconfig.node.json'],
+ tsconfigRootDir: __dirname,
+ },
+}
+```
+
+- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
+- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
+- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
diff --git a/packages/dev-wrapper/index.html b/packages/dev-wrapper/index.html
new file mode 100644
index 0000000..191e59e
--- /dev/null
+++ b/packages/dev-wrapper/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+ DAppStore Widget Development Kit
+
+
+
+ {{ENV_SCRIPT}}
+
+
+
diff --git a/packages/dev-wrapper/package.json b/packages/dev-wrapper/package.json
new file mode 100644
index 0000000..782b262
--- /dev/null
+++ b/packages/dev-wrapper/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@evmos/dev-wrapper",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "exports": {
+ "./*": "./dist/*"
+ },
+ "scripts": {
+ "dev": "tsc --watch & tsc -p ./tsconfig.serve.json --watch & vite build --watch --outDir ./dist/app",
+ "build": "tsc && tsc -p ./tsconfig.serve.json && vite build --outDir ./dist/app",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "clsx": "^2.1.0",
+ "express": "^4.18.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@evmos/dappstore-sdk": "workspace:*",
+ "@types/react": "^18.2.55",
+ "@types/react-dom": "^18.2.19",
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
+ "@typescript-eslint/parser": "^6.21.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "eslint": "^8.56.0",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "typescript": "^5.2.2",
+ "vite": "^5.1.0"
+ }
+}
diff --git a/packages/dev-wrapper/postcss.config.js b/packages/dev-wrapper/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/packages/dev-wrapper/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/packages/dev-wrapper/public/vite.svg b/packages/dev-wrapper/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/packages/dev-wrapper/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/dev-wrapper/serve.ts b/packages/dev-wrapper/serve.ts
new file mode 100644
index 0000000..a16bbe8
--- /dev/null
+++ b/packages/dev-wrapper/serve.ts
@@ -0,0 +1,27 @@
+import { fileURLToPath } from "url";
+import express from "express";
+import path from "path";
+import { readFileSync } from "fs";
+const __dirname = fileURLToPath(new URL("./", import.meta.url));
+
+export const serve = ({ target }: { target: string }) => {
+ const targetUrl = target.startsWith("http")
+ ? target
+ : `http://localhost:${target}`;
+
+ const app = express();
+ const envScript = ``;
+ const index = readFileSync(
+ path.join(__dirname, "../app/index.html"),
+ "utf-8"
+ ).replace("{{ENV_SCRIPT}}", envScript);
+
+ app.get("/", (req, res) => {
+ if (req.originalUrl === "/") {
+ res.end(index);
+ }
+ });
+ app.use(express.static(path.join(__dirname, "../app")));
+
+ return app;
+};
diff --git a/packages/dev-wrapper/src/App.css b/packages/dev-wrapper/src/App.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/packages/dev-wrapper/src/App.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/packages/dev-wrapper/src/App.tsx b/packages/dev-wrapper/src/App.tsx
new file mode 100644
index 0000000..c367163
--- /dev/null
+++ b/packages/dev-wrapper/src/App.tsx
@@ -0,0 +1,171 @@
+import React, { useEffect, useState } from "react";
+import { WagmiProvider } from "wagmi";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { useConnect, useChainId, useSwitchChain } from "wagmi";
+import { useDisconnect } from "wagmi";
+import { useAccount, useConnections } from "wagmi";
+import { type EIP1193Provider } from "viem";
+import { EvmosLogo } from "./EvmosLogo.js";
+import { config } from "./config.js";
+
+import { createHost } from "@evmos/dappstore-sdk/internal/host";
+
+import cx from "clsx";
+
+const Header = () => {
+ return (
+
+ );
+};
+export function WalletOptions() {
+ const { connectors, connect, isPending } = useConnect();
+ const { disconnect } = useDisconnect();
+ const { isConnected, address } = useAccount();
+ const shortenedAddress = address
+ ? `${address.slice(0, 6)}...${address.slice(-4)}`
+ : "";
+ if (isConnected) {
+ return (
+
+ );
+ }
+
+ return connectors.map((connector) => (
+
+ ));
+}
+
+function Networks() {
+ // const { address, isConnecting } = useAccount();
+ // const {} = useConfig();
+ const chainId = useChainId();
+ const { chains, switchChain, isPending } = useSwitchChain();
+
+ return (
+
+ {chains.map((chain) => (
+
+ ))}
+
+ Testnet Faucet
+
+
+
+ );
+}
+
+const WidgetArea = () => {
+ const connections = useConnections();
+ const ref = React.useRef(null);
+ const [provider, setProvider] = useState(null);
+ const [url] = useState(() => {
+ if (typeof window === "undefined") {
+ return "";
+ }
+ if (!("__ENV__" in window)) {
+ return "";
+ }
+ return (window.__ENV__ as Record).TARGET || "";
+ });
+ useEffect(() => {
+ const connection = connections[0];
+ if (!connection) {
+ setProvider(null);
+ return;
+ }
+ if (!("getProvider" in connection.connector)) {
+ setProvider(null);
+ return;
+ }
+ connection.connector.getProvider().then((p) => {
+ console.log(p);
+ setProvider(p as EIP1193Provider);
+ });
+ }, [connections]);
+
+ useEffect(() => {
+ if (!provider || !ref.current) {
+ return;
+ }
+ return createHost({
+ provider,
+ target: ref.current.contentWindow as Window,
+ });
+ }, [ref, provider]);
+
+ if (!provider) {
+ return Connect to a wallet
;
+ }
+
+ return ;
+};
+
+export const App = () => {
+ const [queryClient] = React.useState(new QueryClient());
+
+ return (
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/dev-wrapper/src/EvmosLogo.tsx b/packages/dev-wrapper/src/EvmosLogo.tsx
new file mode 100644
index 0000000..7e5f669
--- /dev/null
+++ b/packages/dev-wrapper/src/EvmosLogo.tsx
@@ -0,0 +1,48 @@
+export const EvmosLogo = () => {
+ return (
+
+ );
+};
diff --git a/packages/dev-wrapper/src/assets/react.svg b/packages/dev-wrapper/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/packages/dev-wrapper/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/dev-wrapper/src/config.tsx b/packages/dev-wrapper/src/config.tsx
new file mode 100644
index 0000000..20033ea
--- /dev/null
+++ b/packages/dev-wrapper/src/config.tsx
@@ -0,0 +1,51 @@
+import { http, createConfig } from "wagmi";
+import { evmos } from "wagmi/chains";
+import { injected } from "wagmi/connectors";
+import { Chain, Hex } from "viem";
+
+// const url = "http://localhost:3000";
+const evmosmainnet: Chain = {
+ ...evmos,
+ name: "Evmos",
+ contracts: {
+ multicall3: {
+ address: "0xca11bde05977b3631167028862be2a173976ca11" as Hex,
+ },
+ },
+ rpcUrls: {
+ default: { http: ["https://evmos.lava.build"] },
+ public: { http: ["https://evmos.lava.build"] },
+ },
+};
+const evmostestnet: Chain = {
+ ...evmos,
+ name: "Evmos Testnet",
+ id: 9000,
+
+ contracts: {
+ multicall3: {
+ address: "0xca11bde05977b3631167028862be2a173976ca11" as Hex,
+ },
+ },
+ rpcUrls: {
+ default: {
+ http: [`https://evmos-testnet.lava.build`],
+ },
+ public: {
+ http: [`https://evmos-testnet.lava.build`],
+ },
+ },
+};
+export const config = createConfig({
+ chains: [evmosmainnet, evmostestnet],
+ transports: {
+ [evmosmainnet.id]: http(),
+ [evmostestnet.id]: http(),
+ },
+ multiInjectedProviderDiscovery: false,
+ connectors: [
+ injected({
+ target: "metaMask",
+ }),
+ ],
+});
diff --git a/packages/dev-wrapper/src/declaration.d.ts b/packages/dev-wrapper/src/declaration.d.ts
new file mode 100644
index 0000000..b39f36e
--- /dev/null
+++ b/packages/dev-wrapper/src/declaration.d.ts
@@ -0,0 +1,4 @@
+declare module "_widget_dir_" {
+ const Widget: React.FC;
+ export default Widget;
+}
diff --git a/packages/dev-wrapper/src/index.css b/packages/dev-wrapper/src/index.css
new file mode 100644
index 0000000..6119ad9
--- /dev/null
+++ b/packages/dev-wrapper/src/index.css
@@ -0,0 +1,68 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/packages/dev-wrapper/src/main.tsx b/packages/dev-wrapper/src/main.tsx
new file mode 100644
index 0000000..149af86
--- /dev/null
+++ b/packages/dev-wrapper/src/main.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { App } from "./App.tsx";
+import "./App.css";
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
+
+
+
+);
diff --git a/packages/dev-wrapper/src/vite-env.d.ts b/packages/dev-wrapper/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/packages/dev-wrapper/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/packages/dev-wrapper/tailwind.config.js b/packages/dev-wrapper/tailwind.config.js
new file mode 100644
index 0000000..6b3829a
--- /dev/null
+++ b/packages/dev-wrapper/tailwind.config.js
@@ -0,0 +1,33 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
+ theme: {
+ extend: {
+ colors: {
+ background: {
+ // background: rgba(10, 10, 10, 1);
+ DEFAULT: "rgba(10 10 10 / )",
+ },
+ foreground: {
+ // background: rgba(237, 224, 220, 1);
+ DEFAULT: "rgba(237 224 220 / )",
+ },
+ surface: {
+ // rgba(20, 17, 15, 1)
+ DEFAULT: "rgba(20 17 15 / )",
+ },
+ primary: {
+ DEFAULT: "rgba(208 75 0 / )",
+ container: "rgba(250 92 0 / )",
+ },
+ body: {
+ DEFAULT: "rgba(180 169 165 / )",
+ },
+ heading: {
+ DEFAULT: "rgba(250 239 235 / )",
+ },
+ },
+ },
+ },
+ plugins: [],
+};
diff --git a/packages/dev-wrapper/tsconfig.json b/packages/dev-wrapper/tsconfig.json
new file mode 100644
index 0000000..72fc627
--- /dev/null
+++ b/packages/dev-wrapper/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src", "serve.ts"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/packages/dev-wrapper/tsconfig.node.json b/packages/dev-wrapper/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/packages/dev-wrapper/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/packages/dev-wrapper/tsconfig.serve.json b/packages/dev-wrapper/tsconfig.serve.json
new file mode 100644
index 0000000..67c6673
--- /dev/null
+++ b/packages/dev-wrapper/tsconfig.serve.json
@@ -0,0 +1,8 @@
+{
+ "extends": "@evmos/config/base.json",
+ "compilerOptions": {
+ "noEmit": false,
+ "outDir": "./dist/serve"
+ },
+ "include": ["./serve.ts"]
+}
diff --git a/packages/dev-wrapper/vite.config.ts b/packages/dev-wrapper/vite.config.ts
new file mode 100644
index 0000000..495433f
--- /dev/null
+++ b/packages/dev-wrapper/vite.config.ts
@@ -0,0 +1,12 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ // build: {
+ // watch: {
+ // exclude: "node_modules/**",
+ // },
+ // },
+});
diff --git a/packages/eslint-config/README.md b/packages/eslint-config/README.md
deleted file mode 100644
index 8b42d90..0000000
--- a/packages/eslint-config/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# `@turbo/eslint-config`
-
-Collection of internal eslint configurations.
diff --git a/packages/eslint-config/library.js b/packages/eslint-config/library.js
deleted file mode 100644
index c667cd1..0000000
--- a/packages/eslint-config/library.js
+++ /dev/null
@@ -1,34 +0,0 @@
-const { resolve } = require("node:path");
-
-const project = resolve(process.cwd(), "tsconfig.json");
-
-/** @type {import("eslint").Linter.Config} */
-module.exports = {
- extends: ["eslint:recommended", "prettier", "eslint-config-turbo"],
- plugins: ["only-warn"],
- globals: {
- React: true,
- JSX: true,
- },
- env: {
- node: true,
- },
- settings: {
- "import/resolver": {
- typescript: {
- project,
- },
- },
- },
- ignorePatterns: [
- // Ignore dotfiles
- ".*.js",
- "node_modules/",
- "dist/",
- ],
- overrides: [
- {
- files: ["*.js?(x)", "*.ts?(x)"],
- },
- ],
-};
diff --git a/packages/eslint-config/next.js b/packages/eslint-config/next.js
deleted file mode 100644
index 6000e54..0000000
--- a/packages/eslint-config/next.js
+++ /dev/null
@@ -1,35 +0,0 @@
-const { resolve } = require("node:path");
-
-const project = resolve(process.cwd(), "tsconfig.json");
-
-/** @type {import("eslint").Linter.Config} */
-module.exports = {
- extends: [
- "eslint:recommended",
- "prettier",
- require.resolve("@vercel/style-guide/eslint/next"),
- "eslint-config-turbo",
- ],
- globals: {
- React: true,
- JSX: true,
- },
- env: {
- node: true,
- browser: true,
- },
- plugins: ["only-warn"],
- settings: {
- "import/resolver": {
- typescript: {
- project,
- },
- },
- },
- ignorePatterns: [
- // Ignore dotfiles
- ".*.js",
- "node_modules/",
- ],
- overrides: [{ files: ["*.js?(x)", "*.ts?(x)"] }],
-};
diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json
deleted file mode 100644
index 575d83a..0000000
--- a/packages/eslint-config/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "@repo/eslint-config",
- "version": "0.0.0",
- "private": true,
- "files": [
- "library.js",
- "next.js",
- "react-internal.js"
- ],
- "devDependencies": {
- "@vercel/style-guide": "^5.1.0",
- "eslint-config-turbo": "^1.11.3",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-only-warn": "^1.1.0",
- "@typescript-eslint/parser": "^6.17.0",
- "@typescript-eslint/eslint-plugin": "^6.17.0",
- "typescript": "^5.3.3"
- }
-}
diff --git a/packages/eslint-config/react-internal.js b/packages/eslint-config/react-internal.js
deleted file mode 100644
index f56c924..0000000
--- a/packages/eslint-config/react-internal.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const { resolve } = require("node:path");
-
-const project = resolve(process.cwd(), "tsconfig.json");
-
-/*
- * This is a custom ESLint configuration for use with
- * internal (bundled by their consumer) libraries
- * that utilize React.
- *
- * This config extends the Vercel Engineering Style Guide.
- * For more information, see https://github.com/vercel/style-guide
- *
- */
-
-/** @type {import("eslint").Linter.Config} */
-module.exports = {
- extends: ["eslint:recommended", "prettier", "eslint-config-turbo"],
- plugins: ["only-warn"],
- globals: {
- React: true,
- JSX: true,
- },
- env: {
- browser: true,
- },
- settings: {
- "import/resolver": {
- typescript: {
- project,
- },
- },
- },
- ignorePatterns: [
- // Ignore dotfiles
- ".*.js",
- "node_modules/",
- "dist/",
- ],
- overrides: [
- // Force ESLint to detect .tsx files
- { files: ["*.js?(x)", "*.ts?(x)"] },
- ],
-};
diff --git a/packages/typescript-config/base.json b/packages/typescript-config/base.json
index 0f80cfd..8b049d9 100644
--- a/packages/typescript-config/base.json
+++ b/packages/typescript-config/base.json
@@ -5,16 +5,18 @@
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
- "incremental": false,
"isolatedModules": true,
"lib": ["es2022", "DOM", "DOM.Iterable"],
- "module": "NodeNext",
+ "module": "ESNext",
"moduleDetection": "force",
- "moduleResolution": "NodeNext",
+ "moduleResolution": "Bundler",
"noUncheckedIndexedAccess": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
- "target": "ES2022"
+ "target": "ESNext",
+ "allowJs": true,
+ "checkJs": true,
+ "jsx": "react-jsx"
}
}
diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json
index 27c0e60..ad7ae62 100644
--- a/packages/typescript-config/package.json
+++ b/packages/typescript-config/package.json
@@ -1,5 +1,5 @@
{
- "name": "@repo/typescript-config",
+ "name": "@evmos/config",
"version": "0.0.0",
"private": true,
"license": "MIT",
diff --git a/packages/ui/.eslintrc.js b/packages/ui/.eslintrc.js
deleted file mode 100644
index 9117326..0000000
--- a/packages/ui/.eslintrc.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/** @type {import("eslint").Linter.Config} */
-module.exports = {
- root: true,
- extends: ["@repo/eslint-config/react-internal.js"],
- parser: "@typescript-eslint/parser",
- parserOptions: {
- project: "./tsconfig.lint.json",
- },
-};
diff --git a/packages/ui/package.json b/packages/ui/package.json
deleted file mode 100644
index b101eab..0000000
--- a/packages/ui/package.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "name": "@repo/ui",
- "version": "0.0.0",
- "private": true,
- "exports": {
- "./button": "./src/button.tsx",
- "./card": "./src/card.tsx",
- "./code": "./src/code.tsx"
- },
- "scripts": {
- "lint": "eslint . --max-warnings 0",
- "generate:component": "turbo gen react-component"
- },
- "devDependencies": {
- "@repo/eslint-config": "*",
- "@repo/typescript-config": "*",
- "@turbo/gen": "^1.11.3",
- "@types/node": "^20.10.6",
- "@types/eslint": "^8.56.1",
- "@types/react": "^18.2.46",
- "@types/react-dom": "^18.2.18",
- "eslint": "^8.56.0",
- "react": "^18.2.0",
- "typescript": "^5.3.3"
- }
-}
diff --git a/packages/ui/src/button.tsx b/packages/ui/src/button.tsx
deleted file mode 100644
index 78e5420..0000000
--- a/packages/ui/src/button.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-
-import { ReactNode } from "react";
-
-interface ButtonProps {
- children: ReactNode;
- className?: string;
- appName: string;
-}
-
-export const Button = ({ children, className, appName }: ButtonProps) => {
- return (
-
- );
-};
diff --git a/packages/ui/src/card.tsx b/packages/ui/src/card.tsx
deleted file mode 100644
index f69672e..0000000
--- a/packages/ui/src/card.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-export function Card({
- className,
- title,
- children,
- href,
-}: {
- className?: string;
- title: string;
- children: React.ReactNode;
- href: string;
-}): JSX.Element {
- return (
-
-
- {title} ->
-
- {children}
-
- );
-}
diff --git a/packages/ui/src/code.tsx b/packages/ui/src/code.tsx
deleted file mode 100644
index 769d971..0000000
--- a/packages/ui/src/code.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-export function Code({
- children,
- className,
-}: {
- children: React.ReactNode;
- className?: string;
-}): JSX.Element {
- return {children}
;
-}
diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json
deleted file mode 100644
index ca86687..0000000
--- a/packages/ui/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "@repo/typescript-config/react-library.json",
- "compilerOptions": {
- "outDir": "dist"
- },
- "include": ["src"],
- "exclude": ["node_modules", "dist"]
-}
diff --git a/packages/ui/tsconfig.lint.json b/packages/ui/tsconfig.lint.json
deleted file mode 100644
index df2762e..0000000
--- a/packages/ui/tsconfig.lint.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "extends": "@repo/typescript-config/react-library.json",
- "compilerOptions": {
- "outDir": "dist"
- },
- "include": ["src", "turbo"],
- "exclude": ["node_modules", "dist"]
-}
diff --git a/packages/ui/turbo/generators/config.ts b/packages/ui/turbo/generators/config.ts
deleted file mode 100644
index 07ce973..0000000
--- a/packages/ui/turbo/generators/config.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type { PlopTypes } from "@turbo/gen";
-
-// Learn more about Turborepo Generators at https://turbo.build/repo/docs/core-concepts/monorepos/code-generation
-
-export default function generator(plop: PlopTypes.NodePlopAPI): void {
- // A simple generator to add a new React component to the internal UI library
- plop.setGenerator("react-component", {
- description: "Adds a new react component",
- prompts: [
- {
- type: "input",
- name: "name",
- message: "What is the name of the component?",
- },
- ],
- actions: [
- {
- type: "add",
- path: "src/{{kebabCase name}}.tsx",
- templateFile: "templates/component.hbs",
- },
- {
- type: "append",
- path: "index.tsx",
- pattern: /"exports": {(?)/g,
- template: '"./{{kebabCase name}}": "./src/{{kebabCase name}}.tsx",',
- },
- ],
- });
-}
diff --git a/packages/ui/turbo/generators/templates/component.hbs b/packages/ui/turbo/generators/templates/component.hbs
deleted file mode 100644
index d968b9e..0000000
--- a/packages/ui/turbo/generators/templates/component.hbs
+++ /dev/null
@@ -1,8 +0,0 @@
-export const {{ pascalCase name }} = ({ children }: { children: React.ReactNode }) => {
- return (
-
-
{{ pascalCase name }} Component
- {children}
-
- );
-};
diff --git a/tsconfig.json b/tsconfig.json
index c8a018d..0967ef4 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,3 +1 @@
-{
- "extends": "@repo/typescript-config/base.json"
-}
+{}