A Python web framework inspired by Next.js with file-based routing, SSR, and SSG and more
Project description
๐ NextPy Framework
The Python web framework with exact Next.js syntax! Build modern web applications with file-based routing, JSX-like 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!
โจ What's New - Complete Next.js Experience!
NextPy now provides identical Next.js syntax in Python with three different syntax styles:
๐ฏ True JSX Syntax (NEW!)
Write exact Next.js JSX syntax in Python:
// pages/index.py - Exact Next.js syntax!
def Home(message):
return (
<div className="container">
<h1>{message}</h1>
<p>Welcome to NextPy!</p>
<button onClick="alert('Hello!')">Click Me</button>
</div>
);
def getServerSideProps(context):
return {
'props': {
'message': 'Hello from JSX!'
}
}
default = Home
๐งฉ Component-Style (Python Functions)
Traditional Python function components:
from nextpy.components import Button, Card, Input
def Home(props):
message = props.get('message', 'Hello!')
return div({'className': 'container'},
h1({}, message),
Button(text="Click Me", variant="primary"),
Input(name="email", placeholder="Enter email")
)
๐ Template Style (Traditional)
Jinja2 templates with data fetching:
def get_template():
return "home.html"
async def get_server_side_props(context):
return {
"props": {
"message": "Hello from templates!"
}
}
๐ฃ React-Like Hooks (NEW!)
All your favorite React hooks now work in Python:
from nextpy import useState, useEffect, with_hooks
@with_hooks
def Counter(props):
[count, setCount] = useState(0)
[name, setName] = useState('NextPy')
useEffect(() => {
print(f'Count changed to: {count}')
}, [count])
return (
<div>
<h1>Hello {name}!</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
๐จ Complete Component Library (NEW!)
50+ pre-built components for rapid development:
from nextpy.components import (
Button, Card, Input, Form, Select,
Navbar, Tabs, Dropdown, Modal,
Alert, Badge, Progress, Avatar,
Container, Grid, Flex, Stack
)
def MyPage():
return (
<div>
<Navbar brand="My App" />
<Container>
<Card title="Welcome">
<Form>
<Input name="email" placeholder="Enter email" />
<Button text="Submit" variant="primary" />
</Form>
</Card>
</Container>
</div>
);
๐ Demo Mode (NEW!)
When users install NextPy and run nextpy dev without creating a project, they get beautiful built-in documentation and examples:
pip install nextpy-framework
nextpy dev # No project needed!
Demo Mode includes:
- ๐ Beautiful homepage with NextPy showcase
- ๐ Complete documentation hub
- ๐จ Component library demonstrations
- ๐ฃ Hooks examples and tutorials
- ๐ Project creation interface
๐ Features
๐ฏ Next.js-Style Components
- True JSX Syntax - Write
<div>tags directly in Python - Component Functions - Same structure as Next.js
- Props & Children - Pass props and children exactly like Next.js
- Default Exports - Use
default = Componentjust like Next.js - 50+ Components - Pre-built UI components (Button, Card, Form, etc.)
- React-like Hooks - useState, useEffect, useReducer, useContext, etc.
๐งฉ Core Next.js Features
- File-based Routing - Pages in
pages/become routes automatically - Dynamic Routes -
[slug].pycreates dynamic URL segments - Server-Side Rendering -
getServerSidePropsfetches data per request - Static Site Generation -
getStaticPropsbuilds pages at compile time - API Routes - Create API endpoints in
pages/api/with HTTP method handlers
๐ฃ React-Like Hooks
- useState - State management:
[count, setCount] = useState(0) - useEffect - Side effects and lifecycle
- useReducer - Complex state management
- useContext - Global state sharing
- useRef - Mutable references
- useMemo - Memoized values
- useCallback - Memoized functions
- Custom Hooks - useCounter, useToggle, useLocalStorage, useFetch, useDebounce
๐จ Development Experience
- Hot Reload - Instant updates on file changes during development
- Demo Mode - Built-in documentation when no project exists
- Dual Rendering - Choose between JSX, component, or template rendering
- Type Safety - Full Python type hints support
- Error Handling - Comprehensive error messages and debugging
๐ ๏ธ Traditional Features (Still Supported)
- HTMX Integration - SPA-like navigation without heavy JavaScript
- Jinja2 Templates - Powerful templating with layout inheritance
- Tailwind CSS Integration - Utility-first CSS framework
- Database Integration - SQLAlchemy and database utilities
๐ฆ Installation
Via pip
pip install nextpy-framework
Development Install (Editable)
git clone https://github.com/nextpy/nextpy-framework.git
cd nextpy-framework
pip install -e .
๐ Quick Start
1. Create a new project
nextpy create my-app
cd my-app
2. Start development server
nextpy dev
3. Open your browser
Navigate to http://localhost:5000 to see your app!
๐ Project Structure
my-app/
โโโ pages/ # File-based routing
โ โโโ index.py # Homepage (/)
โ โโโ about.py # About page (/about)
โ โโโ [slug].py # Dynamic routes (/:slug)
โ โโโ api/ # API routes
โ โโโ users.py # API endpoint (/api/users)
โ โโโ posts.py # API endpoint (/api/posts)
โโโ components/ # Reusable components (NEW!)
โ โโโ ui/ # Basic UI components
โ โ โโโ Button.jsx
โ โ โโโ Card.jsx
โ โ โโโ Modal.jsx
โ โโโ forms/ # Form components
โ โ โโโ Form.jsx
โ โ โโโ Input.jsx
โ โโโ layout/ # Layout components
โ โ โโโ Header.jsx
โ โ โโโ Footer.jsx
โ โ โโโ Sidebar.jsx
โ โโโ features/ # Feature-specific components
โ โโโ DataTable.jsx
โ โโโ Chart.jsx
โโโ templates/ # Jinja2 templates (optional)
โโโ public/ # Static files
โโโ main.py # Application entry point
โโโ requirements.txt # Python dependencies
๐ฆ Framework Structure
.nextpy_framework/nextpy/
โโโ __init__.py # Main exports and imports
โโโ hooks.py # React-like hooks implementation
โโโ hooks_provider.py # Hooks integration with components
โโโ jsx.py # JSX element system
โโโ jsx_preprocessor.py # JSX to Python transformer
โโโ true_jsx.py # True JSX parser
โโโ components/ # Component library
โ โโโ __init__.py # Component exports
โ โโโ form.py # Form components
โ โโโ layout.py # Layout components
โ โโโ ui.py # UI components
โ โโโ navigation.py # Navigation components
โโโ core/
โ โโโ router.py # Main routing system
โ โโโ component_router.py # Component rendering
โ โโโ renderer.py # Template rendering
โ โโโ demo_router.py # Demo mode routing
โ โโโ demo_pages_simple.py # Demo pages
โโโ server/
โโโ app.py # FastAPI application
๐ฏ Syntax Examples
True JSX Syntax (Recommended)
// pages/index.py
def HomePage():
return (
<div className="container">
<header>
<h1>Welcome to NextPy!</h1>
<p>Building modern web apps with Python!</p>
</header>
<main>
<section>
<h2>Features</h2>
<ul>
<li>File-based routing</li>
<li>Server-side rendering</li>
<li>React-like hooks</li>
<li>50+ components</li>
</ul>
</section>
<section>
<h2>Get Started</h2>
<button onClick="alert('Hello!')">Click Me</button>
</section>
</main>
</div>
);
def getServerSideProps(context):
return {
'props': {}
}
default = HomePage
Component-Style with Hooks
// pages/counter.py
from nextpy import useState, useEffect, with_hooks
from nextpy.components import Button, Card
@with_hooks
def CounterPage():
[count, setCount] = useState(0)
[message, setMessage] = useState('Click the button!')
useEffect(() => {
if count > 0:
setMessage(f'Button clicked {count} times!')
}, [count])
return (
<div className="container">
<Card title="Counter Demo">
<h2>{message}</h2>
<p>Count: {count}</p>
<Button
text="Increment"
onClick={() => setCount(count + 1)}
variant="primary"
/>
</Card>
</div>
);
API Routes
// pages/api/users.py
def get(request):
return {
'users': [
{'id': 1, 'name': 'John Doe', 'email': 'john@example.com'},
{'id': 2, 'name': 'Jane Smith', 'email': 'jane@example.com'}
]
}
def post(request):
data = request.get('json', {})
return {
'user': data,
'created': True
}, 201
default = lambda request: {
'GET': get,
'POST': post
}.get(request.get('method', 'GET'), lambda: {'error': 'Method not allowed'})(request)
๐งฉ Reusable JSX Components
Creating Reusable Components
Create reusable JSX components in the components/ directory:
// components/ui/Button.jsx
def Button(text, variant="primary", size="medium", onClick=None, className=""):
base_classes = "px-4 py-2 rounded-md font-medium transition-colors"
variant_classes = {
"primary": "bg-blue-600 text-white hover:bg-blue-700",
"secondary": "bg-gray-200 text-gray-900 hover:bg-gray-300",
"danger": "bg-red-600 text-white hover:bg-red-700"
}
size_classes = {
"small": "px-2 py-1 text-sm",
"medium": "px-4 py-2 text-sm",
"large": "px-6 py-3 text-base"
}
classes = f"{base_classes} {variant_classes[variant]} {size_classes[size]} {className}"
return (
<button className={classes} onClick={onClick}>
{text}
</button>
);
// components/ui/Card.jsx
def Card(title, children, className=""):
return (
<div className={"bg-white rounded-lg shadow-md p-6 " + className}>
<h2 className="text-xl font-bold mb-4">{title}</h2>
{children}
</div>
);
Using Reusable Components
// pages/index.py
from components.ui.Button import Button
from components.ui.Card import Card
def HomePage():
return (
<div className="container mx-auto p-8">
<Card title="Welcome">
<p>This is a reusable card component!</p>
<Button
text="Click Me"
variant="primary"
onClick={() => alert('Button clicked!')}
/>
</Card>
</div>
);
Advanced Reusable Components
// components/layout/Header.jsx
def Header(title, links):
return (
<header className="bg-white shadow-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<h1 className="text-2xl font-bold">{title}</h1>
<nav>
{links.map(link => (
<a
key={link.href}
href={link.href}
className="text-gray-700 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
>
{link.label}
</a>
))}
</nav>
</div>
</div>
</header>
);
Component Organization Best Practices
components/
โโโ ui/ # Basic UI components
โ โโโ Button.jsx
โ โโโ Card.jsx
โ โโโ Modal.jsx
โโโ forms/ # Form components
โ โโโ Form.jsx
โ โโโ Input.jsx
โโโ layout/ # Layout components
โ โโโ Header.jsx
โ โโโ Footer.jsx
โ โโโ Sidebar.jsx
โโโ features/ # Feature-specific components
โโโ DataTable.jsx
โโโ Chart.jsx
๐ Default Export Pattern
What export = Home Means
In NextPy (like Next.js), export = Home specifies the default export of a module. This tells NextPy which component to render for a page.
Page Component Structure
// pages/index.py
# 1. Define your component function
def Home(props):
message = props.get('message', 'Hello World!')
return (
<div>
<h1>{message}</h1>
<p>Welcome to NextPy!</p>
</div>
);
# 2. Define data fetching function (optional)
def getServerSideProps(context):
return {
'props': {
'message': 'Hello from Server!'
}
}
# 3. Set default export - THIS IS THE PAGE COMPONENT
export = Home
Alternative Syntax
// pages/index.py
def Home(props):
return <div>Hello World!</div>
def getServerSideProps(context):
return {'props': {}}
# Alternative way to set default export
default = Home
Why Default Export Matters
- Page Identification: NextPy uses this to identify the main page component
- Rendering: When someone visits
/, NextPy renders theHomecomponent - Data Flow: Props from
getServerSidePropsare passed to theHomecomponent - Consistency: Matches Next.js pattern exactly
Complete Example: Reusable Components + Default Export
// pages/index.py
from components.layout.Header import Header
from components.layout.Footer import Footer
from components.ui.Button import Button
from components.ui.Card import Card
def Home(props):
user = props.get('user', {'name': 'Guest'})
return (
<div>
<Header
title="NextPy App"
links={[
{'label': 'Home', 'href': '/'},
{'label': 'About', 'href': '/about'},
{'label': 'Contact', 'href': '/contact'}
]}
/>
<main className="container mx-auto p-8">
<Card title={`Welcome ${user['name']}!`}>
<p>This is NextPy with reusable JSX components!</p>
<Button
text="Get Started"
variant="primary"
onClick={() => alert('Welcome to NextPy!')}
/>
</Card>
</main>
<Footer />
</div>
);
def getServerSideProps(context):
return {
'props': {
'user': {'name': 'John Doe'}
}
}
export = Home # This is the page component!
File Structure with Default Exports
pages/
โโโ index.py # export = Home (renders at /)
โโโ about.py # export = About (renders at /about)
โโโ contact.py # export = Contact (renders at /contact)
โโโ [slug].py # export = Post (renders at /:slug)
โโโ api/
โโโ users.py # No default export (API route)
โโโ posts.py # No default export (API route)
๐ฃ Hooks Reference
Core Hooks
# State management
[count, setCount] = useState(0)
# Side effects
useEffect(() => {
console.log('Component mounted')
return () => console.log('Cleanup')
}, [])
# Complex state
def counterReducer(state, action):
if action['type'] == 'increment':
return {'count': state['count'] + 1}
return state
[state, dispatch] = useReducer(counterReducer, {'count': 0})
# Context
ThemeContext = createContext('theme', 'light')
theme = useContext(ThemeContext)
# Mutable refs
inputRef = useRef()
# Memoization
expensiveValue = useMemo(() => calculateExpensiveValue(data), [data])
# Memoized callbacks
handleClick = useCallback(() => setCount(count + 1), [])
Custom Hooks
# Counter with increment/decrement
[count, increment, decrement] = useCounter(10)
# Toggle boolean values
[visible, toggle] = useToggle(true)
# LocalStorage persistence
[value, setValue] = useLocalStorage('key', 'default')
# API data fetching
data = useFetch('/api/users')
# Debounced values
debouncedSearch = useDebounce(searchTerm, 500)
๐จ Components Reference
Form Components
Input(name="email", type="email", placeholder="Enter email")
TextArea(name="message", placeholder="Your message", rows=4)
Select(name="country", options=[
{'label': 'USA', 'value': 'us'},
{'label': 'Canada', 'value': 'ca'}
])
Checkbox(name="newsletter", label="Subscribe to newsletter")
RadioGroup(name="contact", options=[
{'label': 'Email', 'value': 'email'},
{'label': 'Phone', 'value': 'phone'}
])
Form(action="/submit", method="POST", children=[...])
SubmitButton(text="Submit Form")
UI Components
Button(text="Click Me", variant="primary", size="large")
Badge(text="New", variant="success")
Avatar(size="medium", fallback="JD")
Alert(message="Success!", variant="success")
Progress(value={75}, variant="primary")
Skeleton(variant="text")
Tooltip(text="Hover info", children=[...])
Chip(text="Removable", removable=True)
Layout Components
Container(max_width="6xl", children=[...])
Grid(columns=3, gap=4, children=[...])
Flex(direction="row", justify="center", children=[...])
Stack(direction="vertical", spacing=4, children=[...])
Card(title="Title", children=[...])
Navigation Components
Navbar(brand="My App", menu_items=[...])
Tabs(tabs=[...], active_tab="tab1")
Dropdown(trigger="Menu", items=[...])
Pagination(current_page=3, total_pages=10)
SearchBar(placeholder="Search...")
BreadcrumbNav(items=[...])
๐ง Data Fetching
Server-Side Rendering
// pages/posts/[slug].py
async def getServerSideProps(context):
slug = context.get('params', {}).get('slug')
# Fetch data from database or API
post = await fetch_post_by_slug(slug)
if not post:
return {'notFound': True}
return {
'props': {
'post': post
}
}
def PostPage(props):
post = props.get('post')
return (
<div>
<h1>{post['title']}</h1>
<div>{post['content']}</div>
</div>
);
Static Site Generation
// pages/blog/index.py
async def getStaticProps(context):
posts = await fetch_all_posts()
return {
'props': {
'posts': posts
},
'revalidate': 3600 # Revalidate every hour
}
def BlogIndex(props):
posts = props.get('posts', [])
return (
<div>
<h1>Blog Posts</h1>
{posts.map(post => (
<article key={post['id']}>
<h2>{post['title']}</h2>
<p>{post['excerpt']}</p>
</article>
))}
</div>
);
Static Paths
// pages/blog/[slug].py
async def getStaticPaths(context):
posts = await fetch_all_posts()
return {
'paths': [
{'params': {'slug': post['slug']}}
for post in posts
],
'fallback': 'blocking'
}
๐ CLI Commands
Project Creation
# Create new project
nextpy create my-app
# Create project with specific template
nextpy create my-app --template blog
# Create project in current directory
nextpy create .
Development
# Start development server
nextpy dev
# Start on specific port
nextpy dev --port 3000
# Start with debug mode
nextpy dev --debug
Build & Deploy
# Build for production
nextpy build
# Build static site
nextpy build --static
# Export to static files
nextpy export
Database
# Initialize database
nextpy db init
# Run migrations
nextpy db migrate
# Create migration
nextpy db migration create add_users_table
๐ฏ Demo Mode
When you install NextPy and run nextpy dev without creating a project:
pip install nextpy-framework
nextpy dev
You'll see:
- ๐ Demo Mode Activated message
- ๐ Beautiful homepage showcasing NextPy features
- ๐ Complete documentation with examples
- ๐จ Component demonstrations with live code
- ๐ฃ Hooks tutorials and API reference
- ๐ Project creation interface
๐ Documentation
Getting Started
- Quick Start Guide - 5-minute setup
- Step-by-Step Todo App - Complete tutorial
- Components Guide - Component library
- Hooks Guide - React-like hooks
- True JSX Guide - JSX syntax
Advanced Topics
- Performance Guide - Optimization tips
- Testing Guide - Testing strategies
- Database Integration - Database setup
- Authentication - User authentication
- Deployment Guide - Production deployment
API Reference
- Component API
- Hooks API
- CLI Commands
- Configuration - All options
๐งช Testing
Run Tests
# Run all tests
pytest
# Run specific test file
pytest test_components.py
# Run with coverage
pytest --cov=nextpy_framework
Test Examples
# test_components.py
from nextpy.components import Button, Card
def test_button_component():
button = Button(text="Click Me", variant="primary")
assert button is not None
def test_card_component():
card = Card(title="Test", children=["Content"])
assert card is not None
๐ Deployment
Production Build
# Build for production
nextpy build
# Start production server
nextpy start
Docker
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
RUN nextpy build
EXPOSE 5000
CMD ["nextpy", "start"]
Vercel
{
"version": 2,
"builds": [
{
"src": "main.py",
"use": "@vercel/python"
}
]
}
๐ค Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
Development Setup
# Clone repository
git clone https://github.com/nextpy/nextpy-framework.git
cd nextpy-framework
# Install in development mode
pip install -e .
# Run tests
pytest
# Run development server
python main.py
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- Next.js Team - For the amazing framework that inspired NextPy
- React Team - For the hooks and component patterns
- FastAPI - For the excellent ASGI framework
- Python Community - For the amazing ecosystem
๐ What's Next?
- ๐ More Components - Expanding the component library
- ๐จ Theme System - Built-in theming support
- ๐ฑ Mobile App - React Native integration
- ๐ Plugin System - Extensible plugin architecture
- ๐ Internationalization - Multi-language support
NextPy: Next.js for Python ๐ โ React โค๏ธ Python
Build modern web applications with the exact Next.js experience, but in Python! ๐
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-2.2.0.tar.gz.
File metadata
- Download URL: nextpy_framework-2.2.0.tar.gz
- Upload date:
- Size: 115.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f51ebb039ae8082d58bd3cb3c0c82cda35bb4e2f124c5d4567a86a67e0964b46
|
|
| MD5 |
e9b70c9d4dfe312ee2f1161d3c14ecb2
|
|
| BLAKE2b-256 |
008cba3184758c0bc19dbc3735f088a9f80582e83ebe4abd68bc76ac50c28e42
|
File details
Details for the file nextpy_framework-2.2.0-py3-none-any.whl.
File metadata
- Download URL: nextpy_framework-2.2.0-py3-none-any.whl
- Upload date:
- Size: 130.2 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 |
84ea38d00d7d1d745d584d7897607325d391754e501ccb685bddfde5febef4d6
|
|
| MD5 |
d5f9ae75a9b0658b9404cc35fdb6f690
|
|
| BLAKE2b-256 |
37810a5123c83b3046dbc8b881c796351e0eb27682217d579f6fec4cef72453b
|