Skip to content

Commit 5f35161

Browse files
committed
and blazor upgraded post
1 parent 5e86c19 commit 5f35161

File tree

5 files changed

+244
-4
lines changed

5 files changed

+244
-4
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
title: Text to Blazor CRUD upgraded to use best LLMs
3+
summary: Discover how to quickly generate Blazor Admin CRUD Apps from a text description using the new okai tool
4+
tags: [okai,ai,autoquery,blazor,vue]
5+
author: Demis Bellot
6+
image: ./img/posts/text-to-blazor-upgraded/bg.webp
7+
---
8+
9+
Text to Blazor has upgraded to use the best coding LLMs from Anthropic, Google, Moonshot AI,
10+
Alibaba and xAI to power its app generation capabilities to create new Blazor Admin CRUD
11+
Apps from just a text description.
12+
13+
<section class="not-prose">
14+
<div id="text-to-blazor" class="bg-white dark:bg-black pb-8">
15+
<a href="/text-to-blazor">
16+
<div class="py-4 mx-auto flex justify-between items-center max-w-screen-lg">
17+
<div class="mx-auto text-center">
18+
<img class="mx-auto h-20" src="/img/models/anthropic.svg">
19+
<div>
20+
<b class="block">Anthropic</b>
21+
<span class="text-sm">Claude 4.0 Sonnet</span>
22+
</div>
23+
</div>
24+
<div class="mx-auto text-center">
25+
<img class="mx-auto h-20" src="/img/models/gemini-pro.svg">
26+
<div>
27+
<b class="block">Google</b>
28+
<span class="text-sm">Gemini 2.5 Pro</span>
29+
</div>
30+
</div>
31+
<div class="mx-auto text-center">
32+
<img class="mx-auto h-20" src="/img/models/moonshot.svg">
33+
<div>
34+
<b class="block">Moonshot AI</b>
35+
<span class="text-sm">Kimi K2 (1T)</span>
36+
</div>
37+
</div>
38+
<div class="mx-auto text-center">
39+
<img class="mx-auto h-20 p-2" src="/img/models/qwen.svg">
40+
<div>
41+
<b class="block">Alibaba</b>
42+
<span class="text-sm">Qwen 3 Coder (480B)</span>
43+
</div>
44+
</div>
45+
<div class="mx-auto text-center">
46+
<img class="mx-auto h-20 p-2" src="/img/models/xai.svg">
47+
<div>
48+
<b class="block">xAI</b>
49+
<span class="text-sm">Grok Code Fast</span>
50+
</div>
51+
</div>
52+
</div>
53+
</a>
54+
<div class="my-8 mx-auto w-[340px]">
55+
<a href="/text-to-blazor"
56+
class="flex items-center rounded-full bg-white px-6 py-3 text-lg font-semibold text-green-900 shadow-sm ring-2 ring-inset ring-green-300 hover:bg-gray-50">
57+
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 mr-4" viewBox="0 0 32 32"><path fill="currentColor" d="M19 22v-2h1v-7h-1v-2h4v2h-1v7h1v2zm-3.5 0h2L14 11h-3L7.503 22h2l.601-2h4.778zm-4.794-4l1.628-5.411l.256-.003L14.264 18zM32 4h-4V0h-2v4h-4v2h4v4h2V6h4zm-2 8h2v2h-2zM18 0h2v2h-2z"/><path fill="currentColor" d="M32 32H0V0h14v2H2v28h28V18h2z"/></svg>
58+
Text to Blazor CRUD App
59+
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 ml-1" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/><path fill="currentColor" d="M16.06 10.94a1.5 1.5 0 0 1 0 2.12l-5.656 5.658a1.5 1.5 0 1 1-2.121-2.122L12.879 12L8.283 7.404a1.5 1.5 0 0 1 2.12-2.122l5.658 5.657Z"/></g></svg>
60+
</a>
61+
</div>
62+
</div>
63+
</section>
64+
65+
Just enter in the type of App you want to create or the Data Models it needs and it will generate
66+
a new Blazor CRUD App for you.
67+
68+
<div class="flex justify-center">
69+
<lite-youtube class="w-full mx-4 my-4" width="560" height="315" videoid="Bd283EYJKxM" style="background-image: url('https://img.youtube.com/vi/Bd283EYJKxM/maxresdefault.jpg')"></lite-youtube>
70+
</div>
71+
72+
[![](/img/posts/text-to-blazor/text-to-blazor-prompt.webp)](/text-to-blazor)
73+
74+
<div class="pb-4 not-prose flex justify-center">
75+
<a href="https://servicestack.net/text-to-blazor" class="text-3xl text-indigo-600 hover:text-indigo-800">https://servicestack.net/text-to-blazor</a>
76+
</div>
77+
78+
This will query 5 different high quality AI models to generate 5 different Data Models, APIs, DB Migrations
79+
and Admin UIs which you can browse to find the one that best matches your requirements.
80+
81+
[![](/img/posts/text-to-blazor-upgraded/text-to-blazor-gen.webp)](/text-to-blazor)
82+
83+
### Using AI to only generate Data Models
84+
85+
Whilst the result is a working CRUD App, the approach taken is very different from most AI tools
86+
which uses AI to generate the entire App that ends up with a whole new code-base developers didn't write
87+
which they'd now need to maintain.
88+
89+
Instead AI is only used to generate the initial Data Models within a **TypeScript Declaration file**
90+
which we've found is the best format supported by AI models that's also the best typed DSL for defining
91+
data models with minimal syntax that's easy for humans to read and write.
92+
93+
### Download preferred Blazor Vue CRUD App
94+
95+
Once you've decided on the Data Models that best matches your requirements, you can download your preferred
96+
generated Blazor Vue CRUD App:
97+
98+
[![](/img/posts/text-to-blazor/text-to-blazor-download.webp)](/text-to-blazor)
99+
100+
### Blazor Admin App
101+
102+
**Admin Only** - ideal for internal Admin Apps where the Admin UI is the Primary UI
103+
104+
![](/img/posts/text-to-blazor/okai-blazor-admin.webp)
105+
106+
### Blazor Vue App
107+
108+
**UI + Admin** - Creates a new [blazor-vue](https://blazor-vue.web-templates.io) template ideal for Internet or public facing Apps,
109+
sporting a full-featured public facing UI for a Web App's users whilst enabling a back-office CRUD UI
110+
for Admin Users to manage their data.
111+
112+
![](/img/posts/text-to-blazor/okai-blazor-vue.webp)
113+
114+
Clicking on the **Admin UI** button will take you to the Admin UI at `/admin`:
115+
116+
![](/img/posts/text-to-blazor/okai-blazor-vue-admin.webp)
117+
118+
## Run Migrations
119+
120+
In order to create the necessary tables for the new functionality, you'll need to run the DB Migrations.
121+
122+
If migrations have never been run before, you can run the `migrate` npm script to create the initial database:
123+
124+
:::sh
125+
npm run migrate
126+
:::
127+
128+
If you've already run the migrations before, you can run the `rerun:last` npm script to drop and re-run the last migration:
129+
130+
:::sh
131+
npm run rerun:last
132+
:::
133+
134+
Alternatively you can nuke the App's database (e.g. `App_Data/app.db`) and recreate it from scratch with `npm run migrate`.
135+
136+
## Instant CRUD UI
137+
138+
After running the DB migrations, you can hit the ground running and start using the Admin UI to manage the new
139+
Data Model RDBMS Tables:
140+
141+
:::youtube 8buo_ce3SNM
142+
Using AutoQuery CRUD UI in a Text to Blazor App
143+
:::
144+
145+
### Create new Records from Search Dialog
146+
147+
We're continually improving the UX of the [AutoQueryGrid Component](/vue/autoquerygrid) used in generating CRUD UIs to enable a more productive and seamless workflow. A change added to that end that you can see in the above video is the ability to add new Records from a Search dialog:
148+
149+
![](/img/posts/text-to-blazor/autoquerygrid-new2.webp)
150+
151+
This now lets you start immediately creating new records without needing to create any lookup entries beforehand.
152+
153+
## Audited Data Models
154+
155+
The TypeScript Data Models enable a rapid development experience for defining an App's Data Models which are used
156+
to generate the necessary AutoQuery CRUD APIs to support an Admin UI.
157+
158+
An example of the productivity of this approach is the effortless support for maintaining a detailed audit history for changes to select tables by inheriting from the `AuditBase` base class, e.g:
159+
160+
```ts
161+
export class Job extends AuditBase {
162+
...
163+
}
164+
```
165+
166+
Which can then be regenerated using the name of the TypeScript Model definitions:
167+
168+
:::sh
169+
npx okai Jobs.d.ts
170+
:::
171+
172+
This will include additional `CreatedBy`, `CreatedDate`, `ModifiedBy`, `ModifiedDate`, `DeletedBy` and `DeletedDate`
173+
properties to the specified Table and also generates the necessary
174+
[Audit Behaviors](https://docs.servicestack.net/autoquery/crud#apply-generic-crud-behaviors)
175+
on the AutoQuery APIs to maintain the audit history for each CRUD operation.
176+
177+
### AutoQuery CRUD Audit Log
178+
179+
As the **blazor-admin** and **blazor-vue** templates are configured to use the [AutoQuery CRUD Executable Audit Log](https://docs.servicestack.net/autoquery/audit-log)
180+
in its [Configure.AutoQuery.cs](https://github.com/NetCoreTemplates/blazor-admin/blob/main/MyApp/Configure.AutoQuery.cs)
181+
the Audit Behaviors will also maintain an Audit Trail of all CRUD operations which can be viewed in the Admin UI:
182+
183+
![](/img/posts/text-to-blazor/okai-audit-form.webp)

MyApp/wwwroot/css/app.css

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@
441441
.right-0 {
442442
right: calc(var(--spacing) * 0);
443443
}
444+
.right-1 {
445+
right: calc(var(--spacing) * 1);
446+
}
444447
.right-1\/2 {
445448
right: calc(1/2 * 100%);
446449
}
@@ -918,6 +921,10 @@
918921
.aspect-video {
919922
aspect-ratio: var(--aspect-video);
920923
}
924+
.size-4 {
925+
width: calc(var(--spacing) * 4);
926+
height: calc(var(--spacing) * 4);
927+
}
921928
.size-5 {
922929
width: calc(var(--spacing) * 5);
923930
height: calc(var(--spacing) * 5);
@@ -2863,6 +2870,9 @@
28632870
--tw-ring-color: color-mix(in oklab, var(--color-white) 10%, transparent);
28642871
}
28652872
}
2873+
.ring-offset-slate-400 {
2874+
--tw-ring-offset-color: var(--color-slate-400);
2875+
}
28662876
.outline {
28672877
outline-style: var(--tw-outline-style);
28682878
outline-width: 1px;
@@ -5907,6 +5917,14 @@
59075917
background-color: var(--color-black);
59085918
}
59095919
}
5920+
.dark\:bg-black\/70 {
5921+
&:where(.dark, .dark *) {
5922+
background-color: color-mix(in srgb, #000 70%, transparent);
5923+
@supports (color: color-mix(in lab, red, red)) {
5924+
background-color: color-mix(in oklab, var(--color-black) 70%, transparent);
5925+
}
5926+
}
5927+
}
59105928
.dark\:bg-black\/90 {
59115929
&:where(.dark, .dark *) {
59125930
background-color: color-mix(in srgb, #000 90%, transparent);
@@ -6079,11 +6097,21 @@
60796097
fill: var(--color-gray-300);
60806098
}
60816099
}
6100+
.dark\:fill-slate-400 {
6101+
&:where(.dark, .dark *) {
6102+
fill: var(--color-slate-400);
6103+
}
6104+
}
60826105
.dark\:fill-slate-500 {
60836106
&:where(.dark, .dark *) {
60846107
fill: var(--color-slate-500);
60856108
}
60866109
}
6110+
.dark\:stroke-slate-400 {
6111+
&:where(.dark, .dark *) {
6112+
stroke: var(--color-slate-400);
6113+
}
6114+
}
60876115
.dark\:text-black {
60886116
&:where(.dark, .dark *) {
60896117
color: var(--color-black);
@@ -6288,6 +6316,11 @@
62886316
--tw-ring-offset-color: var(--color-green-200);
62896317
}
62906318
}
6319+
.dark\:ring-offset-slate-700 {
6320+
&:where(.dark, .dark *) {
6321+
--tw-ring-offset-color: var(--color-slate-700);
6322+
}
6323+
}
62916324
.dark\:group-hover\:fill-slate-300 {
62926325
&:where(.dark, .dark *) {
62936326
&:is(:where(.group):hover *) {
@@ -6297,6 +6330,15 @@
62976330
}
62986331
}
62996332
}
6333+
.dark\:group-hover\:stroke-slate-300 {
6334+
&:where(.dark, .dark *) {
6335+
&:is(:where(.group):hover *) {
6336+
@media (hover: hover) {
6337+
stroke: var(--color-slate-300);
6338+
}
6339+
}
6340+
}
6341+
}
63006342
.dark\:group-hover\:text-white {
63016343
&:where(.dark, .dark *) {
63026344
&:is(:where(.group):hover *) {
@@ -6665,20 +6707,20 @@
66656707
}
66666708
}
66676709
}
6668-
.dark\:hover\:text-slate-200 {
6710+
.dark\:hover\:text-slate-300 {
66696711
&:where(.dark, .dark *) {
66706712
&:hover {
66716713
@media (hover: hover) {
6672-
color: var(--color-slate-200);
6714+
color: var(--color-slate-300);
66736715
}
66746716
}
66756717
}
66766718
}
6677-
.dark\:hover\:text-slate-300 {
6719+
.dark\:hover\:text-slate-800 {
66786720
&:where(.dark, .dark *) {
66796721
&:hover {
66806722
@media (hover: hover) {
6681-
color: var(--color-slate-300);
6723+
color: var(--color-slate-800);
66826724
}
66836725
}
66846726
}
@@ -6768,6 +6810,13 @@
67686810
}
67696811
}
67706812
}
6813+
.dark\:focus\:ring-slate-700 {
6814+
&:where(.dark, .dark *) {
6815+
&:focus {
6816+
--tw-ring-color: var(--color-slate-700);
6817+
}
6818+
}
6819+
}
67716820
.dark\:active\:text-pink-50 {
67726821
&:where(.dark, .dark *) {
67736822
&:active {
110 KB
Loading
307 KB
Loading

MyApp/wwwroot/okai/accepted/index.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,5 +1277,13 @@
12771277
"provider": "anthropic",
12781278
"prompt": "I need an app to manage a simple real estate website.",
12791279
"groupName": "PropertyViewings"
1280+
},
1281+
{
1282+
"id": "1756705138800",
1283+
"model": "gemini-2.5-pro",
1284+
"timing": "34338",
1285+
"provider": "google",
1286+
"prompt": "An app for managing AI image and video generations",
1287+
"groupName": "Generations"
12801288
}
12811289
]

0 commit comments

Comments
 (0)