A Python web framework inspired by Next.js with file-based routing, SSR, and SSG and more
Project description
๐ NextPy Framework
A RAHIMSTUDIOS Product | The Python web framework with exact Next.js syntax! Build modern web applications with file-based routing, True JSX components, React-like hooks, server-side rendering (SSR), static site generation (SSG), and more - all with the same developer experience as Next.js but in Python!
๐ข About RAHIMSTUDIOS
NextPy is proudly developed and maintained by RAHIMSTUDIOS - a cutting-edge technology company dedicated to creating innovative developer tools and frameworks. Our mission is to bridge the gap between Python's simplicity and modern web development paradigms.
๐ฏ Why RAHIMSTUDIOS Built NextPy:
- ๐ Python-First Philosophy - Leverage Python's simplicity for web development
- โก Performance Focus - Blazing fast SSR and SSG capabilities
- ๐จ Developer Experience - Tooling that makes development joyful
- ๐ง Enterprise Ready - Production-grade features and reliability
- ๐ Community Driven - Open-source with professional backing
๐ Quick Start
Installation
# Install NextPy
pip install nextpy-framework
# Create new project
nextpy create my-app
# Navigate to project
cd my-app
# Start development server
nextpy dev
Your First NextPy App with PSX
Create pages/index.psx:
# Import all React-like features from NextPy
from nextpy import (
component, psx, useState, useEffect, useCallback, useMemo,
create_onclick, create_onchange, create_onsubmit
)
# Import components like in React
from components.Button import Button
@component
def Home(props=None):
# Python-style array destructuring for hooks
[name, setName] = useState('rahim')
[count, setCount] = useState(0)
[loading, setLoading] = useState(false)
# Server-side props
props = props or {}
title = props.get("title", "Welcome to NextPy")
message = props.get("message", "Your Python-powered web framework with True JSX")
# Event handlers with create utilities
handleClick = create_onclick(lambda e: setName(name.upper()))
handleIncrement = create_onclick(lambda e: setCount(count + 1))
# Client-side data fetching
def fetch_data():
setLoading(true)
# Simulate API call
setLoading(false)
useEffect(fetch_data, [])
return (
<div className={clsx('flex', 'items-center', 'justify-center', 'min-h-screen', 'bg-gradient-to-br', 'from-blue-500', 'to-purple-600')}>
<div className={clsx('text-center', 'text-white', 'max-w-4xl', 'mx-auto', 'p-8')}>
<h1 className={clsx('mb-4', 'text-5xl', 'font-bold')}>{title}</h1>
<p className={clsx('text-xl', 'mb-8')}>{message} {name}</p>
{/* Interactive Section */}
<div className={clsx('mb-8', 'bg-white', 'bg-opacity-10', 'backdrop-blur-sm', 'rounded-lg', 'p-6')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>Interactive Demo</h2>
<p className="mb-4">Count: {count}</p>
<div className={clsx('flex', 'flex-wrap', 'gap-4', 'justify-center')}>
<Button onclick={handleIncrement} variant="primary" size="lg">
Increment: {count}
</Button>
<Button onclick={handleClick} variant="secondary" size="lg">
Uppercase Name
</Button>
<Button onclick={lambda e: setCount(0)} variant="danger" size="lg">
Reset
</Button>
</div>
</div>
{/* Component Nesting Demo */}
<div className={clsx('mb-8', 'bg-white', 'bg-opacity-10', 'backdrop-blur-sm', 'rounded-lg', 'p-6')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>Component Nesting</h2>
<Button variant="success" onclick={lambda e: console.log("Nested button clicked!")}>
Nested Button Component
</Button>
</div>
{/* Python Logic Demo */}
<div className={clsx('mb-8', 'bg-white', 'bg-opacity-10', 'backdrop-blur-sm', 'rounded-lg', 'p-6')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>Python Logic in JSX</h2>
{/* Conditional rendering */}
{if len(name) > 5:
<p className="text-green-300">โ
Long name detected!</p>
{else:
<p className="text-yellow-300">โ ๏ธ Short name</p>
{/if}}
{/* For loop */}
<div className="mt-4">
{for i in range(3):
<div key={i} className={clsx('mb-2', 'p-2', 'bg-white', 'bg-opacity-20', 'rounded')}>
Item {i}: {name} {i + 1}
</div>
{/for}
</div>
</div>
{/* Navigation */}
<div className={clsx('flex', 'flex-wrap', 'gap-4', 'justify-center')}>
<a href="/about" className={clsx('inline-block', 'px-6', 'py-3', 'font-semibold', 'text-blue-600', 'transition-all', 'duration-300', 'transform', 'bg-white', 'rounded-lg', 'shadow-lg', 'hover:bg-gray-100', 'hover:text-blue-700', 'hover:scale-105')}>
Learn More
</a>
<a href="/blog" className={clsx('inline-block', 'px-6', 'py-3', 'font-semibold', 'text-purple-600', 'transition-all', 'duration-300', 'transform', 'bg-white', 'rounded-lg', 'shadow-lg', 'hover:bg-gray-100', 'hover:text-purple-700', 'hover:scale-105')}>
View Blog
</a>
</div>
</div>
</div>
)
# Server-side props (Next.js style)
def getServerSideProps(context):
return {
"props": {
"title": "Welcome to NextPy by RAHIMSTUDIOS",
"message": "Your Python-powered web framework with True JSX"
}
}
default = Home
Visit http://localhost:8000 to see your app!
๐ฏ Why Choose NextPy by RAHIMSTUDIOS?
โ Complete React Experience in Python
- โ True JSX Syntax - Write exact Next.js JSX syntax in Python
- โ All React Hooks - useState, useEffect, useCallback, useMemo, useRef, useContext, useReducer
- โ
Python-Style Destructuring -
[name, setName] = useState('rahim') - โ Event Utilities - create_onclick, create_onchange, create_onsubmit
- โ Custom Hooks - useCounter, useToggle, useLocalStorage, useFetch
- โ Component Nesting - Full component composition and props passing
โ Next.js Features in Python
- โ File-Based Routing - Automatic route discovery like Next.js
- โ
PSX Files -
.psxextension for Python JSX components - โ
Server-Side Rendering - Full SSR support with
getServerSideProps - โ
Static Site Generation - Build static sites with
getStaticProps - โ
Dynamic Routes -
[slug].psx,[id].psxwith full params support - โ
API Routes - Python API endpoints in
pages/api/ - โ Middleware - Authentication, logging, custom middleware
- โ
Component Imports -
from components.Button import Button
โ Developer Experience
- โ Hot Reload - Instant development feedback
- โ VS Code Extension - Dedicated extension for syntax highlighting
- โ Language Server - Auto-completion, IntelliSense, error checking
- โ TypeScript Support - Full type definitions and IntelliSense
- โ Debug Tools - Built-in debugging with detailed error pages
- โ Plugin System - Extensible architecture
โ Production Ready
- โ Template System - Jinja2 templates with PSX content injection
- โ Tailwind CSS - Automatic compilation and optimization
- โ Error Handling - Comprehensive error pages and debugging
- โ Performance - Optimized rendering and caching
- โ Security - Built-in security headers and protections
- โ Deployment - Docker, Vercel, Heroku, AWS support
๐ฃ๏ธ Routing System
File-Based Routing with PSX
NextPy uses file-based routing just like Next.js, with full .psx support:
pages/
โโโ index.psx # โ /
โโโ about.psx # โ /about
โโโ contact.psx # โ /contact
โโโ blog/
โ โโโ index.psx # โ /blog
โ โโโ post.psx # โ /blog/post
โ โโโ [slug].psx # โ /blog/:slug
โโโ users/
โ โโโ [id].psx # โ /users/:id
โ โโโ [...all].psx # โ /users/*
โโโ api/
โโโ hello.psx # โ /api/hello
โโโ users/
โโโ [id].psx # โ /api/users/:id
Dynamic Routes with PSX
# pages/blog/[slug].psx
from nextpy import component, psx, useState, useEffect
@component
def BlogPost(props=None):
slug = props.get("params", {}).get("slug", "")
[post, setPost] = useState({})
[loading, setLoading] = useState(true)
def fetch_post():
# Simulate API call
setPost({
"title": f"Blog Post: {slug}",
"content": f"This is the content for {slug}",
"date": "2024-03-26"
})
setLoading(false)
useEffect(fetch_post, [slug])
return (
<div className={clsx('container', 'mx-auto', 'p-8')}>
{loading and (
<div className={clsx('text-center', 'py-12')}>
<div className={clsx('animate-spin', 'rounded-full', 'h-12', 'w-12', 'border-b-2', 'border-blue-600', 'mx-auto')}></div>
<p className={clsx('mt-4', 'text-gray-600')}>Loading post...</p>
</div>
)}
{post and not loading and (
<article className={clsx('max-w-4xl', 'mx-auto')}>
<header className="mb-8">
<h1 className={clsx('text-4xl', 'font-bold', 'mb-4')}>{post.get('title')}</h1>
<time className="text-gray-600">{post.get('date')}</time>
</header>
<div className={clsx('prose', 'prose-lg', 'max-w-none')}>
<div>{post.get('content')}</div>
</div>
</article>
)}
</div>
)
def getServerSideProps(context):
slug = context.get("params", {}).get("slug", "")
# Pre-fetch data on server
return {
"props": {
"params": {"slug": slug}
}
}
default = BlogPost
API Routes
# pages/api/users.psx
from nextpy.server.app import JSONResponse
async def get(request):
"""GET /api/users - Fetch all users"""
import requests
response = requests.get("https://jsonplaceholder.typicode.com/users")
users = response.json()
return JSONResponse({
"success": True,
"data": users,
"count": len(users)
})
async def post(request):
"""POST /api/users - Create new user"""
data = await request.json()
# Validate required fields
required_fields = ["name", "email"]
for field in required_fields:
if field not in data:
return JSONResponse({
"success": False,
"error": f"Missing required field: {field}"
}, status_code=400)
# Create new user (in real app, save to database)
new_user = {
"id": len(requests.get("https://jsonplaceholder.typicode.com/users").json()) + 1,
**data
}
return JSONResponse({
"success": True,
"data": new_user,
"message": "User created successfully"
}, status_code=201)
๐ง Data Fetching & State Management
Server-Side Rendering (SSR)
# pages/dashboard.psx
from nextpy import component, psx, useState, useEffect
from nextpy.psx import useFetch
@component
def Dashboard(props=None):
# Server-rendered data
initial_data = props.get("data", {})
# Client-side state
[users, setUsers] = useState(initial_data.get("users", []))
[posts, setPosts] = useState([])
[loading, setLoading] = useState(false)
# Custom hook for data fetching
[data, loading_data, error_data] = useFetch("https://jsonplaceholder.typicode.com/posts?_limit=5")
def fetch_posts():
setLoading(true)
try:
import requests
response = requests.get("https://jsonplaceholder.typicode.com/posts?_limit=10")
if response.status_code == 200:
setPosts(response.json())
except Exception as e:
print(f"Error fetching posts: {e}")
finally:
setLoading(false)
# Initial data fetch
useEffect(lambda: {
if data:
setPosts(data)
fetch_posts()
}, [data])
return (
<div className={clsx('min-h-screen', 'bg-gray-100')}>
<div className={clsx('container', 'mx-auto', 'p-8')}>
<header className="mb-8">
<h1 className={clsx('text-4xl', 'font-bold', 'text-gray-800', 'mb-4')}>Dashboard</h1>
<p className="text-gray-600">Real-time data fetching with PSX</p>
</header>
<div className={clsx('grid', 'grid-cols-1', 'lg:grid-cols-2', 'gap-8')}>
{/* Users Section */}
<section className={clsx('bg-white', 'rounded-lg', 'shadow', 'p-6')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>Users ({len(users)})</h2>
{loading_data and (
<div className={clsx('text-center', 'py-8')}>
<div className={clsx('animate-spin', 'rounded-full', 'h-8', 'w-8', 'border-b-2', 'border-blue-600', 'mx-auto')}></div>
</div>
)}
{not loading_data and users and (
<div className="space-y-3">
{for user in users[:5]:
<div key={user.get('id')} className={clsx('border-b', 'pb-3')}>
<div className={clsx('flex', 'items-center', 'justify-between')}>
<div>
<h3 className="font-semibold">{user.get('name')}</h3>
<p className={clsx('text-sm', 'text-gray-600')}>{user.get('email')}</p>
</div>
<span className={clsx('text-xs', 'bg-blue-100', 'text-blue-800', 'px-2', 'py-1', 'rounded')}>
{user.get('company', {}).get('name', 'N/A')}
</span>
</div>
</div>
{/for}}
</div>
)}
</section>
{/* Posts Section */}
<section className={clsx('bg-white', 'rounded-lg', 'shadow', 'p-6')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>Latest Posts ({len(posts)})</h2>
{loading and (
<div className={clsx('text-center', 'py-8')}>
<div className={clsx('animate-spin', 'rounded-full', 'h-8', 'w-8', 'border-b-2', 'border-green-600', 'mx-auto')}></div>
</div>
)}
{not loading and posts and (
<div className="space-y-4">
{for post in posts:
<div key={post.get('id')} className={clsx('border-l-4', 'border-blue-500', 'pl-4')}>
<h3 className={clsx('font-semibold', 'mb-1')}>{post.get('title')}</h3>
<p className={clsx('text-sm', 'text-gray-600', 'line-clamp-2')}>{post.get('body')}</p>
</div>
{/for}}
</div>
)}
</section>
</div>
{/* Statistics */}
<section className={clsx('mt-8', 'bg-white', 'rounded-lg', 'shadow', 'p-6')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>Statistics</h2>
<div className={clsx('grid', 'grid-cols-1', 'md:grid-cols-3', 'gap-6')}>
<div className="text-center">
<div className={clsx('text-3xl', 'font-bold', 'text-blue-600')}>{len(users)}</div>
<div className="text-gray-600">Total Users</div>
</div>
<div className="text-center">
<div className={clsx('text-3xl', 'font-bold', 'text-green-600')}>{len(posts)}</div>
<div className="text-gray-600">Total Posts</div>
</div>
<div className="text-center">
<div className={clsx('text-3xl', 'font-bold', 'text-purple-600')}>
{len([u for u in users if u.get('company', {}).get('name')])}
</div>
<div className="text-gray-600">Companies</div>
</div>
</div>
</section>
</div>
</div>
)
def getServerSideProps(context):
"""Server-side data fetching"""
try:
import requests
response = requests.get("https://jsonplaceholder.typicode.com/users")
users = response.json()
return {
"props": {
"data": {
"users": users[:10], # First 10 users
"userCount": len(users)
}
}
}
except Exception as e:
return {
"props": {
"data": {
"users": [],
"error": str(e)
}
}
}
default = Dashboard
๐จ Component System
Reusable Components
# components/Button.psx
from nextpy import component, psx
@component
def Button(props=None):
props = props or {}
onclick = props.get("onclick", lambda e: None)
children = props.get("children", "Button")
variant = props.get("variant", "primary")
size = props.get("size", "md")
disabled = props.get("disabled", false)
# Variant styles
variant_styles = {
"primary": "bg-blue-500 hover:bg-blue-600 text-white shadow-lg hover:shadow-xl",
"secondary": "bg-gray-200 hover:bg-gray-300 text-gray-800",
"danger": "bg-red-500 hover:bg-red-600 text-white",
"success": "bg-green-500 hover:bg-green-600 text-white",
"outline": "border-2 border-blue-500 text-blue-500 hover:bg-blue-50"
}
# Size styles
size_styles = {
"sm": "px-3 py-1.5 text-sm",
"md": "px-4 py-2 text-base",
"lg": "px-6 py-3 text-lg"
}
button_class = f"{variant_styles.get(variant, variant_styles['primary'])} {size_styles.get(size, size_styles['md'])} font-medium transition-all duration-200 transform rounded"
return (
<button
onclick={onclick}
disabled={disabled}
className={button_class + (disabled and " opacity-50 cursor-not-allowed" or " hover:scale-105 active:scale-95")}
>
{children}
</button>
)
default = Button
Component Nesting
# components/Card.psx
from nextpy import component, psx
from Button import Button
@component
def Card(props=None):
props = props or {}
title = props.get("title", "Card Title")
content = props.get("content", "Card content")
show_button = props.get("showButton", True)
def handle_card_click():
print(f"Card '{title}' button clicked!")
return (
<div className={clsx('bg-white', 'rounded-lg', 'shadow-lg', 'p-6', 'max-w-md')}>
<h2 className={clsx('text-xl', 'font-bold', 'mb-4')}>{title}</h2>
<p className={clsx('text-gray-600', 'mb-6')}>{content}</p>
{show_button and (
<div className={clsx('flex', 'space-x-4')}>
<Button
onclick={handle_card_click}
variant="primary"
size="md"
>
Learn More
</Button>
<Button
onclick={lambda e: print("Secondary button clicked!")}
variant="secondary"
size="md"
>
Cancel
</Button>
</div>
)}
</div>
)
default = Card
๐ฏ All React Hooks Available
Core Hooks
from nextpy import (
useState, useEffect, useCallback, useMemo, useRef,
useContext, useReducer, useImperativeHandle, useLayoutEffect,
useDebugValue, useTransition, useDeferredValue, useId
)
@component
def HooksDemo(props=None):
# State hooks
[count, setCount] = useState(0)
[name, setName] = useState('NextPy')
[isVisible, setIsVisible] = useState(true)
# Ref hooks
inputRef = useRef(None)
# Reducer hook
def reducer(state, action):
if action['type'] == 'increment':
return {'count': state['count'] + 1}
elif action['type'] == 'decrement':
return {'count': state['count'] - 1}
return state
[reducerState, dispatch] = useReducer(reducer, {'count': 0})
# Memoized callback
handleClick = useCallback(lambda e: setCount(count + 1), [count])
# Memoized value
expensiveValue = useMemo(lambda: sum(range(count + 1)), [count])
# Effect hook
def effect():
print(f"Component updated: count={count}, name={name}")
useEffect(effect, [count, name])
return (
<div className={clsx('p-6', 'bg-white', 'rounded-lg', 'shadow')}>
<h2 className={clsx('text-2xl', 'font-bold', 'mb-4')}>React Hooks Demo</h2>
<div className="space-y-4">
<div>
<p>Count: {count}</p>
<p>Expensive Value: {expensiveValue}</p>
<p>Reducer Count: {reducerState['count']}</p>
</div>
<div className={clsx('flex', 'space-x-4')}>
<Button onclick={handleClick} variant="primary">
Increment
</Button>
<Button onclick={lambda e: dispatch({'type': 'increment'})} variant="secondary">
Reducer Increment
</Button>
<Button onclick={lambda e: setIsVisible(!isVisible)} variant="outline">
Toggle Visibility
</Button>
</div>
{isVisible and (
<div className={clsx('mt-4', 'p-4', 'bg-gray-50', 'rounded')}>
<input
ref={inputRef}
value={name}
onchange={lambda e: setName(e.target.value)}
className={clsx('px-3', 'py-2', 'border', 'rounded')}
placeholder="Enter name"
/>
<p className="mt-2">Hello, {name}!</p>
</div>
)}
</div>
</div>
)
default = HooksDemo
๐ ๏ธ CLI Commands
Project Management
# Create new project
nextpy create my-app
# Start development server
nextpy dev
# Build for production
nextpy build
# Start production server
nextpy start
# Export static site
nextpy export
# Show available routes
nextpy routes
# Show version info
nextpy version
# Show project info
nextpy info
Development Tools
# Generate TypeScript definitions
nextpy generate types
# Run tests
nextpy test
# Lint code
nextpy lint
# Format code
nextpy format
๐ฆ Project Structure
my-app/
โโโ pages/ # Route pages (.py and .psx)
โ โโโ index.psx # Home page
โ โโโ about.psx # About page
โ โโโ blog/
โ โ โโโ index.psx # Blog index
โ โ โโโ [slug].psx # Dynamic blog posts
โ โโโ api/ # API routes
โ โโโ hello.psx # Hello API
โ โโโ users/
โ โโโ [id].psx # User API
โโโ components/ # Reusable components
โ โโโ Button.psx # Button component
โ โโโ Card.psx # Card component
โ โโโ Layout.psx # Layout component
โโโ hooks/ # Custom hooks
โ โโโ useCounter.py # Counter hook
โ โโโ useToggle.py # Toggle hook
โ โโโ useLocalStorage.py # Local storage hook
โโโ styles/ # CSS files
โ โโโ global.css # Global styles
โ โโโ components.css # Component styles
โโโ public/ # Static assets
โ โโโ images/ # Images
โ โโโ fonts/ # Fonts
โ โโโ favicon.ico # Favicon
โโโ templates/ # HTML templates (optional)
โ โโโ _page.html # Base page template
โ โโโ _404.html # 404 page template
โโโ .nextpy/ # NextPy configuration
โ โโโ config.js # Configuration file
โ โโโ plugins/ # Plugin configurations
โโโ .vscode/ # VS Code settings
โ โโโ settings.json # Editor settings
โ โโโ extensions.json # Recommended extensions
โ โโโ launch.json # Debug configuration
โโโ main.py # Application entry point
โโโ requirements.txt # Python dependencies
โโโ package.json # Node.js dependencies (for VS Code extension)
โโโ README.md # Project documentation
๐ Deployment
Production Build
# Build optimized production bundle
nextpy build
# Start production server
nextpy start
# Export static site
nextpy export
Docker Deployment
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["nextpy", "start"]
๐ฏ Why RAHIMSTUDIOS?
๐ข Professional Development
- Enterprise-Grade: Built for production environments
- Expert Support: Professional backing and maintenance
- Regular Updates: Continuous improvements and new features
- Security First: Built with security as a top priority
๐ Innovation Leadership
- Cutting-Edge Technology: Latest web development paradigms
- Python Ecosystem: Leveraging Python's vast ecosystem
- Developer-Focused: Tools that make developers productive
- Community-Driven: Open-source with professional oversight
๐ Performance & Scale
- Optimized Rendering: Blazing fast SSR and SSG
- Scalable Architecture: Built for applications of all sizes
- Modern Tooling: Latest development tools and practices
- Production Ready: Battle-tested in real-world applications
๐ Documentation & Support
๐ Comprehensive Docs
๐ค Community
๐ผ Enterprise Support
๐ Get Started Today!
# Install NextPy by RAHIMSTUDIOS
pip install nextpy-framework
# Create your first project
nextpy create my-awesome-app
# Start building amazing web applications with Python!
cd my-awesome-app && nextpy dev
NextPy - Where Python meets modern web development
A RAHIMSTUDIOS Product - Building the future of Python web frameworks
ยฉ 2026 RAHIMSTUDIOS. All rights reserved. NextPy is a trademark of RAHIMSTUDIOS.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nextpy_framework-3.6.1.tar.gz.
File metadata
- Download URL: nextpy_framework-3.6.1.tar.gz
- Upload date:
- Size: 229.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e711a34c13c0dcff04b405d1375f335935c7f3cb17992fa5e91267151603adc2
|
|
| MD5 |
368519ae7ff15ef3d5f71db1816a73a6
|
|
| BLAKE2b-256 |
9507ea4dd54a6d04513dc587a21d5cdd0b628be01c878bcfb43d7b6532098bcd
|
File details
Details for the file nextpy_framework-3.6.1-py3-none-any.whl.
File metadata
- Download URL: nextpy_framework-3.6.1-py3-none-any.whl
- Upload date:
- Size: 260.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
245ff439da117d41c4ec48f201f7bd99199ae639cdfd46bbd7987fe83d6a96e1
|
|
| MD5 |
85ae8467e38c2eb0e7aabe3c620ae3ab
|
|
| BLAKE2b-256 |
cb209b523d39f567f45fcea9207db08c1d4d94e3f096f2585e7dd5e8a30e9a68
|