Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3b37740
feat(ci): add GitHub Pages deploy, Codecov upload, and base-href for …
Ryanditko Mar 31, 2026
d1b3532
feat(animation): add entrance animation system for components
Ryanditko Mar 31, 2026
e9e4bde
feat(error): add ErrorBoundary widget for graceful component error ha…
Ryanditko Mar 31, 2026
2165faf
feat(parser): integrate ErrorBoundary and EntranceAnimation into parse
Ryanditko Mar 31, 2026
606268e
feat(input): add declarative form validation via JSON props
Ryanditko Mar 31, 2026
cd6a92a
feat(a11y): add Semantics label to text component
Ryanditko Mar 31, 2026
b5bb60a
feat(a11y): add Semantics button label to button component
Ryanditko Mar 31, 2026
451511b
feat(a11y): add Semantics image label to image component
Ryanditko Mar 31, 2026
5e8a8f8
feat(a11y): add Semantics label to icon component
Ryanditko Mar 31, 2026
b0a4205
feat(a11y): add Semantics toggled label to switch component
Ryanditko Mar 31, 2026
ce5dc80
feat(a11y): add Semantics checked label to checkbox component
Ryanditko Mar 31, 2026
feb3217
chore(exports): add animation and error boundary barrel exports
Ryanditko Mar 31, 2026
aa226e4
feat(demo): add validation rules and entrance animations to form screen
Ryanditko Mar 31, 2026
799a26e
feat(server): add mock Dart Shelf backend serving JSON contracts via …
Ryanditko Mar 31, 2026
6eb1173
test(integration): add navigation tests for showcase, form, and landing
Ryanditko Mar 31, 2026
6bf61e2
test(integration): add playground screen selector and format button t…
Ryanditko Mar 31, 2026
94b47ca
docs: document validation, animations, error boundary, a11y, and mock…
Ryanditko Mar 31, 2026
76f2cfd
docs: update README with live demo, badges, new features, and mock se…
Ryanditko Mar 31, 2026
dde9bb1
fix(ci): remove GitHub Pages deploy job, deploy is handled by Vercel
Ryanditko Mar 31, 2026
731e48f
docs: remove GitHub Pages live demo link from README
Ryanditko Mar 31, 2026
6ab550c
chore: add MIT license file
Ryanditko Mar 31, 2026
d588c3b
chore: add server dependencies to .gitignore
Ryanditko Mar 31, 2026
3491007
chore: exclude server directory from Flutter analyzer
Ryanditko Mar 31, 2026
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
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ jobs:
cache: true
- run: flutter pub get
- run: flutter test --coverage --exclude-tags=golden
- uses: codecov/codecov-action@v4
with:
files: coverage/lcov.info
fail_ci_if_error: false
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

build-web:
name: Build Web
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ app.*.map.json
/linux/
/macos/
/windows/

# Server dependencies
server/.dart_tool/
server/pubspec.lock
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Ryan Rodrigues

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
77 changes: 52 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
![Material 3](https://img.shields.io/badge/Material_Design_3-820AD1?logo=materialdesign&logoColor=white)
![JSON](https://img.shields.io/badge/JSON_Contracts-000000?logo=json&logoColor=white)
![License](https://img.shields.io/badge/License-MIT-green)
[![CI](https://github.com/Ryanditko/flutter-backend-driven-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/Ryanditko/flutter-backend-driven-ui/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/Ryanditko/flutter-backend-driven-ui/graph/badge.svg)](https://codecov.io/gh/Ryanditko/flutter-backend-driven-ui)

[Architecture Docs](docs/ARCHITECTURE.md) · [Mock Server](server/README.md)

</div>

Expand Down Expand Up @@ -71,11 +75,13 @@ graph TB
expression["expression/"]
theme["theme/"]
validator["validator/"]
animation["animation/"]
error["error/"]
utils["utils/"]
end
subgraph presentation ["lib/presentation"]
pages["pages"]
widgets["widgets/ ×12"]
widgets["widgets/ ×22"]
end
subgraph playground ["lib/playground"]
pg_page["PlaygroundPage"]
Expand All @@ -84,6 +90,8 @@ graph TB
network --> models
models --> parser
expression --> parser
animation --> parser
error --> parser
parser --> widgets
widgets --> pages
pg_widgets --> parser
Expand All @@ -93,13 +101,13 @@ graph TB

## Features

### Components (19 types)
### Components (22 types)

| Category | Components |
|----------|-----------|
| **Layout** | `column` · `row` · `container` · `card` · `listView` · `stack` · `positioned` · `wrap` · `spacer` |
| **Layout** | `column` · `row` · `container` · `card` · `listView` · `stack` · `positioned` · `wrap` · `spacer` · `responsive` · `expanded` · `flexible` |
| **Leaf** | `text` · `button` · `image` · `input` · `divider` · `icon` · `chip` · `progress` · `badge` |
| **Interactive** | `switch` · `checkbox` |
| **Interactive** | `switch` · `checkbox` · `dropdown` · `tabBar` · `carousel` |

### Actions (7 types)

Expand All @@ -111,7 +119,14 @@ graph TB
- **Dynamic Theming** — per-screen color, typography, and brightness from JSON
- **Contract Validation** — schema checks before rendering with detailed warnings
- **Remote API + Caching** — `HttpApiClient` for HTTP fetching, `CachedApiClient` with TTL
- **Playground** — live JSON editor with split-view preview, screen selector, and auto-render
- **Playground** — live JSON editor with syntax highlighting, split-view preview, and screen selector
- **Form Validation** — declarative `required`, `minLength`, `maxLength`, `pattern` rules from JSON
- **Entrance Animations** — `fadeIn`, `slideUp`, `slideLeft`, `scale` per-component via `props.animation`
- **Error Boundary** — graceful error handling per component, prevents cascading failures
- **Accessibility** — `Semantics` labels on all interactive and leaf components
- **Responsive Layout** — breakpoint system (compact / medium / expanded) with `responsive`, `expanded`, `flexible`
- **Page Transitions** — animated navigation with fade, slide-up, and horizontal slide routes
- **Mock Backend** — standalone Dart Shelf server serving contracts via REST API

---

Expand All @@ -121,10 +136,11 @@ graph TB
|--------|-------------|
| `home` | Welcome page with navigation to all demos and a banner image |
| `profile` | User profile with avatar, details card, and snackbar action |
| `form` | Feedback form with text inputs and submit |
| `form` | Feedback form with validation, entrance animations, and submit |
| `components_showcase` | Every component type in one screen |
| `expressions_demo` | Template interpolation and conditional visibility |
| `theme_demo` | Dark theme applied via JSON contract |
| `new_components` | Dropdown, tab bar, and carousel showcase |

---

Expand All @@ -140,6 +156,16 @@ The landing page offers two modes:
- **App Demo** — navigate through pre-built screens loaded from `assets/screens/`
- **Playground** — edit JSON contracts and preview rendered output in real-time

### Running the Mock Server

```bash
cd server
dart pub get
dart run bin/server.dart
```

The server starts on `http://localhost:8080` and serves contracts from `assets/screens/`.

---

## JSON Contract Example
Expand All @@ -163,20 +189,28 @@ The landing page offers two modes:
"children": [
{
"type": "text",
"props": { "content": "Hi, {{user.name}}!", "style": { "fontSize": 24 } }
"props": {
"content": "Hi, {{user.name}}!",
"style": { "fontSize": 24 },
"animation": { "type": "fadeIn", "duration": 500 }
}
},
{
"type": "input",
"id": "email",
"props": {
"label": "Email",
"validation": {
"required": true,
"pattern": "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$",
"message": "Enter a valid email"
}
}
},
{
"type": "button",
"props": { "label": "Go to Profile" },
"action": { "type": "navigate", "targetScreenId": "profile" }
},
{
"type": "card",
"visible": "{{user.name}}",
"props": { "padding": 16 },
"children": [
{ "type": "text", "props": { "content": "Visible only when user.name is truthy" } }
]
}
]
}
Expand Down Expand Up @@ -211,6 +245,7 @@ _registry.register('yourType', buildYourComponent);
## Documentation

- [Architecture & Schema Specification](docs/ARCHITECTURE.md)
- [Mock Server](server/README.md)

---

Expand All @@ -222,20 +257,12 @@ _registry.register('yourType', buildYourComponent);
| Framework | ![Flutter](https://img.shields.io/badge/Flutter_3.x-02569B?logo=flutter&logoColor=white) |
| Design System | ![Material 3](https://img.shields.io/badge/Material_Design_3-820AD1?logo=materialdesign&logoColor=white) |
| Data Format | ![JSON](https://img.shields.io/badge/JSON-000000?logo=json&logoColor=white) |
| Backend | ![Shelf](https://img.shields.io/badge/Dart_Shelf-0175C2?logo=dart&logoColor=white) |
| CI/CD | ![GitHub Actions](https://img.shields.io/badge/GitHub_Actions-2088FF?logo=githubactions&logoColor=white) |
| Architecture | Server-Driven UI / Backend-Driven Content |

---

## Screenshots

> Run the app and capture screenshots to add here.

| Landing | Home | Components | Playground |
|---------|------|------------|------------|
| *landing* | *home* | *components showcase* | *playground* |

---

<div align="center">

Built with Flutter + Material Design 3
Expand Down
4 changes: 4 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

analyzer:
exclude:
- server/**

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
Expand Down
36 changes: 30 additions & 6 deletions assets/screens/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,65 @@
"type": "text",
"props": {
"content": "We value your feedback",
"style": { "fontSize": 22, "fontWeight": "bold" }
"style": { "fontSize": 22, "fontWeight": "bold" },
"animation": { "type": "fadeIn", "duration": 400 }
}
},
{ "type": "spacer", "props": { "height": 8 } },
{
"type": "text",
"props": {
"content": "Fill in the fields below and submit.",
"style": { "fontSize": 14, "color": "#666666" }
"style": { "fontSize": 14, "color": "#666666" },
"animation": { "type": "fadeIn", "duration": 400, "delay": 100 }
}
},
{ "type": "spacer", "props": { "height": 24 } },
{
"type": "input",
"id": "name",
"props": { "label": "Your Name", "hint": "Enter your full name" }
"props": {
"label": "Your Name",
"hint": "Enter your full name",
"animation": { "type": "slideUp", "duration": 400, "delay": 150 },
"validation": { "required": true, "minLength": 2, "message": "Name must be at least 2 characters" }
}
},
{ "type": "spacer", "props": { "height": 12 } },
{
"type": "input",
"id": "email",
"props": { "label": "Email", "hint": "you@example.com", "keyboardType": "emailAddress" }
"props": {
"label": "Email",
"hint": "you@example.com",
"keyboardType": "emailAddress",
"animation": { "type": "slideUp", "duration": 400, "delay": 250 },
"validation": {
"required": true,
"pattern": "^[\\w\\-\\.]+@([\\w\\-]+\\.)+[\\w\\-]{2,4}$",
"message": "Please enter a valid email address"
}
}
},
{ "type": "spacer", "props": { "height": 12 } },
{
"type": "input",
"id": "message",
"props": { "label": "Message", "hint": "Tell us what you think...", "maxLines": 4 }
"props": {
"label": "Message",
"hint": "Tell us what you think...",
"maxLines": 4,
"animation": { "type": "slideUp", "duration": 400, "delay": 350 },
"validation": { "required": true, "minLength": 10, "maxLength": 500 }
}
},
{ "type": "spacer", "props": { "height": 24 } },
{
"type": "button",
"props": {
"label": "Submit Feedback",
"style": { "backgroundColor": "#820AD1", "textColor": "#FFFFFF" }
"style": { "backgroundColor": "#820AD1", "textColor": "#FFFFFF" },
"animation": { "type": "scale", "duration": 500, "delay": 450 }
},
"action": { "type": "submit" }
},
Expand Down
Loading
Loading