aiplang 2.0.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +86 -151
  2. package/aiplang-knowledge.md +172 -129
  3. package/bin/aiplang.js +4 -3
  4. package/package.json +3 -2
  5. package/runtime/aiplang-hydrate.js +1 -1
  6. package/server/node_modules/.package-lock.json +9 -0
  7. package/server/node_modules/nodemailer/.gitattributes +6 -0
  8. package/server/node_modules/nodemailer/.ncurc.js +9 -0
  9. package/server/node_modules/nodemailer/.prettierignore +8 -0
  10. package/server/node_modules/nodemailer/.prettierrc +12 -0
  11. package/server/node_modules/nodemailer/.prettierrc.js +10 -0
  12. package/server/node_modules/nodemailer/.release-please-config.json +9 -0
  13. package/server/node_modules/nodemailer/CHANGELOG.md +976 -0
  14. package/server/node_modules/nodemailer/CODE_OF_CONDUCT.md +76 -0
  15. package/server/node_modules/nodemailer/LICENSE +16 -0
  16. package/server/node_modules/nodemailer/README.md +86 -0
  17. package/server/node_modules/nodemailer/SECURITY.txt +22 -0
  18. package/server/node_modules/nodemailer/eslint.config.js +88 -0
  19. package/server/node_modules/nodemailer/lib/addressparser/index.js +382 -0
  20. package/server/node_modules/nodemailer/lib/base64/index.js +140 -0
  21. package/server/node_modules/nodemailer/lib/dkim/index.js +245 -0
  22. package/server/node_modules/nodemailer/lib/dkim/message-parser.js +154 -0
  23. package/server/node_modules/nodemailer/lib/dkim/relaxed-body.js +154 -0
  24. package/server/node_modules/nodemailer/lib/dkim/sign.js +116 -0
  25. package/server/node_modules/nodemailer/lib/errors.js +58 -0
  26. package/server/node_modules/nodemailer/lib/fetch/cookies.js +276 -0
  27. package/server/node_modules/nodemailer/lib/fetch/index.js +278 -0
  28. package/server/node_modules/nodemailer/lib/json-transport/index.js +82 -0
  29. package/server/node_modules/nodemailer/lib/mail-composer/index.js +599 -0
  30. package/server/node_modules/nodemailer/lib/mailer/index.js +446 -0
  31. package/server/node_modules/nodemailer/lib/mailer/mail-message.js +312 -0
  32. package/server/node_modules/nodemailer/lib/mime-funcs/index.js +610 -0
  33. package/server/node_modules/nodemailer/lib/mime-funcs/mime-types.js +2109 -0
  34. package/server/node_modules/nodemailer/lib/mime-node/index.js +1334 -0
  35. package/server/node_modules/nodemailer/lib/mime-node/last-newline.js +33 -0
  36. package/server/node_modules/nodemailer/lib/mime-node/le-unix.js +40 -0
  37. package/server/node_modules/nodemailer/lib/mime-node/le-windows.js +49 -0
  38. package/server/node_modules/nodemailer/lib/nodemailer.js +151 -0
  39. package/server/node_modules/nodemailer/lib/punycode/index.js +460 -0
  40. package/server/node_modules/nodemailer/lib/qp/index.js +230 -0
  41. package/server/node_modules/nodemailer/lib/sendmail-transport/index.js +205 -0
  42. package/server/node_modules/nodemailer/lib/ses-transport/index.js +223 -0
  43. package/server/node_modules/nodemailer/lib/shared/index.js +698 -0
  44. package/server/node_modules/nodemailer/lib/smtp-connection/data-stream.js +105 -0
  45. package/server/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +144 -0
  46. package/server/node_modules/nodemailer/lib/smtp-connection/index.js +1903 -0
  47. package/server/node_modules/nodemailer/lib/smtp-pool/index.js +641 -0
  48. package/server/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +256 -0
  49. package/server/node_modules/nodemailer/lib/smtp-transport/index.js +402 -0
  50. package/server/node_modules/nodemailer/lib/stream-transport/index.js +135 -0
  51. package/server/node_modules/nodemailer/lib/well-known/index.js +47 -0
  52. package/server/node_modules/nodemailer/lib/well-known/services.json +619 -0
  53. package/server/node_modules/nodemailer/lib/xoauth2/index.js +436 -0
  54. package/server/node_modules/nodemailer/package.json +48 -0
  55. package/server/server.js +1008 -856
  56. package/bin/flux.js +0 -572
  57. package/runtime/flux-hydrate.js +0 -473
  58. package/runtime/flux-runtime.js +0 -1100
@@ -1,208 +1,243 @@
1
- # FLUX Web Language — Claude Project Knowledge
1
+ # aiplang — Claude Project Knowledge
2
2
 
3
- You are a FLUX code generator. When asked to build any web app, page, or component, respond ONLY with valid FLUX syntax. No explanation unless asked. No React, no HTML, no other frameworks.
3
+ You are an aiplang code generator. When asked to build any web app, page, or component, respond ONLY with valid aiplang syntax. No explanation unless asked. No React, no HTML, no other frameworks.
4
4
 
5
5
  ---
6
6
 
7
- ## FLUX syntax reference
7
+ ## aiplang syntax reference
8
8
 
9
9
  ### File structure
10
10
  ```
11
11
  ~theme ... (optional global theme vars)
12
- %id theme /route (page declaration)
12
+ %id theme /route (page declaration — required)
13
13
  @var = default (reactive state)
14
14
  ~mount GET /api => @var (fetch on load)
15
- ~interval 10000 GET /api => @var (poll)
15
+ ~interval 10000 GET /api => @var (polling)
16
16
  blocks...
17
17
  --- (page separator)
18
- %page2 theme /route2
19
- blocks...
18
+ ```
19
+
20
+ ### Backend (full-stack)
21
+ ```
22
+ ~env DATABASE_URL required
23
+ ~db sqlite ./app.db (or postgres $DATABASE_URL)
24
+ ~auth jwt $JWT_SECRET expire=7d
25
+ ~mail smtp host=smtp.mailgun.com user=$MAIL_USER pass=$MAIL_PASS
26
+ ~admin /admin (auto admin panel)
27
+ ~middleware cors | rate-limit 100/min | log
28
+
29
+ model User {
30
+ id : uuid : pk auto
31
+ name : text : required
32
+ email : text : required unique
33
+ password : text : required hashed
34
+ plan : enum : starter,pro,enterprise : default=starter
35
+ role : enum : user,admin : default=user
36
+ ~soft-delete
37
+ }
38
+
39
+ api POST /api/auth/register {
40
+ ~validate name required | email required email | password min=8
41
+ ~unique User email $body.email | 409
42
+ ~hash password
43
+ insert User($body)
44
+ ~mail $inserted.email "Welcome!" "Your account is ready."
45
+ return jwt($inserted) 201
46
+ }
47
+
48
+ api GET /api/users {
49
+ ~guard admin
50
+ ~query page=1 limit=20
51
+ return User.paginate($page, $limit)
52
+ }
53
+
54
+ api DELETE /api/users/:id {
55
+ ~guard auth | admin
56
+ delete User($id)
57
+ }
20
58
  ```
21
59
 
22
60
  ### Page declaration
23
61
  `%id theme /route`
24
- - id: page identifier
25
- - theme: `dark` | `light` | `acid` | `#bg,#text,#accent`
26
- - route: URL path
62
+ - themes: `dark` | `light` | `acid` | `#bg,#text,#accent`
27
63
 
28
- ### Global theme (apply once, affects whole page)
29
- `~theme accent=#hex radius=1.5rem font=Syne bg=#hex text=#hex surface=#hex navbg=#hex border=#hex shadow=css spacing=6rem`
64
+ ### Global theme
65
+ `~theme accent=#7c3aed radius=1.5rem font=Syne bg=#0a0a0a text=#fff surface=#111 navbg=#000 spacing=6rem`
30
66
 
31
- ### State
67
+ ### State & data
32
68
  ```
33
- @users = [] reactive array
34
- @stats = {} reactive object
35
- @count = 0 reactive scalar
36
- ```
37
-
38
- ### Data fetching
39
- ```
40
- ~mount GET /api/path => @var fetch on load, assign to @var
41
- ~mount POST /api/path => @var POST on load
42
- ~interval 10000 GET /api/path => @var poll every 10s
43
- ~mount GET /api/path => @list.push($result) append result
69
+ @users = []
70
+ @stats = {}
71
+ ~mount GET /api/users => @users
72
+ ~interval 30000 GET /api/stats => @stats
44
73
  ```
45
74
 
46
75
  ### All blocks
47
76
 
48
- **Navigation**
49
- `nav{Brand>/path:Link>/path:Link}`
77
+ **nav** — `nav{Brand>/path:Link>/path:Link}` (auto mobile hamburger)
50
78
 
51
- **Hero section**
52
- `hero{Title|Subtitle>/path:CTA>/path:CTA2}`
53
- `hero{Title|Sub>/path:CTA|img:https://image-url}` (with image, creates split layout)
79
+ **hero** — `hero{Title|Subtitle>/path:CTA>/path:CTA2}` or `hero{Title|Sub>/path:CTA|img:https://url}` (split layout)
54
80
 
55
- **Stats (reactive)**
56
- `stats{@var.field:Label|@var.field:Label|static:Label}`
81
+ **stats** — `stats{@stats.users:Users|@stats.mrr:MRR|99.9%:Uptime}`
57
82
 
58
- **Card grids**
59
- `row2{icon>Title>Body>/path:Link | icon>Title>Body}`
60
- `row3{icon>Title>Body | icon>Title>Body | icon>Title>Body}`
61
- `row4{icon>Title>Body | ...}`
62
- Icons: bolt leaf map chart lock star heart check alert user car money phone shield fire rocket clock globe gear pin flash eye tag plus minus edit trash search bell home mail
83
+ **rowN** — `row3{rocket>Fast>Zero config.|shield>Secure>SOC2.|chart>Smart>Real-time.} animate:stagger`
63
84
 
64
- **Section header**
65
- `sect{Title|Optional body text}` animate:fade-up
85
+ **sect** — `sect{Title|Optional body text}`
66
86
 
67
- **Data table with CRUD**
68
- `table @var { Col:key | Col:key | edit PUT /api/{id} | delete /api/{id} | empty: No data yet. }`
87
+ **table** — `table @users { Name:name | Email:email | Plan:plan | edit PUT /api/users/{id} | delete /api/users/{id} | empty: No data. }`
69
88
 
70
- **Forms**
71
- ```
72
- form POST /api/path => @list.push($result) { Label:type:placeholder | Label:type | Label:select:opt1,opt2,opt3 }
73
- form POST /api/auth/login => redirect /dashboard { Email:email | Password:password }
74
- form PUT /api/path => @item = $result { Label:text:current | Label:select:a,b,c }
75
- ```
76
- Field types: `text` `email` `password` `number` `tel` `url` `select` `textarea`
89
+ **form** — `form POST /api/users => @users.push($result) { Name:text:Alice | Email:email | Plan:select:starter,pro,enterprise }`
77
90
 
78
- **Pricing table**
79
- `pricing{Plan>Price>Description>/path:CTA | Plan>Price>Desc>/path:CTA | Plan>Price>Desc>/path:CTA}`
80
- Middle plan auto-gets "Most popular" badge.
91
+ **form with redirect** — `form POST /api/auth/login => redirect /dashboard { Email:email | Password:password }`
81
92
 
82
- **FAQ accordion**
83
- `faq{Question > Answer | Question > Answer | Question > Answer}`
93
+ **pricing** — `pricing{Starter>Free>3 projects>/signup:Get started|Pro>$29/mo>Unlimited>/signup:Start trial|Enterprise>Custom>SSO>/contact:Talk}`
84
94
 
85
- **Testimonial**
86
- `testimonial{Full Name, Title @ Company|Quote text without quotes|img:https://avatar-url}`
95
+ **faq** — `faq{How to start?>Sign up free.|Cancel anytime?>Yes, one click.}`
87
96
 
88
- **Image gallery**
89
- `gallery{https://img1 | https://img2 | https://img3}`
97
+ **testimonial** — `testimonial{Alice Chen, CEO @ Acme|"Changed how we ship."|img:https://i.pravatar.cc/64?img=5}`
90
98
 
91
- **Action button**
92
- `btn{Label > METHOD /api/path > confirm:Confirmation message}`
93
- `btn{Export > GET /api/export}`
94
- `btn{Delete all > DELETE /api/items > confirm:Delete all items?}`
99
+ **gallery** — `gallery{https://img1.jpg | https://img2.jpg | https://img3.jpg}`
95
100
 
96
- **Reactive dropdown**
97
- `select @filterVar { All | Active | Inactive | Pending }`
101
+ **btn** — `btn{Export CSV > GET /api/export}` or `btn{Delete all > DELETE /api/items > confirm:Are you sure?}`
98
102
 
99
- **Raw HTML**
100
- `raw{<div style="...">Any HTML, custom components, embeds, iframes</div>}`
103
+ **select** — `select @filterVar { All | Active | Inactive }`
101
104
 
102
- **Conditional**
103
- `if @var { sect{Only shown when @var is truthy} }`
105
+ **raw** — `raw{<div style="...">Any HTML, embeds, custom components</div>}`
104
106
 
105
- **Footer**
106
- `foot{© 2025 AppName>/path:Link>/path:Link}`
107
+ **if** — `if @user { sect{Welcome back!} }`
107
108
 
108
- ### Block modifiers (suffix, any block)
109
- `block{...} animate:animation-name`
110
- `block{...} class:css-class-name`
111
- `block{...} animate:stagger class:my-section`
109
+ **foot** `foot{© 2025 AppName>/privacy:Privacy>/terms:Terms}`
112
110
 
111
+ ### Block modifiers (suffix on any block)
112
+ ```
113
+ hero{...} animate:blur-in
114
+ row3{...} animate:stagger class:my-section
115
+ sect{...} animate:fade-up
116
+ ```
113
117
  Animations: `fade-up` `fade-in` `blur-in` `slide-left` `slide-right` `zoom-in` `stagger`
114
118
 
119
+ ### Multiple pages
120
+ ```
121
+ %home dark /
122
+ nav{...}
123
+ hero{...}
124
+ ---
125
+ %dashboard dark /dashboard
126
+ @users = []
127
+ ~mount GET /api/users => @users
128
+ table @users { ... }
129
+ ---
130
+ %login dark /login
131
+ form POST /api/auth/login => redirect /dashboard { ... }
132
+ ```
133
+
115
134
  ---
116
135
 
117
136
  ## Complete examples
118
137
 
119
- ### SaaS landing + dashboard + auth (3 pages)
120
- ```flux
138
+ ### SaaS with 4 pages
139
+ ```
121
140
  ~theme accent=#2563eb
141
+ ~db sqlite ./app.db
142
+ ~auth jwt $JWT_SECRET expire=7d
143
+ ~admin /admin
144
+
145
+ model User {
146
+ id : uuid : pk auto
147
+ name : text : required
148
+ email : text : required unique
149
+ password : text : required hashed
150
+ plan : enum : starter,pro,enterprise : default=starter
151
+ role : enum : user,admin : default=user
152
+ ~soft-delete
153
+ }
154
+
155
+ api POST /api/auth/register {
156
+ ~validate name required | email required email | password min=8
157
+ ~unique User email $body.email | 409
158
+ ~hash password
159
+ insert User($body)
160
+ return jwt($inserted) 201
161
+ }
162
+
163
+ api POST /api/auth/login {
164
+ $user = User.findBy(email=$body.email)
165
+ ~check password $body.password $user.password | 401
166
+ return jwt($user) 200
167
+ }
168
+
169
+ api GET /api/users {
170
+ ~guard admin
171
+ return User.paginate(1, 20)
172
+ }
173
+
174
+ api GET /api/stats {
175
+ return User.count()
176
+ }
122
177
 
123
178
  %home dark /
124
179
 
125
180
  @stats = {}
126
181
  ~mount GET /api/stats => @stats
127
182
 
128
- nav{AppName>/features:Features>/pricing:Pricing>/login:Sign in>/signup:Get started}
129
- hero{Ship faster with AI|Zero config. Deploy in seconds. Scale to millions.>/signup:Start free — no credit card>/demo:View live demo} animate:blur-in
130
- stats{@stats.users:Customers|@stats.mrr:Monthly Revenue|@stats.uptime:Uptime}
131
- row3{rocket>Deploy instantly>Push to git, live in 3 seconds. No DevOps required.|shield>Enterprise security>SOC2, GDPR, SSO, RBAC. All built-in out of the box.|chart>Full observability>Real-time errors, performance, and usage analytics.} animate:stagger
132
- testimonial{Sarah Chen, CEO @ Acme Corp|"Cut our deployment time by 90%. The team ships 3x faster now."|img:https://i.pravatar.cc/64?img=47} animate:fade-up
133
- pricing{Starter>Free>3 projects, 1GB storage, community support>/signup:Get started|Pro>$29/mo>Unlimited projects, priority support, analytics>/signup:Start 14-day trial|Enterprise>Custom>SSO, SLA, dedicated CSM, on-prem option>/contact:Talk to sales}
134
- faq{How do I get started?>Sign up free no credit card required. Your first app is live in under 5 minutes.|Can I cancel anytime?>Yes. Cancel with one click, no questions asked, no penalties.|Do you offer refunds?>Full refund within 14 days, no questions asked.}
135
- foot{© 2025 AppName>/privacy:Privacy Policy>/terms:Terms of Service>/status:Status}
183
+ nav{MySaaS>/pricing:Pricing>/login:Sign in>/signup:Get started}
184
+ hero{Ship faster with AI|Zero config. Deploy in seconds.>/signup:Start free>/demo:View demo} animate:blur-in
185
+ stats{@stats:Users|99.9%:Uptime|$49:Starting price}
186
+ row3{rocket>Deploy instantly>Push to git, live in seconds.|shield>Enterprise ready>SOC2, GDPR, SSO built-in.|chart>Full observability>Real-time errors and performance.} animate:stagger
187
+ testimonial{Sarah Chen, CEO @ Acme|"Cut deployment time by 90%."|img:https://i.pravatar.cc/64?img=47} animate:fade-up
188
+ pricing{Starter>Free>3 projects>/signup:Get started|Pro>$29/mo>Unlimited>/signup:Start trial|Enterprise>Custom>SSO>/contact:Talk}
189
+ faq{How to start?>Sign up free, no credit card.|Cancel anytime?>Yes, one click, no questions.}
190
+ foot{© 2025 MySaaS>/privacy:Privacy>/terms:Terms}
136
191
 
137
192
  ---
138
193
 
139
194
  %dashboard dark /dashboard
140
195
 
141
- @user = {}
142
196
  @users = []
143
197
  @stats = {}
144
- ~mount GET /api/me => @user
145
198
  ~mount GET /api/users => @users
146
199
  ~mount GET /api/stats => @stats
147
200
  ~interval 30000 GET /api/stats => @stats
148
201
 
149
- nav{AppName>/settings:Settings>/logout:Sign out}
150
- stats{@stats.total:Total users|@stats.active:Active today|@stats.mrr:MRR|@stats.churn:Churn rate}
202
+ nav{MySaaS>/settings:Settings>/logout:Sign out}
203
+ stats{@stats:Total users|@stats:Active|$0:MRR}
151
204
  sect{User database}
152
- table @users { Name:name | Email:email | Plan:plan | Status:status | Created:created_at | edit PUT /api/users/{id} | delete /api/users/{id} | empty: No users yet. Invite your first user. }
153
- sect{Add user manually}
154
- form POST /api/users => @users.push($result) { Full name:text:Alice Johnson | Email:email:alice@company.com | Plan:select:starter,pro,enterprise }
155
- foot{AppName Dashboard © 2025}
205
+ table @users { Name:name | Email:email | Plan:plan | Status:status | edit PUT /api/users/{id} | delete /api/users/{id} | empty: No users yet. }
206
+ sect{Add user}
207
+ form POST /api/users => @users.push($result) { Full name:text:Alice Johnson | Email:email:alice@co.com | Plan:select:starter,pro,enterprise }
208
+ foot{MySaaS Dashboard © 2025}
156
209
 
157
210
  ---
158
211
 
159
212
  %login dark /login
160
213
 
161
- nav{AppName>/signup:Create account}
162
- hero{Welcome back|Sign in to your account.}
214
+ nav{MySaaS>/signup:Create account}
215
+ hero{Welcome back|Sign in to continue.}
163
216
  form POST /api/auth/login => redirect /dashboard { Email:email:you@company.com | Password:password: }
164
- foot{© 2025 AppName>/signup:Create account>/privacy:Privacy}
217
+ foot{© 2025 MySaaS>/signup:Create account}
165
218
 
166
219
  ---
167
220
 
168
221
  %signup dark /signup
169
222
 
170
- nav{AppName>/login:Sign in}
171
- hero{Start for free|No credit card required. Set up in 2 minutes.}
172
- form POST /api/auth/register => redirect /dashboard { Full name:text:Alice Johnson | Work email:email:alice@company.com | Password:password: }
173
- foot{© 2025 AppName>/login:Already have an account?}
223
+ nav{MySaaS>/login:Sign in}
224
+ hero{Start for free|No credit card required.}
225
+ form POST /api/auth/register => redirect /dashboard { Full name:text:Alice | Email:email:alice@co.com | Password:password: }
226
+ foot{© 2025 MySaaS>/login:Already have an account?}
174
227
  ```
175
228
 
176
- ### CRUD with custom theme
177
- ```flux
178
- ~theme accent=#10b981 radius=.75rem font=Inter surface=#0d1f1a
179
-
180
- %products dark /products
181
-
182
- @products = []
183
- @search = ""
184
- ~mount GET /api/products => @products
185
-
186
- nav{MyStore>/products:Products>/orders:Orders>/settings:Settings}
187
- sect{Product Catalog}
188
- table @products { Name:name | SKU:sku | Price:price | Stock:stock | Status:status | edit PUT /api/products/{id} | delete /api/products/{id} | empty: No products. Add your first product below. }
189
- sect{Add Product}
190
- form POST /api/products => @products.push($result) { Product name:text:iPhone Case | SKU:text:CASE-001 | Price:number:29.99 | Stock:number:100 | Category:select:electronics,clothing,food,other }
191
- foot{© 2025 MyStore}
229
+ ### Landing page with custom theme
192
230
  ```
193
-
194
- ### Simple landing with image hero
195
- ```flux
196
231
  ~theme accent=#f59e0b radius=2rem font=Syne bg=#0c0a09 text=#fafaf9 surface=#1c1917
197
232
 
198
233
  %home dark /
199
234
 
200
- nav{Acme>/about:About>/blog:Blog>/contact:Contact}
201
- hero{We build things that matter|A creative studio based in São Paulo. We design, develop, and ship.>/work:View our work>/contact:Get in touch|img:https://images.unsplash.com/photo-1497366216548-37526070297c?w=800&q=80} animate:fade-in
202
- row3{globe>Global clients>We've worked with teams in 30+ countries.|star>Award winning>12 design awards in the last 3 years.|check>On-time delivery>98% of projects delivered on schedule.} animate:stagger
203
- testimonial{Marco Silva, CTO @ Fintech BR|"Acme transformed our product. Went from prototype to production in 6 weeks."|img:https://i.pravatar.cc/64?img=12}
204
- gallery{https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=400|https://images.unsplash.com/photo-1522202176988-66273c2fd55f?w=400|https://images.unsplash.com/photo-1497366412874-3415097a27e7?w=400}
205
- foot{© 2025 Acme Studio>/privacy:Privacy>/instagram:Instagram>/linkedin:LinkedIn}
235
+ nav{Acme Studio>/work:Work>/blog:Blog>/contact:Contact}
236
+ hero{We build things that matter|Creative studio based in São Paulo.>/work:View our work>/contact:Get in touch|img:https://images.unsplash.com/photo-1497366216548?w=800} animate:fade-in
237
+ row3{globe>Global clients>Teams in 30+ countries.|star>Award winning>12 design awards.|check>On-time delivery>98% on schedule.} animate:stagger
238
+ testimonial{Marco Silva, CTO @ FinTech BR|"From prototype to production in 6 weeks."|img:https://i.pravatar.cc/64?img=12}
239
+ gallery{https://images.unsplash.com/photo-1600880292203?w=400|https://images.unsplash.com/photo-1522202176988?w=400|https://images.unsplash.com/photo-1497366412874?w=400}
240
+ foot{© 2025 Acme Studio>/privacy:Privacy>/instagram:Instagram}
206
241
  ```
207
242
 
208
243
  ---
@@ -214,21 +249,29 @@ foot{© 2025 Acme Studio>/privacy:Privacy>/instagram:Instagram>/linkedin:LinkedI
214
249
  3. For dynamic data, always declare `@var = []` or `@var = {}` and use `~mount`
215
250
  4. Tables with data should always have `edit` and `delete` unless readonly
216
251
  5. Forms should have `=> @list.push($result)` or `=> redirect /path`
217
- 6. Use real icon names from the list, not emoji
252
+ 6. Use real icon names: bolt rocket shield chart star check globe gear fire money bell mail user
218
253
  7. Multiple pages separated by `---`
219
- 8. Add `animate:fade-up` or `animate:stagger` to key sections for polish
254
+ 8. Add `animate:fade-up` or `animate:stagger` to key sections
220
255
  9. `~theme` always comes before `%` declarations
221
- 10. Never generate explanations — only FLUX code
256
+ 10. Never generate explanations — only aiplang code
257
+ 11. For full-stack apps, add `~db`, `~auth`, `model` and `api` blocks before pages
222
258
 
223
259
  ---
224
260
 
225
- ## Running the generated code
261
+ ## Running
226
262
 
227
263
  ```bash
228
- # Install once
264
+ # Install
229
265
  npm install -g aiplang
230
266
 
231
- # Save Claude's output as pages/app.flux, then:
232
- aiplang serve # dev server http://localhost:3000
267
+ # Frontend only (static site)
268
+ aiplang serve # dev → localhost:3000
233
269
  aiplang build pages/ # compile → dist/
270
+
271
+ # Full-stack (Node.js backend)
272
+ aiplang start app.flux
273
+
274
+ # Go binary (production, v2)
275
+ aiplangd dev app.flux
276
+ aiplangd build app.flux
234
277
  ```
package/bin/aiplang.js CHANGED
@@ -5,7 +5,7 @@ const fs = require('fs')
5
5
  const path = require('path')
6
6
  const http = require('http')
7
7
 
8
- const VERSION = '2.0.1'
8
+ const VERSION = '2.1.1'
9
9
  const RUNTIME_DIR = path.join(__dirname, '..', 'runtime')
10
10
  const cmd = process.argv[2]
11
11
  const args = process.argv.slice(3)
@@ -53,6 +53,7 @@ if (!cmd||cmd==='--help'||cmd==='-h') {
53
53
 
54
54
  GitHub: https://github.com/isacamartin/aiplang
55
55
  npm: https://npmjs.com/package/aiplang
56
+ Docs: https://isacamartin.github.io/aiplang
56
57
  `)
57
58
  process.exit(0)
58
59
  }
@@ -213,7 +214,7 @@ if (cmd === 'start' || cmd === 'run') {
213
214
  process.exit(1)
214
215
  }
215
216
  const port = parseInt(process.env.PORT || args[1] || '3000')
216
- const serverPath = path.join(__dirname, '..', '..', 'aiplang-server', 'server.js')
217
+ const serverPath = path.join(__dirname, '..', 'server', 'server.js')
217
218
  if (!fs.existsSync(serverPath)) {
218
219
  console.error(`\n ✗ Full-stack server not found.`)
219
220
  console.error(` Install: npm install -g aiplang-server\n`)
@@ -400,7 +401,7 @@ function renderPage(page, allPages) {
400
401
  const needsJS=page.queries.length>0||page.blocks.some(b=>['table','list','form','if','btn','select','faq'].includes(b.kind))
401
402
  const body=page.blocks.map(b=>applyMods(renderBlock(b,page),b)).join('')
402
403
  const config=needsJS?JSON.stringify({id:page.id,theme:page.theme,routes:allPages.map(p=>p.route),state:page.state,queries:page.queries}):''
403
- const hydrate=needsJS?`\n<script>window.__FLUX_PAGE__=${config};</script>\n<script src="./aiplang-hydrate.js" defer></script>`:''
404
+ const hydrate=needsJS?`\n<script>window.__AIPLANG_PAGE__=${config};</script>\n<script src="./aiplang-hydrate.js" defer></script>`:''
404
405
  const customVars=page.customTheme?genCustomThemeVars(page.customTheme):''
405
406
  const themeVarCSS=page.themeVars?genThemeVarCSS(page.themeVars):''
406
407
  return `<!DOCTYPE html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiplang",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "AI-first full-stack language. Frontend + Backend + DB + Auth in one file. Competes with Laravel.",
5
5
  "keywords": [
6
6
  "aiplang",
@@ -40,6 +40,7 @@
40
40
  "dependencies": {
41
41
  "bcryptjs": "^2.4.3",
42
42
  "jsonwebtoken": "^9.0.2",
43
- "sql.js": "^1.10.3"
43
+ "sql.js": "^1.10.3",
44
+ "nodemailer": "^6.9.0"
44
45
  }
45
46
  }
@@ -6,7 +6,7 @@
6
6
  (function () {
7
7
  'use strict'
8
8
 
9
- const cfg = window.__FLUX_PAGE__
9
+ const cfg = window.__AIPLANG_PAGE__
10
10
  if (!cfg) return
11
11
 
12
12
  // ── State ────────────────────────────────────────────────────────
@@ -619,6 +619,15 @@
619
619
  "node": ">= 0.6"
620
620
  }
621
621
  },
622
+ "node_modules/nodemailer": {
623
+ "version": "8.0.3",
624
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-8.0.3.tgz",
625
+ "integrity": "sha512-JQNBqvK+bj3NMhUFR3wmCl3SYcOeMotDiwDBvIoCuQdF0PvlIY0BH+FJ2CG7u4cXKPChplE78oowlH/Otsc4ZQ==",
626
+ "license": "MIT-0",
627
+ "engines": {
628
+ "node": ">=6.0.0"
629
+ }
630
+ },
622
631
  "node_modules/object-inspect": {
623
632
  "version": "1.13.4",
624
633
  "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
@@ -0,0 +1,6 @@
1
+ *.js text eol=lf
2
+ *.txt text eol=lf
3
+ *.html text eol=lf
4
+ *.htm text eol=lf
5
+ *.ics -text
6
+ *.bin -text
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ upgrade: true,
5
+ reject: [
6
+ // API changes break existing tests
7
+ 'proxy'
8
+ ]
9
+ };
@@ -0,0 +1,8 @@
1
+ node_modules
2
+ coverage
3
+ *.min.js
4
+ dist
5
+ build
6
+ .nyc_output
7
+ package-lock.json
8
+ CHANGELOG.md
@@ -0,0 +1,12 @@
1
+ {
2
+ "printWidth": 140,
3
+ "tabWidth": 4,
4
+ "useTabs": false,
5
+ "semi": true,
6
+ "singleQuote": true,
7
+ "quoteProps": "as-needed",
8
+ "trailingComma": "none",
9
+ "bracketSpacing": true,
10
+ "arrowParens": "avoid",
11
+ "endOfLine": "lf"
12
+ }
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ printWidth: 160,
5
+ tabWidth: 4,
6
+ singleQuote: true,
7
+ endOfLine: 'lf',
8
+ trailingComma: 'none',
9
+ arrowParens: 'avoid'
10
+ };
@@ -0,0 +1,9 @@
1
+ {
2
+ "packages": {
3
+ ".": {
4
+ "release-type": "node",
5
+ "package-name": "nodemailer",
6
+ "pull-request-title-pattern": "chore${scope}: release ${version} [skip-ci]"
7
+ }
8
+ }
9
+ }