Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
# These owners will be requested for review when someone opens a pull request.

# Default owners for any paths not matched below.
* @Arvolear @Hrom131

# Frontend apps
/web-v2/ @ardier16
4 changes: 4 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ on:
push:
branches:
- main
paths-ignore:
- 'web-v2/**'
pull_request:
paths-ignore:
- 'web-v2/**'
workflow_call:

permissions:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ on:
push:
branches:
- main
paths-ignore:
- 'web-v2/**'
pull_request:
paths-ignore:
- 'web-v2/**'
workflow_call:

env:
Expand Down
3 changes: 3 additions & 0 deletions web-v2/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VITE_API_URL=http://localhost:8000
VITE_ESPLORA_BASE_URL=https://blockstream.info/liquidtestnet/api
VITE_NETWORK=liquidtestnet
27 changes: 27 additions & 0 deletions web-v2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 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?

# Eslint cache
.eslintcache
1 change: 1 addition & 0 deletions web-v2/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.19.0
3 changes: 3 additions & 0 deletions web-v2/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist
node_modules
*.min.js
8 changes: 8 additions & 0 deletions web-v2/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"printWidth": 100,
"semi": false,
"singleQuote": true,
"jsxSingleQuote": true,
"arrowParens": "avoid",
"trailingComma": "all"
}
26 changes: 26 additions & 0 deletions web-v2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM node:20-alpine AS builder

WORKDIR /app
RUN corepack enable

COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

COPY . .

ARG VITE_API_URL
ARG VITE_ESPLORA_BASE_URL
ARG VITE_NETWORK
ENV VITE_API_URL=$VITE_API_URL
ENV VITE_ESPLORA_BASE_URL=$VITE_ESPLORA_BASE_URL
ENV VITE_NETWORK=$VITE_NETWORK

RUN pnpm build

FROM nginx:1.27-alpine AS runtime

COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
74 changes: 74 additions & 0 deletions web-v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Simplicity Lending Web V2

V2 frontend scaffold for the Simplicity Lending protocol.

## Prerequisites

- Node.js 20.19+
- pnpm 10+

## Environment Variables

Copy `.env.example` to `.env` and adjust as needed.

- `VITE_API_URL` - Base URL for the indexer API.
- `VITE_ESPLORA_BASE_URL` - Base URL for Esplora.
- `VITE_NETWORK` - Network name (`liquid`, `liquidtestnet`, `regtest`).

## Stack

- Vite + React + TypeScript
- Tailwind CSS v4 (token-ready theme scaffold)
- HeroUI (`@heroui/react`)
- React Router v7 (protected route stub)
- React Query v5
- Zod v3
- ESLint + Prettier

## Install

```bash
pnpm install
```

## Run

```bash
pnpm dev
```

## Add Icon

Generate a new icon component in `src/components/icons`.

Command:

```bash
pnpm add-icon <icon-name> "<svg>...</svg>"
```

Example:

```bash
pnpm add-icon coins "<svg viewBox='0 0 24 24'>...</svg>"
```

Notes:

- If SVG content is omitted, the script reads SVG from your clipboard.
- The generated component is normalized to use `currentColor` and saved as `<name>-icon.tsx`.

## Lint

```bash
pnpm lint
```

## Docker

Build and run from this directory:

```bash
docker build -t simplicity-web-v2 .
docker run --rm -p 8080:80 simplicity-web-v2
```
118 changes: 118 additions & 0 deletions web-v2/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import js from '@eslint/js'
import globals from 'globals'
import importPlugin from 'eslint-plugin-import'
import jsxA11y from 'eslint-plugin-jsx-a11y'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import simpleImportSort from 'eslint-plugin-simple-import-sort'
import unusedImports from 'eslint-plugin-unused-imports'
import prettierPlugin from 'eslint-plugin-prettier'
import tseslint from 'typescript-eslint'
import eslintConfigPrettier from 'eslint-config-prettier/flat'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist', 'eslint.config.js']),

// Base config for all JS/JSX/TS/TSX files
{
files: ['**/*.{js,jsx,ts,tsx}'],
extends: [
js.configs.recommended,
importPlugin.flatConfigs.recommended,
jsxA11y.flatConfigs.recommended,
react.configs.flat.recommended,
react.configs.flat['jsx-runtime'],
reactHooks.configs.flat.recommended,
],
plugins: {
'react-refresh': reactRefresh,
'simple-import-sort': simpleImportSort,
prettier: prettierPlugin,
'unused-imports': unusedImports,
},
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: globals.browser,
parserOptions: {
ecmaFeatures: { jsx: true },
},
},
settings: {
'import/resolver': {
typescript: {},
node: {
paths: ['src'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
react: { version: 'detect' },
},
rules: {
'import/namespace': 'off',
'prettier/prettier': ['error', {}, { usePrettierrc: true }],
'arrow-parens': 0,
'no-debugger': 1,
'no-warning-comments': [1, { terms: ['hardcoded'], location: 'anywhere' }],
'no-return-await': 0,
'object-curly-spacing': ['error', 'always'],
'simple-import-sort/imports': 'warn',
'simple-import-sort/exports': 'warn',
'unused-imports/no-unused-imports': 'warn',
'no-var': 'error',
'comma-dangle': [1, 'always-multiline'],
'linebreak-style': ['error', 'unix'],
'no-constant-condition': ['error', { checkLoops: false }],
'max-len': [
1,
{
code: 100,
comments: 100,
ignoreUrls: true,
ignoreStrings: true,
ignoreTemplateLiterals: true,
ignoreRegExpLiterals: true,
},
],
'no-console': [1, { allow: ['warn', 'error'] }],
'react/jsx-curly-brace-presence': ['warn', 'never'],
'react/display-name': 'off',
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
},

// TypeScript-specific overrides
{
files: ['**/*.{ts,tsx}'],
extends: [
tseslint.configs.recommended,
importPlugin.flatConfigs.typescript,
],
plugins: {
'@typescript-eslint': tseslint.plugin,
},
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: ['./tsconfig.app.json', './tsconfig.node.json'],
tsconfigRootDir: import.meta.dirname,
},
},
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
},
rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-empty-object-type': [
'warn',
{ allowInterfaces: 'with-single-extends' },
],
},
},

eslintConfigPrettier,
])
13 changes: 13 additions & 0 deletions web-v2/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Simplicity Lending</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
11 changes: 11 additions & 0 deletions web-v2/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
server {
listen 80;
server_name _;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}
}
57 changes: 57 additions & 0 deletions web-v2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "web-v2",
"private": true,
"version": "0.0.0",
"type": "module",
"engines": {
"node": ">=20.19.0"
},
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"format": "prettier --write .",
"format:check": "prettier --check .",
"preview": "vite preview",
"add-icon": "tsx ./scripts/add-icon.ts"
},
"dependencies": {
"@heroui/react": "^3.0.4",
"@tanstack/react-query": "^5.100.10",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"react-router-dom": "^7.15.0",
"zod": "^3.25.76"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
"@tailwindcss/postcss": "^4.2.0",
"@types/node": "^24.12.4",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.2.0",
"autoprefixer": "^10.4.24",
"chalk": "^5.6.2",
"clipboardy": "^5.3.1",
"eslint": "^9.39.4",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.4.26",
"eslint-plugin-simple-import-sort": "^13.0.0",
"eslint-plugin-unused-imports": "^4.4.1",
"globals": "^16.5.0",
"postcss": "^8.5.6",
"prettier": "^3.4.2",
"tailwindcss": "^4.2.0",
"tsx": "^4.21.0",
"typescript": "~5.9.3",
"typescript-eslint": "^8.59.3",
"vite": "^7.3.3",
"vite-plugin-checker": "^0.13.0"
}
}
Loading
Loading