@icarusmx/creta 1.5.4 → 1.5.7

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 (37) hide show
  1. package/bin/creta.js +44 -3
  2. package/lib/aws-guide-viewer.js +179 -0
  3. package/lib/builders/MenuBuilder.js +23 -4
  4. package/lib/executors/ExercisesExecutor.js +8 -0
  5. package/lib/exercises/array-object-manipulation.md +1281 -0
  6. package/lib/exercises/aws-billing-detective.md +588 -0
  7. package/lib/exercises/git-stash-workflow.md +426 -0
  8. package/lib/exercises/iterm2-pane-navigation.md +504 -0
  9. package/lib/exercises/railway-deployment.md +1185 -0
  10. package/lib/papers/bitcoin/bitcoin.md +92 -0
  11. package/lib/papers/mapreduce/mapreduce.md +476 -0
  12. package/lib/papers/spark/spark.md +49 -0
  13. package/lib/vim-setup-tutorial.js +367 -0
  14. package/package.json +5 -1
  15. package/ascii-logo.txt +0 -8
  16. package/codex-refactor.txt +0 -13
  17. package/docs/diagrams/README.md +0 -131
  18. package/docs/diagrams/architecture-overview.mmd +0 -71
  19. package/docs/diagrams/architecture.svg +0 -1
  20. package/docs/diagrams/ecosystem-integration.mmd +0 -49
  21. package/docs/diagrams/evolution-phases.mmd +0 -49
  22. package/docs/diagrams/output.svg +0 -1
  23. package/docs/diagrams/phase2-command-help-flow.mmd +0 -51
  24. package/docs/diagrams/user-journey.mmd +0 -78
  25. package/ejemplo.sh +0 -3
  26. package/refactor.txt +0 -581
  27. package/templates/sveltekit-portfolio/package.json +0 -20
  28. package/templates/sveltekit-portfolio/src/app.css +0 -51
  29. package/templates/sveltekit-portfolio/src/app.html +0 -12
  30. package/templates/sveltekit-portfolio/src/routes/+layout.svelte +0 -108
  31. package/templates/sveltekit-portfolio/src/routes/+page.svelte +0 -79
  32. package/templates/sveltekit-portfolio/static/favicon.png +0 -0
  33. package/templates/sveltekit-portfolio/svelte.config.js +0 -10
  34. package/templates/sveltekit-portfolio/vite.config.js +0 -10
  35. package/test/enunciados.test.js +0 -72
  36. package/test/sintaxis-menu.test.js +0 -45
  37. package/wea-fome-qlia.sh +0 -92
@@ -0,0 +1,1185 @@
1
+ # Railway Deployment Guide - Node.js Apps
2
+
3
+ <!-- vim: set foldmethod=marker foldlevel=0: -->
4
+
5
+ ## 📖 LazyVim Reading Guide {{{
6
+
7
+ **Start with:** `zM` (close all folds) → Navigate with `za` (toggle fold under cursor)
8
+
9
+ This document uses fold markers `{{{` and `}}}` for organized reading.
10
+
11
+ **Navigation Tips:**
12
+ - `zM` - Close all folds (see just section headers)
13
+ - `zR` - Open all folds (see everything)
14
+ - `za` - Toggle current fold
15
+ - `zj` - Jump to next fold
16
+ - `zk` - Jump to previous fold
17
+
18
+ }}}
19
+
20
+ ## 🎯 What You'll Learn {{{
21
+
22
+ This guide covers the complete Railway deployment workflow for Node.js applications:
23
+
24
+ 1. **Initial Setup** - Install CLI, authenticate, initialize project
25
+ 2. **Deploy Node.js/Express** - From local dev to production deployment
26
+ 3. **Environment Variables** - Manage secrets and configuration
27
+ 4. **Custom Domains** - Set up domains, DNS, and SSL certificates
28
+
29
+ **Prerequisites:**
30
+ - Node.js and npm installed
31
+ - Git knowledge (basic commands)
32
+ - A Node.js/Express app to deploy (or use example provided)
33
+ - Railway account (free tier available at railway.app)
34
+
35
+ **Time to complete:** 30-45 minutes
36
+
37
+ }}}
38
+
39
+ ## 🚂 Part 1: Initial Setup {{{
40
+
41
+ ### Install Railway CLI {{{
42
+
43
+ **macOS/Linux:**
44
+ ```bash
45
+ # Using Homebrew (recommended for macOS)
46
+ brew install railway
47
+
48
+ # Or using npm (cross-platform)
49
+ npm install -g @railway/cli
50
+
51
+ # Verify installation
52
+ railway --version
53
+ ```
54
+
55
+ **Expected output:**
56
+ ```
57
+ railway version 3.5.0
58
+ ```
59
+
60
+ **Windows:**
61
+ ```bash
62
+ # Using npm
63
+ npm install -g @railway/cli
64
+
65
+ # Or using Scoop
66
+ scoop install railway
67
+ ```
68
+
69
+ **LazyVim Tip:** Open a floating terminal to run commands while reading:
70
+ - `<leader>ft` - Open floating terminal
71
+ - `<C-\><C-n>` - Exit terminal insert mode (go to Normal mode)
72
+ - `<C-w>w` - Cycle between terminal and guide
73
+ - `i` - Back to terminal insert mode (type commands)
74
+
75
+ }}}
76
+
77
+ ### Login and Authentication {{{
78
+
79
+ **Step 1: Login via browser**
80
+ ```bash
81
+ railway login
82
+ ```
83
+
84
+ **What happens:**
85
+ 1. Opens browser to Railway login page
86
+ 2. Authenticate with GitHub/Google/Email
87
+ 3. CLI receives access token
88
+ 4. Token stored in `~/.railway/config.json`
89
+
90
+ **Expected output:**
91
+ ```
92
+ 🚝 Logging in...
93
+ ✓ Logged in as your-email@example.com
94
+ ```
95
+
96
+ **Verify authentication:**
97
+ ```bash
98
+ railway whoami
99
+ ```
100
+
101
+ **Output:**
102
+ ```
103
+ Logged in as: Your Name (your-email@example.com)
104
+ ```
105
+
106
+ **Troubleshooting:**
107
+ - If browser doesn't open: `railway login --browserless`
108
+ - Manual token: Get from railway.app/account/tokens
109
+
110
+ }}}
111
+
112
+ ### Initialize Project {{{
113
+
114
+ **Two ways to start:**
115
+
116
+ #### Option 1: Link Existing Railway Project
117
+ ```bash
118
+ # If you already created a project on Railway dashboard
119
+ cd your-app-directory
120
+ railway link
121
+ ```
122
+
123
+ **Interactive prompt:**
124
+ ```
125
+ Select a project:
126
+ > my-express-api
127
+ my-portfolio-site
128
+ test-project
129
+ ```
130
+
131
+ #### Option 2: Create New Project from CLI
132
+ ```bash
133
+ cd your-app-directory
134
+ railway init
135
+ ```
136
+
137
+ **Prompts you'll see:**
138
+ ```
139
+ Enter project name: my-express-api
140
+ Select environment: production
141
+ ✓ Project created: my-express-api
142
+ ```
143
+
144
+ **Verify project setup:**
145
+ ```bash
146
+ railway status
147
+ ```
148
+
149
+ **Output:**
150
+ ```
151
+ Project: my-express-api
152
+ Environment: production
153
+ Service: Not deployed yet
154
+ ```
155
+
156
+ **LazyVim Workflow:**
157
+ - Use `<leader>/` to search "railway init" in this file
158
+ - Press `n` to jump to next occurrence
159
+ - Press `N` to go back
160
+
161
+ }}}
162
+
163
+ ### Understanding Railway Project Structure {{{
164
+
165
+ **After initialization, Railway creates:**
166
+ ```
167
+ your-app/
168
+ ├── .railway/ # Railway metadata (gitignored)
169
+ │ └── config.json # Project/service mapping
170
+ ├── railway.json # Deployment configuration (optional)
171
+ ├── railway.toml # Alternative config format (optional)
172
+ └── your app files...
173
+ ```
174
+
175
+ **Important:**
176
+ - `.railway/` is automatically added to `.gitignore`
177
+ - `railway.json` defines build/deploy settings (we'll create this next)
178
+
179
+ }}}
180
+
181
+ }}}
182
+
183
+ ## 🚀 Part 2: Deploy Node.js/Express Apps {{{
184
+
185
+ ### Prepare Your Express App {{{
186
+
187
+ **Example Express App Structure:**
188
+ ```
189
+ my-express-api/
190
+ ├── package.json
191
+ ├── index.js # or server.js
192
+ ├── .env # Local env vars (gitignored)
193
+ ├── .gitignore
194
+ └── README.md
195
+ ```
196
+
197
+ **Minimal Express App (index.js):**
198
+ ```javascript
199
+ import express from 'express'
200
+
201
+ const app = express()
202
+ const PORT = process.env.PORT || 3000
203
+
204
+ app.get('/', (req, res) => {
205
+ res.json({ message: 'Hello from Railway!' })
206
+ })
207
+
208
+ app.get('/health', (req, res) => {
209
+ res.json({ status: 'ok', timestamp: new Date() })
210
+ })
211
+
212
+ app.listen(PORT, () => {
213
+ console.log(`Server running on port ${PORT}`)
214
+ })
215
+ ```
216
+
217
+ **package.json Requirements:**
218
+ ```json
219
+ {
220
+ "name": "my-express-api",
221
+ "type": "module",
222
+ "scripts": {
223
+ "start": "node index.js",
224
+ "dev": "node --watch index.js"
225
+ },
226
+ "dependencies": {
227
+ "express": "^4.18.2"
228
+ },
229
+ "engines": {
230
+ "node": ">=18.0.0"
231
+ }
232
+ }
233
+ ```
234
+
235
+ **Critical: Specify `start` script!** Railway runs `npm start` by default.
236
+
237
+ **LazyVim Tip:** Use `gf` (go to file) on `"./index.js"` to quickly navigate to that file.
238
+
239
+ }}}
240
+
241
+ ### Create railway.json Config {{{
242
+
243
+ **Purpose:** Define build and deployment behavior explicitly.
244
+
245
+ **Create `railway.json` in project root:**
246
+ ```json
247
+ {
248
+ "$schema": "https://railway.app/railway.schema.json",
249
+ "build": {
250
+ "builder": "NIXPACKS",
251
+ "buildCommand": "npm install"
252
+ },
253
+ "deploy": {
254
+ "startCommand": "npm start",
255
+ "restartPolicyType": "ON_FAILURE",
256
+ "restartPolicyMaxRetries": 3
257
+ }
258
+ }
259
+ ```
260
+
261
+ **Configuration explained:**
262
+
263
+ | Field | Purpose | Options |
264
+ |-------|---------|---------|
265
+ | `builder` | Build system | `NIXPACKS` (auto-detect), `DOCKERFILE` (use Dockerfile) |
266
+ | `buildCommand` | Install dependencies | `npm install`, `npm ci`, `pnpm install` |
267
+ | `startCommand` | Run the app | `npm start`, `node index.js` |
268
+ | `restartPolicyType` | When to restart | `ON_FAILURE`, `ALWAYS`, `NEVER` |
269
+
270
+ **Advanced: Multiple environments:**
271
+ ```json
272
+ {
273
+ "environments": {
274
+ "production": {
275
+ "deploy": {
276
+ "startCommand": "npm start"
277
+ }
278
+ },
279
+ "staging": {
280
+ "deploy": {
281
+ "startCommand": "npm run start:staging"
282
+ }
283
+ }
284
+ }
285
+ }
286
+ ```
287
+
288
+ **LazyVim Editing:**
289
+ - `ci{` - Change inside braces (replace JSON value)
290
+ - `va{` - Select entire object (visual select around braces)
291
+
292
+ }}}
293
+
294
+ ### Deploy with railway up {{{
295
+
296
+ **The magic command:**
297
+ ```bash
298
+ railway up
299
+ ```
300
+
301
+ **What happens (step by step):**
302
+ ```
303
+ 1. 📦 Creating deployment...
304
+ 2. 🔨 Building application...
305
+ - Detecting build system: Nixpacks
306
+ - Installing dependencies: npm install
307
+ - Running build command (if specified)
308
+ 3. 🚀 Deploying...
309
+ - Creating container
310
+ - Starting service
311
+ - Assigning public URL
312
+ 4. ✓ Deployment successful!
313
+ - URL: https://my-express-api-production.up.railway.app
314
+ ```
315
+
316
+ **Expected output:**
317
+ ```
318
+ ⚡ Deploying...
319
+ ✓ Build successful
320
+ ✓ Deployment live at https://my-express-api-production.up.railway.app
321
+
322
+ Deployment ID: d3pl0ym3nt-1234
323
+ Service: my-express-api
324
+ Environment: production
325
+ ```
326
+
327
+ **Verify deployment:**
328
+ ```bash
329
+ # Open in browser
330
+ railway open
331
+
332
+ # Or curl the health endpoint
333
+ curl https://your-app.up.railway.app/health
334
+ ```
335
+
336
+ **First-time deployment:**
337
+ - Usually takes 2-5 minutes
338
+ - Subsequent deploys are faster (cached layers)
339
+
340
+ }}}
341
+
342
+ ### Monitor Logs and Debugging {{{
343
+
344
+ **View live logs:**
345
+ ```bash
346
+ railway logs
347
+ ```
348
+
349
+ **Output (real-time stream):**
350
+ ```
351
+ [2025-01-15 10:30:45] Server running on port 3000
352
+ [2025-01-15 10:30:50] GET /health 200 15ms
353
+ [2025-01-15 10:31:00] GET / 200 8ms
354
+ ```
355
+
356
+ **Follow logs (like tail -f):**
357
+ ```bash
358
+ railway logs --follow
359
+ ```
360
+
361
+ **Filter logs by service:**
362
+ ```bash
363
+ railway logs --service my-express-api
364
+ ```
365
+
366
+ **Common deployment errors:**
367
+
368
+ #### Error 1: Build Failed
369
+ ```
370
+ Error: Cannot find module 'express'
371
+ ```
372
+ **Fix:** Add `express` to `package.json` dependencies
373
+
374
+ #### Error 2: Port Binding
375
+ ```
376
+ Error: listen EADDRINUSE: address already in use :::3000
377
+ ```
378
+ **Fix:** Use `process.env.PORT` (Railway assigns dynamic port)
379
+
380
+ ```javascript
381
+ // ❌ Wrong
382
+ const PORT = 3000
383
+
384
+ // ✅ Correct
385
+ const PORT = process.env.PORT || 3000
386
+ ```
387
+
388
+ #### Error 3: Start Command Failed
389
+ ```
390
+ Error: Missing script: "start"
391
+ ```
392
+ **Fix:** Add to `package.json`:
393
+ ```json
394
+ "scripts": {
395
+ "start": "node index.js"
396
+ }
397
+ ```
398
+
399
+ **LazyVim Debugging Workflow:**
400
+ 1. `<leader>ft` - Open floating terminal
401
+ 2. `railway logs` - Watch errors in real-time
402
+ 3. `<C-\><C-n>` - Exit terminal insert mode
403
+ 4. `<C-w>w` - Switch back to code
404
+ 5. Fix issue
405
+ 6. `<C-w>w` - Back to terminal, then `i` to type
406
+ 7. `git commit && railway up`
407
+
408
+ }}}
409
+
410
+ ### Redeploy After Changes {{{
411
+
412
+ **Automatic deploys (recommended):**
413
+ ```bash
414
+ # Connect GitHub repo to Railway
415
+ railway link
416
+
417
+ # Enable auto-deploys on Railway dashboard
418
+ # Now every git push triggers deployment
419
+ ```
420
+
421
+ **Manual redeploy:**
422
+ ```bash
423
+ # Make changes to your code
424
+ git add .
425
+ git commit -m "fix: correct port binding"
426
+
427
+ # Deploy to Railway
428
+ railway up
429
+ ```
430
+
431
+ **Rollback to previous deployment:**
432
+ ```bash
433
+ railway rollback
434
+ ```
435
+
436
+ **View deployment history:**
437
+ ```bash
438
+ railway deployments
439
+ ```
440
+
441
+ **Output:**
442
+ ```
443
+ ID Status Created Duration
444
+ d3pl0y-5 ACTIVE 2 hours ago 1m 30s
445
+ d3pl0y-4 SUCCESS 5 hours ago 1m 45s
446
+ d3pl0y-3 FAILED 1 day ago 0m 20s
447
+ ```
448
+
449
+ }}}
450
+
451
+ }}}
452
+
453
+ ## 🔐 Part 3: Environment Variables & Secrets {{{
454
+
455
+ ### Setting Variables via CLI {{{
456
+
457
+ **Add single variable:**
458
+ ```bash
459
+ railway variables set DATABASE_URL="postgresql://user:pass@host:5432/db"
460
+ ```
461
+
462
+ **Add multiple variables:**
463
+ ```bash
464
+ railway variables set \
465
+ NODE_ENV=production \
466
+ API_KEY=sk_live_abc123 \
467
+ MAX_CONNECTIONS=100
468
+ ```
469
+
470
+ **List all variables:**
471
+ ```bash
472
+ railway variables
473
+ ```
474
+
475
+ **Output:**
476
+ ```
477
+ Name Value
478
+ DATABASE_URL postgresql://...
479
+ NODE_ENV production
480
+ API_KEY sk_live_*** (hidden for security)
481
+ MAX_CONNECTIONS 100
482
+ ```
483
+
484
+ **Delete variable:**
485
+ ```bash
486
+ railway variables delete API_KEY
487
+ ```
488
+
489
+ **Bulk import from .env file:**
490
+ ```bash
491
+ railway variables set --from-env-file .env.production
492
+ ```
493
+
494
+ }}}
495
+
496
+ ### Using .env Files Locally {{{
497
+
498
+ **Local development setup:**
499
+
500
+ **1. Create `.env` (local only, gitignored):**
501
+ ```bash
502
+ # .env
503
+ NODE_ENV=development
504
+ PORT=3000
505
+ DATABASE_URL=postgresql://localhost:5432/mydb_dev
506
+ API_KEY=sk_test_abc123
507
+ ```
508
+
509
+ **2. Add to `.gitignore`:**
510
+ ```bash
511
+ # .gitignore
512
+ .env
513
+ .env.*
514
+ !.env.example
515
+ ```
516
+
517
+ **3. Create `.env.example` (committed to repo):**
518
+ ```bash
519
+ # .env.example
520
+ NODE_ENV=development
521
+ PORT=3000
522
+ DATABASE_URL=postgresql://localhost:5432/dbname
523
+ API_KEY=your_api_key_here
524
+ ```
525
+
526
+ **4. Load variables in code:**
527
+ ```javascript
528
+ // index.js
529
+ import 'dotenv/config' // Load .env file
530
+
531
+ const config = {
532
+ nodeEnv: process.env.NODE_ENV,
533
+ port: process.env.PORT || 3000,
534
+ databaseUrl: process.env.DATABASE_URL,
535
+ apiKey: process.env.API_KEY
536
+ }
537
+
538
+ console.log('Config loaded:', config.nodeEnv)
539
+ ```
540
+
541
+ **Install dotenv:**
542
+ ```bash
543
+ npm install dotenv
544
+ ```
545
+
546
+ **Railway automatically loads env vars** - no dotenv needed in production!
547
+
548
+ }}}
549
+
550
+ ### Secrets Management Best Practices {{{
551
+
552
+ **1. Never commit secrets:**
553
+ ```bash
554
+ # ❌ Bad
555
+ git add .env
556
+ git commit -m "add environment variables"
557
+
558
+ # ✅ Good
559
+ # Add .env to .gitignore BEFORE committing
560
+ echo ".env" >> .gitignore
561
+ ```
562
+
563
+ **2. Use Railway's built-in variables:**
564
+
565
+ Railway provides these automatically:
566
+ ```bash
567
+ RAILWAY_ENVIRONMENT # production, staging, etc.
568
+ RAILWAY_PROJECT_ID # Unique project ID
569
+ RAILWAY_SERVICE_ID # Unique service ID
570
+ RAILWAY_DEPLOYMENT_ID # Current deployment ID
571
+ RAILWAY_PUBLIC_DOMAIN # Your app's URL
572
+ ```
573
+
574
+ **Access in code:**
575
+ ```javascript
576
+ if (process.env.RAILWAY_ENVIRONMENT === 'production') {
577
+ // Production-only logic
578
+ }
579
+ ```
580
+
581
+ **3. Separate secrets by environment:**
582
+ ```bash
583
+ # Production
584
+ railway variables set --environment production \
585
+ DATABASE_URL=postgresql://prod-host/db
586
+
587
+ # Staging
588
+ railway variables set --environment staging \
589
+ DATABASE_URL=postgresql://staging-host/db
590
+ ```
591
+
592
+ **4. Rotate secrets regularly:**
593
+ ```bash
594
+ # Generate new API key
595
+ NEW_KEY=$(openssl rand -hex 32)
596
+
597
+ # Update Railway
598
+ railway variables set API_KEY=$NEW_KEY
599
+
600
+ # Trigger redeploy
601
+ railway up
602
+ ```
603
+
604
+ **5. Validate required variables:**
605
+ ```javascript
606
+ // config.js
607
+ const requiredVars = [
608
+ 'DATABASE_URL',
609
+ 'API_KEY',
610
+ 'JWT_SECRET'
611
+ ]
612
+
613
+ for (const varName of requiredVars) {
614
+ if (!process.env[varName]) {
615
+ throw new Error(`Missing required env var: ${varName}`)
616
+ }
617
+ }
618
+ ```
619
+
620
+ **LazyVim Tip:**
621
+ - Search for env vars: `<leader>/` then type `process.env.`
622
+ - Jump between matches with `n` and `N`
623
+
624
+ }}}
625
+
626
+ ### Using Railway Plugins for Databases {{{
627
+
628
+ **Add PostgreSQL database:**
629
+ ```bash
630
+ railway add
631
+ ```
632
+
633
+ **Interactive prompt:**
634
+ ```
635
+ Select a plugin to add:
636
+ > PostgreSQL
637
+ MySQL
638
+ MongoDB
639
+ Redis
640
+ ```
641
+
642
+ **Railway automatically sets:**
643
+ ```bash
644
+ DATABASE_URL=postgresql://user:pass@host:5432/railway
645
+ PGHOST=containers-us-west-1.railway.app
646
+ PGPORT=5432
647
+ PGUSER=postgres
648
+ PGPASSWORD=generated_password
649
+ PGDATABASE=railway
650
+ ```
651
+
652
+ **Connect in your app:**
653
+ ```javascript
654
+ import pg from 'pg'
655
+ const { Pool } = pg
656
+
657
+ const pool = new Pool({
658
+ connectionString: process.env.DATABASE_URL,
659
+ ssl: { rejectUnauthorized: false } // Railway requires SSL
660
+ })
661
+
662
+ // Test connection
663
+ const client = await pool.connect()
664
+ console.log('Database connected!')
665
+ client.release()
666
+ ```
667
+
668
+ **Install pg driver:**
669
+ ```bash
670
+ npm install pg
671
+ ```
672
+
673
+ }}}
674
+
675
+ }}}
676
+
677
+ ## 🌐 Part 4: Custom Domains & Networking {{{
678
+
679
+ ### Add Custom Domain {{{
680
+
681
+ **Prerequisites:**
682
+ - Own a domain (from Namecheap, Google Domains, etc.)
683
+ - Access to DNS settings
684
+
685
+ **Add domain via CLI:**
686
+ ```bash
687
+ railway domain
688
+ ```
689
+
690
+ **Interactive prompt:**
691
+ ```
692
+ Enter custom domain: api.yourdomain.com
693
+ ✓ Domain added: api.yourdomain.com
694
+ ⚠️ DNS not configured yet - see instructions below
695
+ ```
696
+
697
+ **Or specify directly:**
698
+ ```bash
699
+ railway domain add api.yourdomain.com
700
+ ```
701
+
702
+ **View current domains:**
703
+ ```bash
704
+ railway domain list
705
+ ```
706
+
707
+ **Output:**
708
+ ```
709
+ Domain Status Service
710
+ my-app.up.railway.app Active my-express-api (auto)
711
+ api.yourdomain.com Pending my-express-api (custom)
712
+ ```
713
+
714
+ **Remove domain:**
715
+ ```bash
716
+ railway domain remove api.yourdomain.com
717
+ ```
718
+
719
+ }}}
720
+
721
+ ### Configure DNS Settings {{{
722
+
723
+ **Railway provides DNS instructions after adding domain.**
724
+
725
+ **Step 1: Get DNS records**
726
+ ```bash
727
+ railway domain --service my-express-api
728
+ ```
729
+
730
+ **Output:**
731
+ ```
732
+ Domain: api.yourdomain.com
733
+ Status: Pending DNS verification
734
+
735
+ Add these records to your DNS provider:
736
+ Type Name Value
737
+ CNAME api my-app.up.railway.app
738
+ ```
739
+
740
+ **Step 2: Add CNAME record at your DNS provider**
741
+
742
+ **Example: Cloudflare**
743
+ ```
744
+ Type: CNAME
745
+ Name: api
746
+ Target: my-app.up.railway.app
747
+ Proxy: OFF (or ON, both work)
748
+ TTL: Auto
749
+ ```
750
+
751
+ **Example: Namecheap**
752
+ ```
753
+ Type: CNAME Record
754
+ Host: api
755
+ Value: my-app.up.railway.app
756
+ TTL: Automatic
757
+ ```
758
+
759
+ **Step 3: Wait for DNS propagation**
760
+ ```bash
761
+ # Check DNS propagation
762
+ dig api.yourdomain.com
763
+
764
+ # Or use online tool
765
+ # https://dnschecker.org/#CNAME/api.yourdomain.com
766
+ ```
767
+
768
+ **Propagation time:** 5 minutes to 48 hours (usually ~1 hour)
769
+
770
+ **Step 4: Verify in Railway**
771
+ ```bash
772
+ railway domain list
773
+ ```
774
+
775
+ **Once verified:**
776
+ ```
777
+ Domain Status SSL
778
+ api.yourdomain.com Active Provisioning...
779
+ ```
780
+
781
+ **SSL certificate is automatic!** Railway uses Let's Encrypt.
782
+
783
+ }}}
784
+
785
+ ### SSL/TLS Certificates {{{
786
+
787
+ **Railway handles SSL automatically:**
788
+ 1. You add custom domain
789
+ 2. DNS verification completes
790
+ 3. Railway provisions Let's Encrypt cert (free)
791
+ 4. HTTPS enabled automatically
792
+
793
+ **No configuration needed!**
794
+
795
+ **Verify SSL:**
796
+ ```bash
797
+ curl -I https://api.yourdomain.com
798
+ ```
799
+
800
+ **Look for:**
801
+ ```
802
+ HTTP/2 200
803
+ server: Railway
804
+ x-forwarded-proto: https
805
+ strict-transport-security: max-age=31536000
806
+ ```
807
+
808
+ **Force HTTPS in your app (optional):**
809
+ ```javascript
810
+ // middleware/force-https.js
811
+ export function forceHTTPS(req, res, next) {
812
+ if (process.env.NODE_ENV === 'production' &&
813
+ req.headers['x-forwarded-proto'] !== 'https') {
814
+ return res.redirect(301, `https://${req.headers.host}${req.url}`)
815
+ }
816
+ next()
817
+ }
818
+
819
+ // index.js
820
+ import { forceHTTPS } from './middleware/force-https.js'
821
+ app.use(forceHTTPS)
822
+ ```
823
+
824
+ **SSL certificate renewal:** Automatic (every 60 days)
825
+
826
+ }}}
827
+
828
+ ### Database Connections {{{
829
+
830
+ **Railway networking:**
831
+ - Services within same project can communicate via **private network**
832
+ - No public internet needed for internal connections
833
+
834
+ **Connect to PostgreSQL from your app:**
835
+
836
+ **Option 1: Use DATABASE_URL (simplest)**
837
+ ```javascript
838
+ import pg from 'pg'
839
+ const pool = new pg.Pool({
840
+ connectionString: process.env.DATABASE_URL
841
+ })
842
+ ```
843
+
844
+ **Option 2: Use individual env vars**
845
+ ```javascript
846
+ const pool = new pg.Pool({
847
+ host: process.env.PGHOST,
848
+ port: process.env.PGPORT,
849
+ database: process.env.PGDATABASE,
850
+ user: process.env.PGUSER,
851
+ password: process.env.PGPASSWORD,
852
+ ssl: { rejectUnauthorized: false }
853
+ })
854
+ ```
855
+
856
+ **Connection pooling best practices:**
857
+ ```javascript
858
+ const pool = new pg.Pool({
859
+ connectionString: process.env.DATABASE_URL,
860
+ max: 20, // Max connections in pool
861
+ idleTimeoutMillis: 30000, // Close idle connections after 30s
862
+ connectionTimeoutMillis: 2000 // Fail fast if can't connect
863
+ })
864
+
865
+ // Graceful shutdown
866
+ process.on('SIGTERM', async () => {
867
+ await pool.end()
868
+ process.exit(0)
869
+ })
870
+ ```
871
+
872
+ **Test database connection:**
873
+ ```javascript
874
+ async function testConnection() {
875
+ try {
876
+ const client = await pool.connect()
877
+ const result = await client.query('SELECT NOW()')
878
+ console.log('Database connected:', result.rows[0].now)
879
+ client.release()
880
+ } catch (err) {
881
+ console.error('Database connection failed:', err)
882
+ process.exit(1)
883
+ }
884
+ }
885
+
886
+ testConnection()
887
+ ```
888
+
889
+ }}}
890
+
891
+ ### CORS Configuration {{{
892
+
893
+ **Allow requests from your frontend domain:**
894
+
895
+ ```javascript
896
+ import cors from 'cors'
897
+
898
+ const allowedOrigins = [
899
+ 'https://yourdomain.com',
900
+ 'https://www.yourdomain.com',
901
+ process.env.RAILWAY_ENVIRONMENT === 'development' && 'http://localhost:3000'
902
+ ].filter(Boolean)
903
+
904
+ app.use(cors({
905
+ origin: allowedOrigins,
906
+ credentials: true,
907
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
908
+ allowedHeaders: ['Content-Type', 'Authorization']
909
+ }))
910
+ ```
911
+
912
+ **Install cors:**
913
+ ```bash
914
+ npm install cors
915
+ ```
916
+
917
+ **Test CORS:**
918
+ ```bash
919
+ curl -H "Origin: https://yourdomain.com" \
920
+ -H "Access-Control-Request-Method: POST" \
921
+ -X OPTIONS \
922
+ https://api.yourdomain.com/endpoint
923
+ ```
924
+
925
+ **Expected headers in response:**
926
+ ```
927
+ Access-Control-Allow-Origin: https://yourdomain.com
928
+ Access-Control-Allow-Methods: GET, POST, PUT, DELETE
929
+ Access-Control-Allow-Credentials: true
930
+ ```
931
+
932
+ }}}
933
+
934
+ }}}
935
+
936
+ ## 🎓 Quick Reference {{{
937
+
938
+ ### Common Commands Cheat Sheet {{{
939
+
940
+ **Authentication:**
941
+ ```bash
942
+ railway login # Login via browser
943
+ railway logout # Logout
944
+ railway whoami # Show current user
945
+ ```
946
+
947
+ **Project Management:**
948
+ ```bash
949
+ railway init # Create new project
950
+ railway link # Link to existing project
951
+ railway status # Show project info
952
+ railway list # List all projects
953
+ ```
954
+
955
+ **Deployment:**
956
+ ```bash
957
+ railway up # Deploy current directory
958
+ railway up --detach # Deploy without watching logs
959
+ railway logs # View logs
960
+ railway logs -f # Follow logs (tail -f)
961
+ railway open # Open app in browser
962
+ ```
963
+
964
+ **Environment Variables:**
965
+ ```bash
966
+ railway variables # List all vars
967
+ railway variables set KEY=value # Set variable
968
+ railway variables delete KEY # Delete variable
969
+ railway variables --environment staging # Target specific env
970
+ ```
971
+
972
+ **Domains:**
973
+ ```bash
974
+ railway domain # Interactive domain management
975
+ railway domain add example.com # Add custom domain
976
+ railway domain list # List all domains
977
+ railway domain remove example.com # Remove domain
978
+ ```
979
+
980
+ **Plugins:**
981
+ ```bash
982
+ railway add # Add plugin (database, Redis, etc.)
983
+ railway plugins # List plugins
984
+ railway remove # Remove plugin
985
+ ```
986
+
987
+ **Utilities:**
988
+ ```bash
989
+ railway run node script.js # Run command with Railway env vars
990
+ railway shell # Open shell with env vars loaded
991
+ railway environment # Switch environment
992
+ railway service # Manage services
993
+ ```
994
+
995
+ }}}
996
+
997
+ ### Troubleshooting Guide {{{
998
+
999
+ **Problem: Build fails with "command not found"**
1000
+ ```
1001
+ Error: sh: npm: command not found
1002
+ ```
1003
+ **Solution:** Specify Node.js version in `railway.json`:
1004
+ ```json
1005
+ {
1006
+ "build": {
1007
+ "builder": "NIXPACKS"
1008
+ },
1009
+ "deploy": {
1010
+ "nixpacksVersion": "1.x"
1011
+ }
1012
+ }
1013
+ ```
1014
+
1015
+ ---
1016
+
1017
+ **Problem: App crashes immediately after deploy**
1018
+ ```
1019
+ Error: Application exited with code 1
1020
+ ```
1021
+ **Debug:**
1022
+ ```bash
1023
+ railway logs --tail 100
1024
+ ```
1025
+ **Common causes:**
1026
+ - Missing environment variables
1027
+ - Port binding to hardcoded port instead of `process.env.PORT`
1028
+ - Missing `start` script in package.json
1029
+
1030
+ ---
1031
+
1032
+ **Problem: Environment variables not loading**
1033
+ ```javascript
1034
+ console.log(process.env.MY_VAR) // undefined
1035
+ ```
1036
+ **Solution:**
1037
+ 1. Check variable is set: `railway variables`
1038
+ 2. Restart app: `railway up`
1039
+ 3. Verify environment: `railway status`
1040
+
1041
+ ---
1042
+
1043
+ **Problem: Database connection timeout**
1044
+ ```
1045
+ Error: connect ETIMEDOUT
1046
+ ```
1047
+ **Checklist:**
1048
+ - [ ] DATABASE_URL is set: `railway variables | grep DATABASE`
1049
+ - [ ] SSL is enabled in connection: `ssl: { rejectUnauthorized: false }`
1050
+ - [ ] Database plugin is running: `railway plugins`
1051
+ - [ ] Network connectivity: Database and app in same project?
1052
+
1053
+ ---
1054
+
1055
+ **Problem: Custom domain shows "DNS not configured"**
1056
+ ```
1057
+ Status: Pending DNS verification
1058
+ ```
1059
+ **Steps:**
1060
+ 1. Verify CNAME record exists at DNS provider
1061
+ 2. Check DNS propagation: `dig yourdomain.com`
1062
+ 3. Wait up to 48 hours (usually ~1 hour)
1063
+ 4. Use DNS checker: https://dnschecker.org
1064
+
1065
+ ---
1066
+
1067
+ **Problem: High memory usage / crashes**
1068
+ ```
1069
+ Error: JavaScript heap out of memory
1070
+ ```
1071
+ **Solution:** Increase Node.js memory limit:
1072
+ ```json
1073
+ {
1074
+ "deploy": {
1075
+ "startCommand": "node --max-old-space-size=4096 index.js"
1076
+ }
1077
+ }
1078
+ ```
1079
+
1080
+ Or upgrade Railway plan for more resources.
1081
+
1082
+ ---
1083
+
1084
+ **Problem: Slow cold starts**
1085
+
1086
+ **Optimization strategies:**
1087
+ 1. **Reduce dependencies:** Review `package.json`, remove unused packages
1088
+ 2. **Use build cache:** Railway caches `node_modules` between deploys
1089
+ 3. **Lazy load modules:** Only import what you need when you need it
1090
+ 4. **Optimize Docker layers:** If using Dockerfile, order commands by change frequency
1091
+
1092
+ ---
1093
+
1094
+ **Get help:**
1095
+ - Railway Docs: https://docs.railway.app
1096
+ - Railway Discord: https://discord.gg/railway
1097
+ - Railway CLI help: `railway --help`
1098
+
1099
+ }}}
1100
+
1101
+ ### LazyVim Workflow Summary {{{
1102
+
1103
+ **Quick navigation in this file:**
1104
+ ```vim
1105
+ zM " Close all folds - see outline
1106
+ /railway up " Search for deployment command
1107
+ n " Next match
1108
+ za " Toggle fold under cursor
1109
+ <leader>ft " Open floating terminal to run commands
1110
+ ```
1111
+
1112
+ **Working with code:**
1113
+ ```vim
1114
+ gf " Go to file under cursor
1115
+ gd " Go to definition
1116
+ K " Show hover docs
1117
+ <leader>/ " Search across entire project
1118
+ ```
1119
+
1120
+ **Editing tricks:**
1121
+ ```vim
1122
+ ci" " Change inside quotes (update URLs)
1123
+ ci{ " Change inside braces (edit JSON)
1124
+ >> " Indent line
1125
+ =i{ " Auto-format JSON object
1126
+ ```
1127
+
1128
+ **Terminal integration:**
1129
+ ```vim
1130
+ <leader>ft " Open floating terminal
1131
+ <C-\><C-n> " Exit terminal insert mode → Normal mode
1132
+ <C-w>w " Cycle between terminal and code
1133
+ i " Back to terminal insert mode (type commands)
1134
+ :terminal " Alternative: open terminal in current window
1135
+ ```
1136
+
1137
+ }}}
1138
+
1139
+ }}}
1140
+
1141
+ ## 🎯 Next Steps {{{
1142
+
1143
+ **After completing this guide, you should be able to:**
1144
+ - ✅ Deploy Node.js apps to Railway from CLI
1145
+ - ✅ Manage environment variables and secrets
1146
+ - ✅ Configure custom domains with SSL
1147
+ - ✅ Connect databases and manage networking
1148
+ - ✅ Debug deployment issues with logs
1149
+
1150
+ **Level up your deployment skills:**
1151
+ 1. **Add CI/CD:** Connect GitHub for auto-deploys on push
1152
+ 2. **Multi-environment setup:** Create staging + production environments
1153
+ 3. **Monitoring:** Set up health checks and alerts
1154
+ 4. **Scaling:** Configure autoscaling for high traffic
1155
+ 5. **Database migrations:** Learn Railway's migration workflows
1156
+
1157
+ **Resources:**
1158
+ - Railway Docs: https://docs.railway.app
1159
+ - Railway Templates: https://railway.app/templates
1160
+ - Railway Discord: https://discord.gg/railway
1161
+ - This guide in Creta: `creta` → "Practicar con ejercicios" → "Railway Deployment Guide"
1162
+
1163
+ }}}
1164
+
1165
+ ---
1166
+
1167
+ **💡 Pro Tip:** Keep this guide open in LazyVim while deploying with Railway CLI!
1168
+
1169
+ **Terminal Workflow:**
1170
+ 1. Open this guide: `nvim lib/exercises/railway-deployment.md`
1171
+ 2. `<leader>ft` - Open floating terminal
1172
+ 3. Type Railway commands (e.g., `railway up`)
1173
+ 4. `<C-\><C-n>` - Exit terminal insert mode (to Normal mode)
1174
+ 5. `<C-w>w` - Cycle back to guide to read next steps
1175
+ 6. `<C-w>w` - Back to terminal
1176
+ 7. `i` - Enter insert mode to type more commands
1177
+ 8. Repeat steps 3-7 as you work through the guide!
1178
+
1179
+ **Quick reference:**
1180
+ - `<leader>ft` → Open terminal
1181
+ - `<C-\><C-n>` → Exit terminal typing mode
1182
+ - `<C-w>w` → Switch windows
1183
+ - `i` → Start typing in terminal
1184
+
1185
+ **🏛️ Salgamos de este laberinto** - Happy deploying with Railway! 🚂