Skip to content

Commit a251cf3

Browse files
feat(devex): add project templates, Python SDK demo, quickstart scrip… (#359)
* feat(devex): add project templates, Python SDK demo, quickstart scripts, and Vercel deploy config - Add Templates page (/templates) to web dashboard with 6 project templates (React SDK Demo, Kanban Board, Social Media Clone, Python SDK Demo, TypeScript Quickstart, Python Quickstart) - Add sidebar navigation link for Templates - Create Python SDK demo project with full auth, CRUD, storage, mail demos and unit tests (6/6 passing with mocks) - Add interactive quickstart scripts for TypeScript and Python SDK scaffolding - Configure Vercel deployment for all frontend examples - Add CI workflow for example projects - Add comprehensive DevEx documentation (examples/DEVEX.md) * fix: use array form for providers prop in react-sdk-demo * fix: remove enableEmailPassword prop not in installed @urbackend/react@0.1.1 types * fix: use only supported props for @urbackend/react@0.1.1 UrAuth (providers, theme, onSuccess) * fix: address security and compatibility findings 1. CI: add permissions: contents: read, persist-credentials: false, include workflow in paths, pin Python deps 2. DEVEX.md: use immutable release tag + checksum verification for quickstart scripts 3. main.py: use Optional[dict] instead of dict | None for Python 3.9 compat 4. Quickstart scripts: remove SECRET_KEY/PROJECT_ID from client scaffolds, keep only publishable credentials 5. Python quickstart: fix base_url -> base parameter for UrBackendClient * fix: address Node 20 requirement and vercel.json config 1. setup-ts-sdk.sh: require Node.js 20+ (needed for global File constructor) 2. vercel.json: replace unsupported top-level deploy object with per-app config reference, each demo keeps its own vercel.json * fix: address review findings - Node 20, vercel links, clipboard promises, storage cleanup, test mocks 1. setup-ts-sdk.sh: require Node.js 20+ for global File constructor 2. Templates.jsx: fix invalid deployUrl for quickstart-ts, add Promise handling to copy buttons, card keyboard support already present 3. examples.yml: remove stray </write_to_file> artifact 4. DEVEX.md: replace placeholder checksums with actual SHA-256 digests 5. main.py: add remote file cleanup after storage upload 6. test_demo.py: remove module-level sys.modules override, use setup_method * node.js version fix * fix: remove stray </write_to_file> artifacts from examples.yml and vercel.json * fix: pin @urbackend/sdk to 0.4.2 and urbackend to 0.1.0 in CI - @urbackend/sdk@0.4.5 has broken exports, 0.4.2 works correctly - urbackend Python package only has 0.1.0 on PyPI, not 0.1.1 * fix: use sign_up instead of signup in auth demo and tests - Python SDK uses sign_up method name, not signup - Updated all mock setups, side effects, and assertions - Removed stray XML token from test_demo.py * fix: build local SDK workspaces before example CI builds - react-sdk-demo package-lock uses file: references to local SDKs - Add build steps for sdks/urbackend-sdk and sdks/urbackend-react * fix: use published npm packages instead of local file: references - Pin @urbackend/sdk to 0.4.2 in all examples - Pin @urbackend/react to 0.1.0 in react-sdk-demo - Remove local file: references that require building SDKs first - Update CI to build from root with workspace flags * fix: use working-directory instead of --workspace for examples - npm workspaces must be defined in root package.json - examples are not in the workspaces array - Use defaults.run.working-directory instead
2 parents ba6fb3d + ad7cf9e commit a251cf3

21 files changed

Lines changed: 4223 additions & 1336 deletions

File tree

‎.github/workflows/examples.yml‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: Examples CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'examples/**'
8+
- 'sdks/**'
9+
- '.github/workflows/examples.yml'
10+
pull_request:
11+
branches: [ main ]
12+
paths:
13+
- 'examples/**'
14+
- 'sdks/**'
15+
- '.github/workflows/examples.yml'
16+
17+
permissions:
18+
contents: read
19+
20+
jobs:
21+
react-sdk-demo:
22+
runs-on: ubuntu-latest
23+
defaults:
24+
run:
25+
working-directory: examples/react-sdk-demo
26+
steps:
27+
- uses: actions/checkout@v4
28+
with:
29+
persist-credentials: false
30+
- uses: actions/setup-node@v4
31+
with:
32+
node-version: '20'
33+
cache: 'npm'
34+
cache-dependency-path: examples/react-sdk-demo/package-lock.json
35+
- run: npm install
36+
- run: npm run build
37+
38+
sdk-kanban-client:
39+
runs-on: ubuntu-latest
40+
defaults:
41+
run:
42+
working-directory: examples/sdk-kanban/client
43+
steps:
44+
- uses: actions/checkout@v4
45+
with:
46+
persist-credentials: false
47+
- uses: actions/setup-node@v4
48+
with:
49+
node-version: '20'
50+
cache: 'npm'
51+
cache-dependency-path: examples/sdk-kanban/client/package-lock.json
52+
- run: npm install
53+
- run: npm run build
54+
55+
social-demo-client:
56+
runs-on: ubuntu-latest
57+
defaults:
58+
run:
59+
working-directory: examples/social-demo/client
60+
steps:
61+
- uses: actions/checkout@v4
62+
with:
63+
persist-credentials: false
64+
- uses: actions/setup-node@v4
65+
with:
66+
node-version: '20'
67+
cache: 'npm'
68+
cache-dependency-path: examples/social-demo/client/package-lock.json
69+
- run: npm install
70+
- run: npm run build
71+
72+
python-sdk-demo:
73+
runs-on: ubuntu-latest
74+
defaults:
75+
run:
76+
working-directory: examples/python-sdk-demo
77+
steps:
78+
- uses: actions/checkout@v4
79+
with:
80+
persist-credentials: false
81+
- uses: actions/setup-python@v5
82+
with:
83+
python-version: '3.11'
84+
- run: |
85+
python -m pip install --upgrade pip
86+
pip install urbackend==0.1.0 python-dotenv==1.2.2 pytest==9.1.1
87+
- run: pytest tests/ -v

‎apps/web-dashboard/src/App.jsx‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Dashboard from './pages/Dashboard';
1212
import ProjectDetails from './pages/ProjectDetails';
1313
import CreateProject from './pages/CreateProject';
1414
import CreateCollection from './pages/CreateCollection';
15+
import Templates from './pages/Templates';
1516
import NotFound from './pages/NotFound';
1617
import Analytics from './pages/Analytics';
1718
import Releases from './pages/Releases';
@@ -81,6 +82,14 @@ function AppContent() {
8182
</ProtectedRoute>
8283
} />
8384

85+
<Route path="/templates" element={
86+
<ProtectedRoute>
87+
<MainLayout>
88+
<Templates />
89+
</MainLayout>
90+
</ProtectedRoute>
91+
} />
92+
8493
<Route path="/create-project" element={
8594
<ProtectedRoute allowIncompleteOnboarding>
8695
<MainLayout>

‎apps/web-dashboard/src/components/Layout/Sidebar.jsx‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { Link, useLocation, useParams } from 'react-router-dom';
22
import { useAuth } from '../../context/AuthContext';
33
import {
44
LayoutDashboard, Database, Shield, HardDrive, Settings, BarChart2,
5-
ArrowLeft, LogOut, X, Rocket, Webhook, Users, Mail, ChevronLeft, ChevronRight
5+
ArrowLeft, LogOut, X, Rocket, Webhook, Users, Mail, ChevronLeft, ChevronRight,
6+
LayoutTemplate
67
} from 'lucide-react';
78
import ThemeToggle from '../ThemeToggle';
89

@@ -81,6 +82,9 @@ function Sidebar({ logo, isOpen, onClose, isCollapsed, onToggleCollapse }) {
8182
<Link to="/dashboard" onClick={handleNavClick} className={`nav-item ${isActive('/dashboard') ? 'active' : ''}`} {...navA11yProps('Dashboard')}>
8283
<LayoutDashboard size={16} /> <span>Dashboard</span>
8384
</Link>
85+
<Link to="/templates" onClick={handleNavClick} className={`nav-item ${isActive('/templates') ? 'active' : ''}`} {...navA11yProps('Templates')}>
86+
<LayoutTemplate size={16} /> <span>Templates</span>
87+
</Link>
8488
<Link to="/releases" onClick={handleNavClick} className={`nav-item ${isActive('/releases') ? 'active' : ''}`} {...navA11yProps("What's New")}>
8589
<Rocket size={16} /> <span>What's New</span>
8690
</Link>

0 commit comments

Comments
 (0)