Start with Single File FREE
Learn how to create and deploy a web page using AI prompts and templates. This is the fastest way to get started with QuickStart.
Log in to QuickStart and click Single File from the left menu. The AI Coder Editor opens with an integrated development environment for HTML, SCSS, and Vue.js — all in one screen.
Click the template dropdown at the top of the editor. Browse pre-built templates like landing pages, portfolios, dashboards, and more. You can also use community-shared templates.
Once the template loads, HTML, SCSS, and JavaScript code appear in the editor. Modify anything you like and hit the Run button to see live results. You can also ask AI to generate code via prompts.
For your first deployment, you'll need a Railway account. Go to Settings > Account and register your Railway API token. This is a one-time setup that applies to all future deployments.
Click the Deploy button at the top of the editor. The deployment progress is shown step by step — file generation, server upload, build — all handled automatically. It usually takes 1-2 minutes.
Once deployed, QuickStart automatically assigns a free domain. Click the domain link to see your web page live on the internet. Congratulations!
Start with Project
Build a full-stack web application with frontend and backend. Project is not a standalone entry point — it deploys on top of a container (domain) that must already be provisioned via the Database or Macro path. Complete one of those paths first, then come back here.
From the Project menu, click "New Project". Enter a name and description, then select an existing domain (container) and dataset — the project structure will be scaffolded on top of that container. A domain represents the Docker container where your project runtime lives, so it must be provisioned in advance through the Database or Macro path.
Add programs inside your project. Each program represents a page or feature unit. Create the UI with HTML/CSS and write server logic in PHP. AI can auto-generate code from prompts.
Set up routers to map programs to URLs. For example, connect a "Board" program to /board. Visitors can access it through that URL. You can specify GET/POST methods too.
Click Deploy to start the 8-step automatic deployment: Pack creation → DB setup → Data encryption → Server upload → Build → Configure → Test → Complete. Watch real-time progress for each step.
After deployment, visit the domain connected to your project. Test that all programs, routers, and database connections work correctly.
Start with Database PRO
The lightest entry point. Choosing this path provisions a Docker container (domain) bundled with one database engine (MySQL, MariaDB, PostgreSQL, or MongoDB) + a PHP/Laravel backend + npm — a deliberately minimal-feature stack. Ideal when you only need a DB plus a simple web backend and want to keep the footprint small. Start by storing data, running SQL, and auto-generating REST APIs. Switch to the Macro path later if you need a richer runtime.
From the Database menu, click "New Dataset" to open the wizard. In step 1 pick either Deploy (provision a fresh DB container via Railway) or Connect (supply host / port / credentials of an existing DB you already run), then choose the engine — MySQL, MariaDB, PostgreSQL, or MongoDB.
Browse table lists in the DB Editor and inspect field structures. You can also create new tables or modify existing ones.
Enter SQL in the query editor and execute it for instant results. All SQL statements are supported — SELECT, INSERT, UPDATE, DELETE. You can even ask AI to write queries in natural language.
Pick a table and click Generate API — a mapping interface opens where you can review the API structure. Accept the defaults to produce CRUD (create / read / update / delete) endpoints in one shot, or restructure exposed fields, parameters, and response shape to match exactly what your frontend needs before generating.
Bind the generated APIs to Layout Builder blocks or call them from project programs to build data-driven web services. Import/export data via CSV or JSON.
Start with Macro MAX
Pick this path when you need a far richer runtime than the Database path offers. It provisions a Docker container (domain) with MariaDB and PostgreSQL bundled automatically, MongoDB available as an optional add-on, and Python, Node.js, curl, jq, recurring timer automation, ffmpeg, and most of the tooling you may or may not need down the road — preinstalled and ready. Well-suited for composite workloads: data scraping/processing, external API orchestration, media transcoding, scheduled automation. If you're torn between "DB + PHP is enough" and "I might need more later", this is the safer choice.
From the Macro menu, click "New Macro" and enter a name. If you need input parameters, define their names, types, and default values. Parameters are variables that receive values at runtime.
Write your automation logic in Node.js or PHP using the code editor. Call external APIs, process data, handle files — anything you need. Access parameters and execution context through the run_data object.
Test your code instantly. Click Quick Test and the macro runs immediately, showing results in the bottom panel. Supports multiple result formats: tables, JSON, download links, and messages.
To run a macro automatically on a recurring basis, set two values: a start time (HH:MM) and an interval in minutes. Examples: 00:00 + 5 → every 5 minutes from midnight; 03:30 + 1440 → once daily at 3:30 AM.
Deploy your macro to a Railway server for reliable, independent execution. After deployment, an API endpoint is created so you can trigger the macro via HTTP requests from external systems.
QuickStart Overview
Understanding the core concepts below first makes it much easier to see how QuickStart's features interlock — and you'll get far more value out of the service. Scan the concept map up top by category, then click any chip to jump into a detailed card. Cross-links inside each description let you move fluidly between related concepts.
Concept Map
Core Concepts
Domain
happycat.apidealder.net). It's created automatically when you go through the Database or Macro Deploy path, and every Project is installed on top of an existing domain. One user can own multiple domains; multiple projects can share a single domain. Deploy
deploy_logs. Re-deploys usually complete in about a minute. Agent
Project
Program
Program Builder
Hook
mounted, beforeUpdate, updated, and so on — and each hook is a slot where you can inject "code to run at that moment". You keep the builder's default behaviour while surgically adding your own logic exactly where it fits, giving no-code assemblies a clean extensibility escape hatch. Scaffold
Router
/board → the Board program. Supports GET/POST methods, URL parameters, and auth requirements. With the VSCode extension, routes are auto-derived from function names. Revision
Solution
Dataset
Parser
Block
Preset
Frame
Scene
Macro
Translation
Patch
User
Architecture
QuickStart is split into 4 tiers with clearly separated communication responsibilities. In particular, bulk data flows directly between the client and the Agent without passing through the QuickStart server — the design is intentionally optimized to minimize server traffic and storage.
Layer Breakdown
Client (Browser)
- Dedicated editors for Single File · Project · Database · Macro · Data Collection
- Chat with AI and preview the result instantly
- 40-language switching and preview inside the Project feature
- Safely stores login info, in-progress edits, and theme settings in the browser
- Drag-and-drop canvas for placing blocks in the Layout Builder
- Large files upload and download directly to the user's container, bypassing the central server
QuickStart Server
- Account · pricing plans · payments management
- Keeps track of project · solution · domain lists and their current state
- When a deploy starts, each step runs automatically in the right order
- Issues the temporary transfer permits browsers need for direct container transfers
- Serves the pages and resources needed to render the UI
- Regular-user data never passes through the central server, keeping load and cost low
Docker Agent (User Server)
- Always on, running inside the user's domain (container)
- Directly creates, reads, updates, and deletes the real data for programs · blocks · routers · datasets
- Remote file operations — upload · edit · download
- Runs deployed programs · macros · data-collection tasks directly
- Verifies requests via a dedicated security key and temporary permit
- User data stays isolated inside this container, never mixed with anyone else's
Railway Hosting
- Provisions new containers and provides the deploy environment
- Auto-assigns a default domain and supports connecting your own
- Scales processing power and memory automatically with traffic
- Aggregates execution logs and status metrics
- QuickStart drives container operations through an official integration channel
Network Flows Between Layers
| Channel | Endpoints | Protocol | What Flows |
|---|---|---|---|
| Control Channel | Client ↔ QuickStart Server | Secure, session-backed connection | Carries everyday requests like logins, project listings, and settings changes. Payloads are small, so the UI feels snappy and server load stays low. |
| Data Channel (server-bypassing) | Client ↔ Docker Agent | Single-use transfer authorization | File uploads, downloads, remote editing, and large query results travel here. The user's browser communicates directly with the user's own container — the central QuickStart server is not in the path, so large transfers incur zero server storage or bandwidth cost and stay fast. |
| Coordination Channel | QuickStart Server ↔ Docker Agent | Container-scoped security key | Used to check that a user's container is healthy, probe available capabilities, and exchange the management signals needed around deployments. No real user data ever flows here. |
| Provisioning Channel | QuickStart Server ↔ Railway | Official integration with the infrastructure provider | Delivers infrastructure instructions — new container creation, deploy requests, domain wiring. If a user registers their own Railway account with QuickStart, these actions run inside that account. |
| Containment | Docker Agent ⊂ Railway | — | The agent runs inside a container that Railway manages. Railway owns the container's lifecycle, resources, and network, so infrastructure-level issues are absorbed there and users can focus on their service logic. |
The central server handles only control and coordination, while actual data is exchanged directly between the user's browser and the user's own container. That keeps transfers fast under heavy load because there is no central bottleneck, and it drives server storage and bandwidth cost down sharply. Most importantly, each user's data stays isolated inside their own container — there is simply no path for it to mix with another user's or with the central server, so data security is a property of the architecture itself.
Pricing & Plans
Start free with QuickStart, then expand to PRO or MAX as needed. The table below captures the core differences at a glance.
| Plan | Available Services | Best For |
|---|---|---|
| FREE |
Single File
Layout Builder
Slideshow Basic
Domain Management
Community Support
|
Individuals publishing ideas as quick single-file pages |
| PRO |
+ Everything in FREE
Full-stack Project
Database
Web Crawling
Slideshow Parameter Cursor
|
Operators running full-stack web apps who also need database and web crawling |
| MAX |
+ Everything in PRO
Coder Builder
Macro Automation
Scheduled Crawling
Display Channel
|
Power users who need scheduled automation and advanced builder features |
Single File
The simplest way to create a web page from a single file.
- {{ item }}
Go to /service/single. The top toolbar is split into three zones.
- Left — History · Guide · App title · Save (💾)
- Center — Template dropdown (11 options)
- Right — Shared list · Share · Copy · Run ▶ · Deploy 📦
The body has four editor tabs (prompt · html · scss · vuejs) and a live preview on the right.
Two ways to start:
- Prebuilt templates — 11 options in the dropdown: E-Commerce · Realtime Stock Chart · Favorites Dashboard · SaaS Pricing · Kiosk Menu · Restaurant Booking · YouTube Creator Hub · Product Detail · Chat App · Event Countdown · Admin Dashboard. Selecting one fills all four tabs instantly.
- AI prompt from scratch — describe what you want in the prompt tab (e.g. "a cafe menu page with 3 category tabs"), then use the AI button to auto-generate the HTML/SCSS/Vue tabs.
Switch tabs to edit each layer.
- prompt — the description used for AI regeneration. Editing + regenerating refreshes the code.
- html — structure and text. Line numbers + Ctrl+F search.
- scss — colors, fonts, spacing. Most templates define theme variables at the top of the file.
- vuejs — data and interactivity. Uses
data() { return { ... } },methods: { ... },mounted().
const/let, arrow functions, and template literals are forbidden. Use var and function.
Click Run ▶ on the right side of the toolbar to render the page live in the preview panel. Click again after edits to refresh.
The History button on the top left opens your recent saved versions. The → Load icon on a row restores that state — your safety net when an edit breaks things.
Two ways to get your work out:
- Deploy 📦 — the rightmost toolbar button. After connecting a Railway account, a deploy progress modal runs; in 1–3 minutes your page is live on a free domain.
- Share — the share icon in the toolbar. Add title/description/tags and publish to the community; other users can fork your work (this is a template share, not a live deploy).
Project
Develop full-stack web applications with both frontend and backend.
- {{ item }}
Open Service > Project from the menu. The layout:
- Left sidebar — blue [+ New Project] / [+ New Team] buttons plus Recent, Public Solutions, My Projects, Teams sections.
- Top breadcrumb — switches between list ↔ detail ↔ programs ↔ deploy views.
- Body — cards showing each project's domain badge, DB type, and program/router counts.
Click [+ New Project] → wizard modal.
- Step 1 — feature cards and a flow diagram.
- Step 2 — config
- Domain (required) — one of your existing domains
- Dataset (required) — the DB this project will use
- Project name / description
- Team assignment (checkboxes)
- [Save] at the bottom — only enabled once both domain and dataset are selected.
A program is one page or one piece of functionality inside a project. Fill in basic info in the creation form, then jump straight into the code editor to author Blade + SCSS + Vue on a single screen.
1) Creating a new program
The project detail toolbar shows [+ New Program] and [+ New Router]. Clicking New Program opens a form modal.
- Program name (e.g.
home,admin_dashboard) - Description — one-line note about what this screen/feature is
- Type — frontend (HTML/CSS/JS) / backend (PHP)
- Router — pick an existing router, or inline-create one with alias + URL path + HTTP method
2) Opening the code editor & screen layout
Click the icon on a program row to switch into the editor view. The screen is divided into three zones.
- Top breadcrumb + tool bar — current program name, save-state indicator, and a group of tool buttons all on one row.
- Left sidebar — list of other programs in the same project. Each item has (Code) and (Builder) quick icons that jump between views.
- Center 3-column editor — three CodeMirror 6 panels (HTML / CSS / JavaScript) laid out side by side. Clicking a panel highlights it as focused, and the editor theme follows your Dark/Light setting automatically.
3) What each tab actually holds
- HTML — plain HTML plus Blade directives (
@if,@foreach) and@{{ ... }}output. Server-side variables, conditions, and loops are expressed directly in the template. - CSS — SCSS syntax (nesting,
&references, variables, mixins) straight through. Compiled automatically on deploy. - JavaScript — Vue 3 Options API shape (data / computed / methods / mounted). The runtime picks this up automatically and binds it to the template in the HTML column.
Standard CodeMirror shortcuts work as expected: Ctrl+F for in-editor search, Ctrl+Z undo, Ctrl+/ comment, automatic bracket/tag closing, and soft line wrapping.
4) Edit state & the save cycle
The moment you change a single character, Unsaved appears in the top bar to tell you there are unsaved changes. Click [ Save] and all three tabs are shipped at once; on success a Saved check briefly appears.
Each save writes the three columns into the program body and simultaneously records the moment as a revision. Save = an automatic version snapshot — you can roll back to any of them later.
5) Deploy on Save — straight to live on every save
Flip the [Deploy on Save] toggle next to Save to ON and every save also auto-deploys the change to the project's destination (e.g. the main server). A short "N deployed" badge briefly appears after the push, so you never have to click a separate Deploy button — the "edit → live" loop closes itself. The toggle is remembered per project, so turning it on once sticks.
6) The top tool cluster at a glance
- Database — opens the dataset binding popup. Name a variable, pick a table, set WHERE/LIMIT/ORDER, and the query result is auto-injected into the program under that variable.
- Builder — switches to a block-based editing view of the same program. Code view and Builder view share the same output.
- Code Search — project-wide search & replace panel (see 7 below).
- Revisions — revision history with diff panel (see 8 below).
- Extension Guide — popup explaining how to edit and deploy the same project locally via the VSCode extension.
7) Project-wide Search & Replace
Type a keyword at the top and press Enter or the button. The scope tabs give you two choices — Project (all programs in the current project) or Revisions (include past snapshots).
- Results show a type badge (HTML / CSS / JS), program ID, program name, and match count.
- Type filter tabs All / HTML / CSS / JS narrow results to a single column, with the match count on each tab.
- Click the arrow next to a program name to jump straight into that program's editor.
- Click [Show More] on a row to open the context panel on the right showing the surrounding code for every match.
Replace lives on the second row. Pick a scope (All / HTML / CSS / JS), fill in search and replace terms, hit the button — a "changes will be made in N files" confirmation appears, and on Yes the project-wide replace runs in one shot.
8) Revisions · history and rollback
Every save adds a snapshot here. The moment the panel opens it auto-diffs the latest revision ↔ your current edits on the right-hand side.
- Left: the revision list (paginated). Each row has three action icons:
- Revert — overwrite the editor with this revision (unsaved changes are lost).
- Diff with current — this revision ↔ what's in the editor right now.
- Diff with previous — this revision ↔ the revision immediately before it.
- Right: side-by-side diff with HTML / CSS / JS tabs. The tab that actually changed is auto-selected.
9) The actual order an author follows
- Open the editor from a program row's icon.
- Author in the HTML(Blade) → CSS(SCSS) → JS(Vue) tabs, whichever the change needs.
- Reach for Database when data is needed, Code Search for cross-program lookups, Revisions to compare against history.
- Hit [Save] → wait for "Saved". If Deploy on Save is ON, the deploy goes out too.
- If something breaks, revert to the right snapshot via the Revisions panel.
- For a rename that spans many programs, use Code Search → Replace to do it in one confirmed action.
Register routers in the collapsible router section of the detail view or via [+ New Router].
- alias — internal identifier (e.g.
home,api_orders) - URL path — public path (e.g.
/home,/api/orders) - HTTP method — GET / POST / PUT / DELETE / ANY
Connect a router to a program in the program form's Router selector — visitors hitting that URL will trigger the program.
function list_orders().
Click the 🚀 (rocket) icon on a project list card to open the deploy modal.
- Pick a deploy mode: integrate (reuse existing Docker) · rebuild · new
- Click [Start deploy] → the 9-step pipeline runs (each turns green on completion):
① Pack create → ② DB prepare → ③ Data prepare → ④ Server transfer → ⑤ Docker build → ⑥ Docker deploy → ⑦ Domain connect → ⑧ Install complete → ⑨ Service stabilization - When finished, the domain URL is live and immediately reachable.
Code Builder
A tab-based wizard that designs the list · detail · search · CRUD screens around one (or several) DB tables, plus any needed PHP/Vue code, and turns the whole thing into a finished program (Blade + Vue Script) with one click of the [Builder] button. You enter it via the icon from the program list. You never hand-write boilerplate — the path from DB schema → UI → interaction is automated end-to-end.
- {{ item }}
Open the Code Builder via the icon on a program row. Eight step tabs sit at the top (DB · List · Detail · Search · Hook · Style · Code · Menu); most programs are finished by going through them left-to-right just once.
The flow at a glance
- [1] DBpick tables
pick fields
WHERE · ORDER - [2] Listplace fields
groups · sort
five layouts - [3] Detail · Searchshape the form
choose components
insert / update split - [4] Hook · Codeinject hooks
[Builder] emits code
reuse snippets - [5] Menu4-level tree
[menu:code]
common include
DB tab in detail — if the connection is down you first see a "DB not connected" banner with a reconnect guide. Once it is live, the panel opens up like this:
- #list (editable) — one main table. Pick from the dropdown and press [Select]. This is the table whose rows you will edit / delete / insert.
- #list2 (view-only) — a secondary table for joins (e.g. pulling labels or names).
- #list3, #list4 … — click the in the sidebar to add additional tables.
- Three field pickers — from the same column list you separately multi-select "fields for List", "fields for Detail", and "fields for Search". A checkbox next to each toggles all on / off.
- DB Search Option —
WHERE·ORDER BY·LIMITthree lines, plus an optionalRaw Query. These become the default query filter for the list. - Bottom [Update] saves the step; [Reset] starts over.
The "fields for List" you picked in the DB tab appear as candidates on the left. This tab defines what the list screen looks like and how each column behaves.
Pick one of five layouts first. The options below auto-adjust to your choice.
- datatable — table with built-in sorting and pagination.
- table — plain table with per-column sort toggle.
- grid — card grid.
- modal — list that opens rows as modals in place.
- slots — embedded into slots of a layout frame.
Add items (field columns) — click [+ Add Item] on the left to open the candidate dropdown. Pick an existing field, or use + new to add a virtual one (for computed or composed values).
- Per row: header_value (display label) · header_text (description) · width · mutator (per-field custom code) · sortable · linkable · use_opt (option value) · (show / hide toggle).
- Use ↑↓ to reorder, to remove, the wand for AI-assisted code.
Grouping — the top-right [Create Group] bundles selected fields into 1–5 groups. Tap … to assign items into a group.
- In group mode, [Toggle Panel] switches the view to a group edit panel. There you fill in, per group, a group name (internal identifier), a group header (title shown on screen) and a layout (how columns inside the group are arranged). At the top of the panel the group display method decides how multiple groups are shown — tabs, side-by-side boxes or a single input group row.
[Update] at the bottom saves the step.
The Detail tab defines the detail / edit popup (modal) that opens when you click a row in the list. The layout looks almost identical to the List tab; the key extra is picking an input component per field.
- Component dropdown — choose the input type per field: text · textarea · select · checkbox · radio · date · datetime · file · editor · hidden …
- opt_name / opt_value — extra options specific to the component (option list for select, allowed extensions for file, format for date …).
- insert / update triangle icon — toggles whether the field shows up on the Add form, the Edit form, or both. e.g.
id/created_atare normally edit-only. - required (+/-) toggle — required-input flag.
- layout — cell placement / width (1/2, 1/3, full-width, …).
- In the top toolbar pick the primary key column (the column that uniquely identifies a row) and the detail page key (the column that will be carried in the URL when a detail page opens).
The Search tab shares the same editor. Differences:
- Match mode — how the typed value is looked up against the DB: contains (partial match) · equals (exact match) · one-of (match against a comma list) · full-text (word search in long text), and so on.
- Components reflect search UX — free-text inputs, dropdown filters, …
Search inputs are auto-placed above the list; submitting them AND-combines with the DB-tab WHERE you set earlier.
By now steps 1–3 have filled in the screen "ingredients". Time to add fine-grained behavior, permissions, and custom logic, then emit the code.
Hook tab — shows a small diagram of the generated HTML and JavaScript scaffold, with a set of hook points (badges) where you can inject custom code.
- Mini HTML / JavaScript skeleton at the top — <?php ... ?>, <style>, <body>, modal, data / computed / mounted / methods positions are marked so you can see exactly where your hook ends up.
- Expand any hook row with to reveal its editor. Double-click for wide mode.
- Right-click in the editor → Save Snippet / Load Snippet. Save recurring logic (login checks, permission guards, upload preprocessing …) under an ident and reuse it in any other program.
Style tab — CSS / SCSS editor for this program. Flip css_integrate to merge with the project's global CSS bundle; flip Backend Code to attach a PHP snippet too.
Code tab · the actual generation — this is where you press [Builder].
- Two CodeMirror editors — Blade template on the left, Vue Script on the right. They preview the code assembled from steps 1–3 and your hook inputs.
- Session Condition, four cells — Add / Delete / Read / Detail. Each takes a session predicate (e.g.
user_level>=3) guarding that CRUD operation. - Feature toggle grid — turn on reusable features (CSV / Excel export, multi-delete, sort persistence, …) and set any needed parameters.
- The [Builder] button at the bottom assembles everything into Blade + Vue Script and writes it straight into the program's actual code. From there the regular code editor takes over — edit, save, deploy as usual.
[menu:code] shortcodeOnce you have several programs you'll want a shared navigation. The Menu tab is a wizard that builds a menu tree up to 4 levels deep and lets you drop it anywhere via a one-line shortcode.
Menu group — a namespace that holds one menu definition inside the project.
- Pick an existing group from the dropdown, or type a new group code (alphanumeric + underscore, 2–9 chars) and press [Create Menu Group].
4-depth tree editor — selecting a group reveals a Depth 0 table on the left. Drilling into a row opens the next depth to its right; up to four columns line up as you go deeper (Depth 0 → Depth 3).
Depth 0 ┐
├─ Depth 1 ┐
│ ├─ Depth 2 ┐
│ │ └─ Depth 3 ← max 4 levels
└─ Depth 1'
...- Each depth table has its own [+ Add Menu] button — the popup lets you fill name, URL alias, and optional session condition.
- Per row: edit, delete, arrows to reorder.
- Click the check button at the end of a row to drill into that item's children in the column on the right.
Inject as a shortcode — once the tree is in place, drop it onto your actual pages. In a common include area (a layout frame, a header / sidebar partial) a single line is all you need:
<?php echo get_menus_by_code($project_id, 'group_code', 'nav nav-menu', 'role="navigation"'); ?>
At render time, the get_menus_by_code() helper reads the project_menu table and assembles <ul>/<li> up to four levels deep. Menu rows that carry a session_condition are only shown when the user's session satisfies it. The item whose URL matches the current page automatically receives the active class.
get_menus_by_code($project_id, 'main') into the header / sidebar slot of a layout frame. From that point on all menu edits happen only in the Menu tab, and every page picks them up immediately. The custom_class and custom_attr arguments let you hand the renderer your design theme's class names and attributes, so the same menu adapts to dark / light, sidebar / topbar without touching the helper.
Layout Builder
Build web page layouts by assembling blocks — no coding required.
- {{ item }}
Go to /layout/page.
- Left sidebar — [+ New Page] button + Recent / Shared / My Pages sections.
- Top toolbar — search (field + keyword), Block/Frame/Page switcher tabs, Grid/List toggle, rows per page (20/50/100).
- Body — page cards with title, description, frame, deployed-or-not indicator.
Click a page card or the grid icon to open the full-screen builder. It has three areas.
- Left panel — top: Frame filmstrip (pick the responsive template), middle: Frame canvas (iframe + slot overlays), bottom: Block filmstrip (draggable blocks).
- Center panel — Data sampler (Architecture / Data tabs) for API binding.
- Right panel — Deploy + AI assist.
After picking a Frame, transparent drop slots appear over the iframe. Start dragging a block from the Block filmstrip and the slots highlight blue — drop to install the block in that slot.
Installed slots become "filled"; click the slot again to swap. The same block can fill multiple slots, and one page can mix different blocks freely.
In the center panel's Architecture tab, pair each block's sample data keys with actual API response keys.
- Each block card's left column shows the sample key tree the block expects.
- The center ⚡ (lightning) toggle switches on API-binding mode.
- On the right, pick an endpoint you built in the Database service → that API's response key tree expands.
- Click to pair a sample key with an API key — a mapping line connects them and appears in the "Pair Map" at the bottom as
sample_key → api_key.
The Data tab shows raw JSON responses for debugging.
Use the right panel to deploy.
- Expose parameters — list of query/path parameters to expose in the URL. Each row has an enabled checkbox, name, source (query/path), default value. [Add] to grow the list.
- Deploy URL — typing a slug like
/my-pageupdates the preview live. - [Deploy] — shows a progress bar + step label; when done, it's live on the domain.
- Below, the Deploy history accumulates past URLs you can revisit.
category as a path parameter lets the same page code serve /product/beverage and /product/dessert with different data — no code duplication.
Slideshow
A channel service for managing presentations and display content.
- {{ item }}
Open Display > Slideshow from the menu. Left sidebar has a [+ Register slideshow] button and a "Community slideshows" filter; the body is a Grid/List view.
Each card shows title, scene count, total play duration, and deploy status.
Click [+ Register slideshow].
- Step 1 — Introduction: cards + flow diagram (Remote → Upload → Slideshow → Browser) explaining URI mapping, channels, 67 transitions, and timeline control.
- Step 2 — Register: enter title + description → [Save] → lands in the detail editor.
The center Timeline panel defines playback.
- Total duration — slider, 10–3600 s.
- Scene count — range slider; per-scene duration auto-calculates.
- Transitions — pick from a catalog of 67 (fade, slide, cube, page flip, etc.).
- Confirm with the [Save] button.
Parametric cursor (Page Sequencer) auto-generates N scenes from a single layout page by varying one parameter.
- Parameter name (e.g.
month), algorithm (by_range/by_comma/by_json), values (e.g.1-12step 1). - Result: 12 auto-generated scenes, one per month.
Display channels (MAX only) — broadcast the same slideshow with different mixes to different displays.
- Channel name (e.g. "Category A", "Category B") + multi-select slides to include.
- Toggling "Use query parameter" maps channels to URLs via
?keyword=value.
The right deploy panel (se-deploy) publishes the show.
- Type a URL path (e.g.
/menu-signage) + pick a domain from the dropdown. - Click [Deploy slideshow] — progress bar, "Deploying..." and "Deploy complete" messages.
- A deploy history card records domain / path / timestamp.
Point each display's browser at the URL in fullscreen — you're done.
Data Collection (Parser)
Automatically crawl websites and save data to your database.
- {{ item }}
Open Data > Parser from the menu. Left sidebar has [+ New Parser Rule] plus Recent / Public / My rules sections; the body is Grid/List view.
Each card has (Run) · (Item test) · (Schedule — MAX) · (Edit) · (Duplicate) · (Delete) icons.
[+ New Parser Rule] opens a 3-step wizard. The wizard only registers the base rule info (name, description, target dataset) — the actual crawl URL, selectors, and field mapping are filled in afterwards on the parser settings screen that opens automatically when the wizard finishes.
- Step 1 — Overview: A "What is a Parser Rule?" intro followed by four feature cards side-by-side (Data Extraction, Advanced Web Crawling, Field Mapping, Reusability) and a "Parser Pipeline" diagram showing the four supported flows at a glance (Parser Rule → DB / → Macro → DB / → Scheduler → DB / → API Endpoint → Service Launch). Press [Next] to continue.
- Step 2 — Database Connection: Click a dataset card (shows db_type badge, table name, domain) to pick where extracted rows will land. If no datasets are registered, only a "Go to Dataset" link is shown. Pressing [Next] auto-runs a 3-step deploy progress ("Agent connect → Parser engine deploy → Deploy complete") that provisions the parser engine on the selected docker agent.
- Step 3 — Create Rule: Enter the rule name and optional description, then press [Create Rule]. The base info (name, description, dataset, share flag) is saved, the wizard closes, and the settings screen of the newly created rule opens automatically.
That is where the wizard ends. On the parser settings screen you then fill in the target URL, HTTP options, Loop Splitter, XPath/JSON selectors, and field mapping (see ▶︎ Step 3 · Target URL & extraction selectors), verify results on the "Test" tab, and save — only then is the parser ready to actually run.
A step bar at the top tracks progress; [Back] returns to the previous step (disabled while deployment is running). The wizard modal closes only via the top-right [x] button.
Enter the Target URL at the top of the editor and combine three techniques to extract rows.
- Loop Splitter (3 inputs — primary + 2 secondary) — string patterns that chop HTML into repeated units.
- XPath selectors — up to 3 levels, extracting fields inside each unit. The selector should point at a node set (array), not a leaf value — if the actual data sits at
//h3/a/text(), enter just//h3/aso the result comes out as an array. - JSON selectors — for JSON APIs, dot/bracket paths. Same idea: point at the array path. If the data has a shape like
data.items[0].title, enterdata.itemsas the selector so the item array is produced. - Post-processing functions — chain
trim(@p),replace(...),regex(...),strtoupper(@p),slice(),remove()per column.
The fastest path is to feed a slice of the source (via the Loop Splitter) into the AI Prompt and let the AI response auto-register the rule. Hand-tuning selectors one by one is much slower — especially when the page structure is non-trivial.
Auto-register with an AI prompt (recommended)
Instead of hand-filling selectors, hand the sample to an AI and apply the completed rule it returns.
- Prerequisite — enter the Target URL and run the extract test once from the "Test" tab so a response body exists. That body is injected into the prompt automatically.
- Click the highlighted "AI Prompt" button (wand icon) at the top of the test result panel. A prompt is auto-built in the editor area just below it, picking the right language for the document out of 8 supported (Korean · English · Japanese · Chinese · Russian · German · French · Spanish) and the right document type (HTML / JSON / XML).
- Click inside the editor panel → Ctrl+A → Ctrl+C to copy everything.
- Paste into an AI such as ChatGPT / Claude / Gemini and run → the AI returns a rule JSON.
- Copy the response, then click the "Import Pattern" button (import icon) in the same panel — a paste-in textarea opens. Paste and click [Apply Pattern].
- Loop splitter, selectors, unique key, and every column are mapped into the right slots of the rule automatically; the editor switches to the "fields" tab so you can check the result immediately. A summary toast like "Pattern applied: N fields" appears at the bottom.
If the AI response isn't valid, you'll see an "Invalid JSON" toast and your existing values stay untouched — safe to retry.
The (vial) icon on a card — or the Test tab in the editor — opens the test modal.
- Top bar: "N items / M columns"
- Exports: CSV · XLSX · JSON · HTML
- Grid: Row# + auto-detected columns
- Cell hover → "Copy" button
Tweak selectors, test, adjust, test — repeat until the output looks right.
Clicking the (Play) icon on a rule card opens the Run modal — the single screen where you decide where to hit, with what parameter combinations, how to run, and where to store results, then launch and monitor in place.
- [1] URITarget address
{param} tokens
path · query - [2] FuzzerParameter mix
1-N · A,B · DB
combine / pair - [3] PreviewExpand URLs
Fill left panel
Verify count - [4] Run · SaveRuntime / Schedule
DB / CSV / JSON
Items per run - [5] StartFlow checks
[Start] enables
Pause anytime - [6] FeedbackProgress · stats
Per-URL log
Macro chain
Interface at a glance — 3-panel layout
- Left panel · URL list — shows the preview URLs generated from the center panel, numbered. While a run is in progress the current row is highlighted and finished rows show a check, so you can see progress at a glance. Each row has a button to test-parse that single URL in isolation, and a at the top-right loads past run configurations for reuse.
- Center panel · Plan & Execute — the main body: define URI, fuzzer parameters, run/save mode, then launch from the flow diagram's [Start] button.
- Right panel · Result feedback — two tabs. "Results" shows live statistics and log during a run; "Parse Test" shows the cell-level preview when you click on the left.
Step-by-step
- URI input — first card in the center panel. Two example styles — path-token (
/category/{param}/list) and query-string (?param={param}) — are pinned to the header as clickable hint badges. Names inside the curly braces{...}must match the parameter names defined in the next card so substitution works. - Fuzzer parameters — the card that builds the list of values injected into each
{...}. A top toggle picks one of two modes:- Combination — cartesian product of every parameter's values. E.g.
{page}=1..10 ×{cat}=A,B → 20 URLs. - Paired — zip-style: the n-th value of every parameter together. All lists must have the same length.
- Combination — cartesian product of every parameter's values. E.g.
- URL preview — the [URL preview] button at the bottom of the card expands the URI + parameter combinations into real URLs listed in the left panel. The count shows in the header badge, so you can immediately verify the expected size (e.g. range 10 × categories 2 = 20).
- Run mode & Save mode — the third card.
- Run: Runtime (one-off) / Schedule (periodic, MAX plan). Schedule reveals start-time and interval (minutes) inputs inline.
- Items per run: Page / PK.
- Save: DB (dataset, or a custom external DB via host/user/password/database), CSV, JSON, or SQL. DB mode also surfaces table (collection) name and a DBMS badge so you can confirm the destination visually.
- Visual flow guide & Start — below the cards, a small flow diagram chains URI → Parameter → Preview → Save → [Start] → Macro. Each node lights up with a green check as its input is filled. Once required nodes are valid the [Start] button at the top-right activates. (If you pin a macro on the trailing node, it runs automatically right after the scrape.)
- Live feedback while running — the moment you press Start, the top progress bar fills up (parsed / total) and the right-panel "Results" tab updates in real time.
- Stat cards: Total · Passed · Failed · Remaining — the red "Failed" card only appears when a failure actually happens.
- Log view: one line per URL as it's processed, latest highlighted, each showing time · URL · +rows added; failed URLs carry an badge.
- Pause / Resume: the Start button switches to [Pause] during a run — stop at any time safely.
- File-save modes (CSV/JSON/SQL): the Output textarea below fills with the generated file body; a button grabs it immediately.
What this run screen buys you
- Plan, run and observe in one screen — no tab hopping. Tweak the URI, parameter list, or save target and immediately re-run. The configure → run → verify loop is as tight as it gets.
- A fuzzer that scales — generate tens of thousands of URLs without writing one by hand. Ranges, comma lists, DB columns, JSON arrays, newline lists — category × page × date combinations are ready in seconds.
- DB-backed parameters (by_db_field) read a key table column and iterate detail pages on top of it — the classic "list → detail" two-stage crawl works end-to-end without spreadsheets or glue scripts.
- Transparent live feedback — per-URL checkmarks, streaming log, and success/fail counters make it easy to spot exactly where things stalled. Rerun a failed row on its own via to isolate the cause.
- Resource-friendly architecture — the actual HTTP and parsing runs on your docker agent, not the QuickStart server. Large crawls don't affect the service's bandwidth.
- Macro chaining — attach a macro to run right after the scrape for notifications, aggregation, or post-processing, turning collect → clean → notify into a single action.
Scheduled runs are a hands-off mode: the docker agent executes the rule on a fixed interval on its own, even while the screen is closed. Rows flow straight into the dataset (DB), so to actually see the results you open the target table in the Database editor.
- [1] Schedule setupStart time
Interval (min)
Active toggle - [2] Agent sync[Save] pushes
config to the
docker agent - [3] Auto periodic runAgent runs alone
QuickStart idle
Background task - [4] DB accumulationRows INSERT into
dataset table
Dup keys skipped - [5] Check in Database editorData > Database
Open the table
Query with WHERE/ORDER
The (clock) icon on a card opens the schedule modal (FREE/PRO plans show a "Max" ribbon).
- Start time (hour 0–23, minute 0–59)
- Interval (minutes)
- Active toggle
- Run mode: Single URL / URL list (batch)
[Save] persists to QuickStart and auto-syncs to the selected docker agent. The agent is what actually runs the schedule — QuickStart never sits in the traffic path.
Verify results in the "Database editor"
Because scheduled runs are headless, the way to check the output is to open the target dataset directly and inspect the rows that piled up.
- Open Data > Database from the left menu.
- Click the dataset card that the parser rule is linked to — this opens the Database editor.
- Pick the target table from the left table list (e.g.
items,products, etc.). - Use WHERE / ORDER BY at the top to bring recent rows to the top (
ORDER BY created_at DESC,ORDER BY id DESC) and inspect what the last scheduled run added. - A quick row count (COUNT) or a date-range filter is enough to sanity-check trend — if the count grows each interval, the schedule is healthy.
The run log itself is shown as a table in the Run modal's right-panel "Results" tab when schedule mode is active, but for content verification of the actual harvested data, the Database editor is always the source of truth.
Automation Macro
Write and execute server-side scripts to automate repetitive tasks.
- {{ item }}
Open Data > Macro from the menu. Left sidebar with Recent / Community / My macros sections; body is Grid/List view. The top toolbar supports search by name or description.
Click the sidebar's [+ New Macro] button to open the create wizard immediately.
[+ New Macro] opens a 4-step wizard. This single wizard covers both registering the macro's base info and preparing its runtime server.
- Step 1 — Macro intro: A "What is a Macro?" intro with four feature cards (Pipeline Chaining, Adapter Pattern, Input → Output, Code Gen) and a flow diagram showing four supported topologies (DB Query · Chaining · Parser · Scheduler). No input — press [Next].
- Step 2 — Connection method: Prepare where the macro will actually run. Two options:
- Deploy new macro server — Connect your Railway account (paste token), then pick language · framework · core stack · optional addons (MongoDB / FFmpeg / Puppeteer / WebSocket, etc.) · DB credentials. Clicking [Deploy server] runs a 6-step pipeline (Receive → Decrypt → Docker build → Deploying → Network → Verify) and your account gets a dedicated macro runtime.
- Connect existing macro server — If you already have a server running your macro code, enter its connection info to attach to it.
- Step 3 — Type selection: Pick one of 24 macro types (ETL pipeline · Batch API · Data migration · CSV/Excel import · and more). Starter code matching the type — with input parameters, loop scaffolding, and output structure — is auto-generated as a starting point for the next step.
- Step 4 — Register: Enter a macro name (e.g. "Nightly DB sync", "Bulk translate") and a short description, then press [Create]. The macro is saved, the wizard closes, and the detail view (code editor) opens automatically.
A step bar at the top tracks progress; [Back] returns to a previous step (disabled while deployment is running). The wizard closes only via the top-right [x] button.
When the wizard closes, a 3-pane editor opens: on the left, the input-field definition; in the center, the code editor with PHP / Node.js / Python tabs; on the right, the AI Prompt pane. The editor is pre-filled with a scaffold for the macro type you chose in Step 3, so you usually just edit the important parts.
- [1] Receive run_datainput_data
conn_string
table_name · user_id - [2] Normalize inputsarray → object
Type cast
Defaults - [3] Core logicAPI · DB
Files · shell
Data transforms - [4] Assemble resultsuccess flag
data / json
download_links - [5] ReturnMatch the
output type
picked in wizard - [6] AI PromptRight pane
Pick a scenario
AI → paste code
The variable you automatically receive — run_data
Your function always takes a single argument called run_data. The server fills it in just before running, and it carries at least these keys.
run_data.input_data— the values the user typed into Quick Test or the scheduler. It first arrives as an array of{ item_name, item_value, item_type }entries, so the first job of every macro is to flip it to a plain key/value object.run_data.conn_string— DB connection string of the dataset you picked in the wizard (AES-decrypted by the server). DB-oriented macros use it as-is.run_data.table_name,run_data.file_name— target table / file name from the wizard.run_data.user_id,run_data.app_id— the caller and the macro id. Handy for logging and permission checks.run_data.save_type,run_data.app_type— the save mode and macro type selected in the wizard. Use for branching.
Recommended coding pattern
This is the minimal skeleton even a hobbyist developer can copy straight. Keep the function name you set in the wizard (e.g. macro_run) — the server calls it by that exact name.
Node.js example — distilled from the real _sample/code39.js:
async function macro_run(run_data) {
// ── 1) Normalize inputs — accept both array and object ──
const raw = run_data.input_data || {};
const params = {};
if (Array.isArray(raw)) {
raw.forEach(f => { params[f.item_name] = f.item_value; });
} else {
Object.assign(params, raw);
}
// ── 2) Defaults · type casting ──
const output_format = params.output_format || 'svg';
const style = params.style || 'default';
const max_items = Number(params.max_items || 10);
// ── 3) Core logic ──
try {
// ... API call, DB query, file transform, etc.
const results = [ /* collected results */ ];
// ── 4) Build result & return (success) ──
return {
success: true,
data: results, // array renders as table
message: results.length + ' item(s) processed',
};
} catch (e) {
// ── 4') Failure uses the same shape ──
return { success: false, error: e.message, data: [] };
}
}PHP / Python follow the same shape — a function taking run_data and returning ['success' => true, 'data' => [...]] / {'success': True, 'data': [...]}. Define your fields in the left Input pane, then press the scaffold button in the center pane's header — the tool generates a language-specific skeleton that already unpacks every declared field for you.
The return shape follows the output type you picked in the wizard
The return protocol is the same for every macro, but which fields you fill depends on the output form you chose in Step 3 of the wizard. The Quick Test result panel looks at those fields to decide how to render.
success: true/false(required · all macros)data: [{...}, {...}]— when output type is "table / grid". The panel auto-detects columns and renders a table.json: {...}— when output type is "JSON / raw". Rendered in a JSON viewer (textarea + copy button).download_links: [{ url, name, size }]— when output type is "file download". Rendered as a list of download buttons.message(success) /error(failure) — text block (<pre>). Safe to include alongside any of the above.
You can fill multiple fields at once — e.g. show a data table and also hand over a CSV via download_links (the real code39.js returns data + download_links + message together).
Getting code from AI — the right pane
When the logic gets tricky or an external library feels unfamiliar, ask for help from the "AI Prompt" pane on the right.
- First, define the required input fields (name, type, description) in the left Input pane. This definition is baked into the prompt automatically.
- Click a scenario badge at the top of the right pane (examples tailored to your macro type — e.g. "Scrape a URL and INSERT into DB", "Migrate table A → B") and the scenario template fills the prompt textarea.
- In the textarea, add specifics (which URL, which columns, which edge cases to handle, etc.).
- Click the header's copy button to copy the whole prompt, paste it into ChatGPT / Claude / Gemini, and run.
- Paste the AI's code into the center editor and press Save.
- Jump to Step 4 (Quick Test) and iterate.
Combine the scaffold button () with the AI Prompt and the code you actually have to write shrinks down to just the core-logic lines.
console.log(params) / print($input_data) line shows the actual received values — they stream straight into the terminal pane below.
Switch to the Quick Test tab (🧪 flask icon) at the top of the left pane. Quick Test runs the code through the macro server you prepared in Step 2.
- Fill in the input parameters row by row.
- Click [Run] → "Running..." spinner.
- Result display depends on the return shape:
data→ tablejson→ JSON viewerdownload_links→ list of download buttonsmessage/error→<pre>text block
Stdout and stderr stream into the terminal pane below in real time — great for debugging.
success in the return object.
Once Quick Test looks good, hand the macro off to a schedule for unattended execution. In the detail view's Schedule section, two values are all you need.
- Start time (offset) —
HH:MMformat (e.g.00:00= midnight,03:30= 3:30 AM). This is the anchor for the repeating schedule. - Interval N (minutes) — the macro runs every N minutes from the start time. Enter
5for every 5 minutes,60for hourly,1440for once a day. - Active toggle — pause or resume without losing the config.
Examples: start time 00:00 + interval 5 → runs every 5 minutes from midnight (00:00, 00:05, 00:10 …). Start time 09:00 + interval 1440 → runs once a day at 9 AM.
Once saved, the macro server runs this macro on this cadence on its own. QuickStart only signals — actual execution and traffic live on the macro server. (There are no cron expressions — start time + interval is all the scheduler uses.)
Database
Create and manage databases with automatic REST API generation.
- {{ item }}
Open Data > Database from the menu. Left sidebar has a blue [+ New Dataset] button and Recent / Public / My / Team sections; the body is Grid/List view cards.
Each card's four icons: ▶ (DB editor) · table (cell editor) · (API settings) · copy/delete.
[+ New Dataset] → wizard modal.
- Step 1 — three connection options: Deploy new DB (Railway) · Connect existing DB · Local file (JSON/CSV/Excel). DB type dropdown (MySQL 3306 · MariaDB 3306 · PostgreSQL 5432 · MongoDB 27017) · host · port · DB · user · password → [Test connection] verifies the credentials reach the database.
- Step 2 — on success, pick a table; its fields expand.
- Step 3 — register the dataset: name · description · table · PK · columns (
*or comma-separated) · WHERE · LIMIT · ORDER BY · shared. The right panel's [Test query] previews results; then [Save].
Click the ▶ (play) icon on a dataset card to open the full-screen editor, which has three panels.
- Left — tabs (Tables/Views/Procedures/Functions), table structure inspector, command icons (Copy CREATE · Drop · Update · Insert · Delete · Join · Reverse · Refresh).
- Center — multi-tab SQL editor. ▶ Run or F5/F9. Export as TSV/CSV/JSON/SQL, or send straight to a macro with "Send to Macro".
- Right — result grid with cell-level editing.
Click the API settings button (plug icon) on a card and the API settings modal opens.
- Basics: Namespace (required, URL tail) · Table · JOIN Table · Page var (default
page) · Per Page (50) · cache (0–1440 min). - [Auto generate] → assembles the JSON shape (main_container → main_fields → item_container → item_fields → detail). Each field is a "JSON key → SQL variable" pair.
- [Save] → [Deploy] activates the endpoint.
Endpoints go live at GET https://happycat.apidealder.net/endpoint/{namespace}. The modal's ACL section locks them down.
- API Key (auto-generate button · header/param delivery · header name
X-API-KEY) - IP whitelist — wildcards / CIDR
- Referer restriction — allowed domains
- Rate limit — max req/min
Example: curl -H "X-API-KEY: ..." https://happycat.apidealder.net/endpoint/menu_list
Remote Management
Open, edit and manage files on your deployed server from the browser — no FTP or SSH client needed. Folder browsing, code editing, uploads, and a live shell all share the same screen.
- {{ item }}
Remote Management is split into four zones. Know where to look before you start clicking.
- Left server list — every domain you're managing, each with a small status dot. You can collapse this panel to just icons when you need more room.
- Center file area — the file browser for the selected server. The toolbar at the top holds the path bar, sort buttons, and the terminal toggle; the folder content below expands into columns as you drill in.
- Bottom action bar — Upload · New folder · New file · Download · Delete. Buttons light up only after you pick a file or folder.
- Terminal panel — a console that slides up from the bottom on demand. Use the terminal icon in the top toolbar to show/hide it.
Click a domain in the left list. The dot next to the domain name tells you its current state:
- Green dot — online. The file list opens immediately.
- Gray dot — offline. The container may be sleeping or the network may be blocked.
- White dot — still checking, or the status is unknown.
If the list is empty you'll see a "Deploy a server first" prompt with shortcut buttons to the single-file, project, and database deployment screens.
The center area is a column-style browser — each folder you click expands into a new column on the right. Up to four columns are visible at once; deeper paths collapse the leftmost column automatically.
- Path bar — the house icon jumps back to the root (/), and each slash-separated segment above is clickable to jump to that exact spot.
- Path input — type a full path such as
/var/www/html/storage/logsand press Enter to jump straight there without clicking through. - Sort buttons — name · size · modified time. Press the same button again to flip the order.
- Selecting — a single click selects one item, Shift+click picks a range, Ctrl/⌘+click adds or removes items one by one. Once more than one item is picked, an "N selected" badge appears in the top-right of the action bar.
Click a file once to select it. Click it a second time and it opens — the right view pops up automatically based on the file type.
- Text / code files → a syntax-highlighted editor opens in the center. HTML, PHP, Vue, CSS/SCSS, JavaScript/TypeScript, JSON and more are detected automatically.
- Images (PNG · JPG · GIF · SVG · WebP · BMP · ICO) → open in a preview viewer so you can confirm them visually.
- Binary / executable files trigger a "Cannot edit binary file" message and don't open.
- The [Save] button in the top-right of the editor pushes the change to the server on the spot — no redeploy needed. Esc or [Cancel] closes without saving.
- Only files up to 10 MB can be opened in the editor; larger files show a "too large" notice instead.
.env, config tweaks, or log inspection, editing right here is the fastest path. Saves go live the moment you hit Save — no full redeploy required.
Combine the bottom action bar with the terminal panel to get actual work done.
- Upload archive — drag or click to pick a .zip · .tar · .tar.gz · .tgz file. A preview of the archive contents appears; once you hit Start Upload, the file is sent in 1 MB chunks with a percent bar, and the current folder auto-refreshes when it finishes.
- Upload file — pick one or many files at once and they're uploaded as-is into the current folder (no extraction).
- New folder / New file — prompts for a name. Letters, digits, dot, hyphen, and underscore only.
- Download — files download as-is; pick a folder and it's zipped into a single ZIP automatically.
- Delete — confirms once; with multiple items selected, all of them go in a single operation.
- Move / copy — drag a file onto a folder and a confirm dialog opens. Or press Ctrl+X/Ctrl+C to stash a selection, then Ctrl+V in a different folder to paste with the same confirm dialog.
- Terminal — the terminal icon in the top toolbar slides up the bottom panel and connects you to the selected server's shell. Type a command and press Enter — stdout shows in white, stderr in red. ↑/↓ recalls previous commands, and the current working directory is tracked for you, so after
cd some/paththe next command runs from there.
/bin/sh is the default shell — not bash. Install new packages with apk add package-name.
AI Prompt Guide
QuickStart doesn't bundle an AI and query it directly. Instead, AI Prompt buttons throughout the product capture the context you're looking at (table schema, HTML sample, layout structure, etc.) and copy a structured prompt to the clipboard. Paste it into an external AI such as ChatGPT, Claude, or Gemini — the adjacent Import button then applies the response back into the UI. The prompt is already scaffolded for the task, so you don't have to figure out what to describe.
VSCode Extension
A VS Code extension for working on your QuickStart project locally in the editor of your choice. Download the project as a package from the web console, open the folder in VS Code, and everything that follows — auto-authentication → automatic Laravel / frontend setup → file editing → deploy to other servers → two-way sync between the web and the editor — happens inside a single side panel (QUICKSTART at the bottom). Walk through the steps below once and the rest becomes button clicks.
40-Language Translation
A tool that translates every on-screen phrase (words and menu labels) of one project into many languages at once. It scans your project pages for translatable terms, assembles the AI prompt for you, pulls the AI's JSON response back into the grid automatically, persists the result into the project's translation store (project_translate table), and finally exports a Laravel-ready lang_files.json. The goal — scale to 40 languages in a single cycle — is designed so that even a first-time user can walk through the steps below.
Solution Market
Browse and fork projects, macros, and single files created by other users to start your own.
- {{ item }}
Fork & Share
Share your projects and fork others' to get a head start.
- {{ item }}
Domain Management
Manage free domains provided by QuickStart.
- {{ item }}
Build Your First Website
A step-by-step walkthrough of a small restaurant reservation page from the first click to going live — with exact button locations and the order of events so a complete beginner can follow along. When done, visitors can pick a date, time, and party size and submit a real reservation.
After signing in, open the top navigation or dashboard and click Services → Single File. The screen is split into a top toolbar and the body:
- Top toolbar — left side: History · Guide · Title input · Save (💾). Center: Template dropdown. Right: Share · Run ▶ · Deploy 📦.
- Center editor — four tabs at the top:
prompt · html · scss · vuejs. Click to switch. - Right preview panel — renders when you press Run.
Open the template dropdown in the center of the toolbar and choose "Restaurant Booking System". The sequence is:
- The moment the dropdown value changes, the selected template is automatically applied.
- All four tabs (prompt · html · scss · vuejs) are auto-filled with the pre-built code plus the AI prompt used to regenerate it.
- The active tab switches to prompt by default — that text is what the AI uses if you ask for a regeneration.
- Click Run ▶ in the toolbar and the right preview renders a 3-column reservation screen (calendar / time slots / reservation form).
Note: this template is an operator screen for the shop owner to manage dates, time slots, and table availability — not a simple visitor-facing menu landing page.
This template is customized in two tiers: a Settings modal (no code needed) and direct code edits. The entry point is the ⚙ Settings icon next to the theme toggle (☀/🌙) at the top right of the rendered page.
A. Settings modal — data only, no code
- Click ⚙ → a full-screen overlay opens with a centered modal (4 tabs).
- Time Ranges — adjust morning / lunch / dinner start and end times with number inputs. A visualization bar at the top reflects color segments live. If start == end, the segment shows "(inactive)".
- Time Slots — pick a step (10 / 30 / 60 / 120 min), then toggle individual slots active/inactive in the grid. Active/inactive counts are shown at the top.
- Tables — list with inline rename + delete, and an input at the bottom to add tables. This list drives the "Table" select in the reservation form.
- Holidays — recurring off-days (Sun–Sat, 7 toggle buttons) + specific holidays (date input + reason text, add/delete list). Reasons only show inside settings, never on the public screen.
B. Code edits — shop name, theme, etc.
- html tab — replace the header title string
"레스토랑 예약"with your shop name. Use Ctrl+F to locate it. - vuejs tab —
mounted()contains mock-data generation (D+1 ~10%, D+2 ~5%, D+3 ~2% random reservations + a Korean names array). For real use, empty that block or replace it with a server API call. Public holidays are fetched fromhttps://date.nager.at/api/v3/PublicHolidays/{year}/KR— swapKRfor another country code if needed. - scss tab — the theme uses CSS custom properties, not SCSS variables. Defined under
.reservation(light) /.reservation.dark(dark):--primary(brand accent),--bg(page background),--card-bg,--text/--text-sub,--border,--holiday(public-holiday red),--closed-bg(shop holiday amber),--occ-bg/--occ-border(slot with seats left). Editing just these shifts the whole look consistently.
After editing: Save (💾) → Run ▶ to refresh. Unsaved tabs show a small dot (●).
mounted() localStorage load + a watcher that saves changes, or graduate to the Project service (PRO) to store in a real database.
Now try booking one reservation yourself, as if you were a customer. This matches exactly what your staff or visitors will do after going live. Follow this order inside the preview:
- Pick a date on the calendar (left side) — click any date from today onward. Red days are public holidays, amber days are specific closures you set, and dimmed days are regular days off — those can't be clicked. Days that already have reservations show a small number like "+2" in the corner so you can see bookings at a glance.
- Pick a time (middle) — once you choose a date, the available times appear as rounded buttons. The number on each button, like "2/5", means "2 already booked / 5 tables total". Light shade = plenty of seats, dark = mostly taken, strikethrough = fully booked and not clickable.
- See who already booked — clicking a time button opens a list below showing the existing reservations for that time (guest name, table, party size). This prevents you from double-booking.
- Fill in the form (right side) — your chosen date and time appear as a summary at the top. Then fill the fields from top to bottom:
- Guest name
- Phone: just type digits, it auto-formats to "010-1234-5678"
- Table: tables already taken at this time are automatically hidden, so you can't accidentally double-book
- Party size: 1 to 20 people
- Memo: special requests (birthday, wheelchair access, etc.)
- Click the [Reserve] button — if you left the name empty, a warning appears. Otherwise a "Reservation complete" confirmation pops up, and the "+N" number on the calendar and the "N/M" number on the time button both go up by 1 instantly. The form clears itself and is ready for the next booking.
- Try both the light and dark theme — click the ☀/🌙 icon at the top right. Your shop might be used in bright daylight or a dim evening, so check that everything reads well in both.
To check phone and tablet views, just drag the browser window narrower with your mouse. As the screen gets narrower, the 3 columns automatically rearrange into 2 columns and finally stack as a single column. Since staff often use tablets and customers use phones, make sure text and buttons stay large enough to tap on narrow screens.
Deployment uses Railway, a hosting provider. The first time you click the Deploy button, a "Connect Railway account" modal appears. The sequence is:
- Click Log in with Railway → Railway's login page opens in a new tab.
- No Railway account yet? Sign up free on that page (email or GitHub).
- On the "QuickStart requests permission to deploy" screen, click Authorize.
- You're redirected back to QuickStart and a "Connected" toast appears.
You only do this once — subsequent deploys skip this step.
With the account connected, click Deploy again. A progress modal opens and walks through 8 stages — each turns green when complete.
- Pack — bundle your code into a package.
- Upload — send the package to Railway.
- Install — install required libraries.
- Build — compile SCSS and bundle Vue.
- Migrate — place static files in their web-server location.
- Start — boot the container.
- Health — verify the site actually responds.
- Complete — finalize and assign the URL.
Total time is usually 1–3 minutes. Expand Show logs at the bottom of the modal to watch in real time.
When the deploy finishes, an Open domain button appears at the bottom of the modal. Click it and the auto-assigned free domain (e.g. happycat.apidealder.net) opens in a new tab. Share that URL with anyone.
Later, to attach your own domain (e.g. myname.com), go to Settings → Domain Management in the dashboard, register the custom domain, and add the DNS records shown there to your DNS provider.
Build an API Server
Turn data from your own database into a public API anyone can call. Share a single URL like GET https://happycat.apidealder.net/endpoint/menu_list and mobile apps, other websites, or spreadsheets can pull data from it directly. This walkthrough mirrors the real buttons and modal order you'll see on screen.
From the top nav or dashboard, click Services → Database to open the database page. The screen splits into a left sidebar and a center body.
- Left sidebar — a blue [+ New Dataset] button at the top, followed by "Recent", "Public datasets", "My datasets", and "Team" sections.
- Center body — top toolbar has a search box (name / table / URI), a grid⇄list view toggle, and a rows-per-page selector (20/50/100). Below that your existing datasets appear as cards.
- Four icons on each card — ▶ (play) opens the Database Editor · table icon opens the Cell Editor · API settings button (plug icon) opens API Settings · plus copy/delete. Double-click the card name for inline rename.
Click the [+ New Dataset] button in the left sidebar and a 3-step wizard modal opens in the center. The flow:
- Step 0 — Overview: explainer cards about datasets and capabilities. Click Next to continue.
- Step 1 — Connection method: choose one of three large options.
- Deploy new DB — provisions a fresh DB container on Railway.
- Connect existing DB (most common) — connect to a DB you already have.
- Local file — upload a JSON / CSV / Excel as a dataset.
- For "Connect existing DB":
- DB type dropdown — MySQL (default port 3306) · MariaDB (3306) · PostgreSQL (5432) · MongoDB (27017). Selecting one auto-fills the default port.
- Host · Port · Database name · User · Password
- Click [Test connection] at the bottom — on success the wizard auto-advances to Step 2; on failure a red error shows below.
Once connected, the wizard walks you through two more steps automatically.
Step 2 — Table selection
- Tables in the DB appear as rows (name · icon · row count · comment).
- Click a table and the right panel expands to show its field list.
Step 3 — Register the dataset (this is where the "dataset" metadata is finalized)
- Left — registration form:
- Dataset name (required) — e.g. "Menu list"
- Dataset description
- Target table dropdown (required)
- Primary Key field — auto-selects
idif present. - Included columns —
*(all) or comma-separated likeid,name,price - WHERE clause — e.g.
stock_flag = 1 - LIMIT — e.g.
0,100(offset 0, 100 rows) - ORDER BY — e.g.
created_at DESC - Shared checkbox — expose read-only to other users.
- Right — query tester: clicking [Test query] runs the actual SQL with your current settings and shows result row count, column count, and a live preview. Tune the left-side conditions until you see what you want.
- Click [Save] → wizard closes → a new dataset card appears on the main screen.
Click the ▶ (play) icon on a dataset card to open the Database Editor as a full-screen overlay. It has three panels.
- Left — object browser: tabs at top (Tables / Views / Procedures / Functions). Click any table to see columns · types · comments in the inspector below. The command strip above the list covers Copy CREATE script, Drop, Update, Insert, Delete, Join, Reverse, Refresh.
- Center — SQL editor: manage multiple queries as tabs. Double-click a tab to rename. The toolbar has a ▶ Run button plus F5 / F9 shortcuts. Results can be exported as TSV / CSV / JSON / SQL, or sent straight to a Macro with "Send to Macro".
- Right — result grid: rows from the last query, with cell-level editing.
Use this step to confirm that the data you're about to expose actually looks the way you want. Fix it here first if it doesn't.
UPDATE ... WHERE id=... explicitly in the SQL tab is safer and leaves a clearer trail.
Now expose this dataset as a REST API. Click the API settings button (plug icon) on the dataset card to open the API Settings modal.
- Basics
- Namespace (required) — this becomes the URL tail.
menu_listproduces/endpoint/menu_list. - Table — target table (auto-filled from the dataset)
- JOIN Table — optional second table if you want to join
- Page var — pagination query param name (default
page) - Per page — default 50
- Cache time — 0–1440 minutes
- Namespace (required) — this becomes the URL tail.
- Auto-generate response: clicking [Auto generate] builds the JSON shape as
main_container → main_fields → item_container → item_fields → (optional) detail. Each field is a "JSON key → SQL variable" pair (e.g.name → $customer_name). You can add or remove fields manually. - Access control (ACL) — detailed below.
- Click [Save] to store the API definition.
- Click [Deploy] to run the deploy pipeline — a progress bar appears, and the endpoint goes live when it finishes.
Once deployed, the endpoint is public under (with a custom domain):
GET https://happycat.apidealder.net/endpoint/menu_listGET https://happycat.apidealder.net/endpoint/menu_list?page=2GET https://happycat.apidealder.net/endpoint/menu_list/csv— CSV download
API Key auth (ACL section inside the API modal):
- API Key — click [Auto-generate] for a UUID-style random key.
- Delivery —
headerorparam. - Header name e.g.
X-API-KEY/ Param name e.g.api_key.
Call examples
Via header:
curl -H "X-API-KEY: your-secret-key" https://happycat.apidealder.net/endpoint/menu_list
Via query param:
curl "https://happycat.apidealder.net/endpoint/menu_list?api_key=your-secret-key"
Browser fetch:
const res = await fetch('https://happycat.apidealder.net/endpoint/menu_list', { headers: { 'X-API-KEY': 'your-secret-key' } });
const data = await res.json();
Extra guards (all in the ACL section):
- IP whitelist — wildcards (
192.168.1.*) and CIDR (10.0.0.0/24). - Referer restriction — list of allowed domains.
- Rate limit — max requests per minute.
Automate Data Collection
Build a pipeline that scrapes an external website on a schedule and piles the data into your DB (shopping sites, news, price comparison, etc.). Set it once and fresh data arrives every night — ready to be consumed by the API you built in the previous chapter, or by the Layout Builder.
From the top nav or dashboard, click Services → Data Collection to open the parser rules list screen. The layout mirrors the Database page.
- Left sidebar — a blue [+ New Parser Rule] button at the top, then "Recent", "Public rules", and "My rules" (with a user filter).
- Center body — toolbar with search, grid/list toggle, pagination. Below, your existing rules show as cards (or table rows).
- Icons on each card — ⚗️ (test tube) Item Test · ⏱ (clock) Schedule (shows a "Max" ribbon if your plan doesn't include it) · edit · duplicate · delete. Cards display rule name, test page, description, and creation date.
Click [+ New Parser Rule] in the left sidebar → a 3-step wizard opens.
- Step 1 — Overview: four info cards (Extract / Crawl / Field Mapping / Reuse) and a pipeline diagram (Parser Rule → Database / Macro / Scheduler / API). No input, just context.
- Step 2 — Database connection: pick a dataset from a card list where the scraped data will land. Each card shows dataset name, DB type, table, and domain. After selecting, press [Next] — a 3-phase auto flow runs ("Agent connect → Parser engine deploy → Deploy complete") that installs the parser engine onto the selected docker agent.
- Step 3 — Rule registration:
- Rule name (required) — e.g. "Naver News IT section"
- Description — one line about what it collects
- Click [Create Rule] and the wizard closes, landing you directly in the parser settings screen.
The rule editor opens with a Target URL field at the top. Enter the page you want to scrape (e.g. https://news.example.com/it), then configure extraction. The parser combines three approaches.
- Loop Splitter (3 inputs — primary + 2 secondary) — a string pattern that chops the HTML into repeated units. Example: use part of
<li class="article">as the splitter so each article becomes one item. - XPath selectors (up to 3 levels) — pick title / URL / image from inside each repeated unit with XPath. The selector should point at a node set (array), so if the value sits at
//h3/a/text(), enter just//h3/a. - JSON selectors (3 levels) — if the page returns JSON, use dot/bracket syntax to point at the array path. For data shaped like
data.items[0].title, enterdata.itemsso the item array is produced. - Function post-processing — the "function" column applies to each extracted value:
trim(@p)— strip whitespace (@pis the current value)replace(old,new)/regex(pattern,replacement)- Direct PHP calls like
strtoupper(@p) - Built-in helpers:
get_data()·slice()·remove()·map()
The fastest path isn't hand-typing selectors — it's feeding a slice of the source (via the Loop Splitter) into the AI Prompt and letting the AI response auto-register the rule. That's exactly what Step 4 below covers.
Instead of hand-typing dozens of selectors, you can hand the sample to an AI and apply the completed rule it returns. This is the recommended path for beginners.
Prerequisite — you must have entered a Target URL in Step 3 and run the extract test from the editor's "Test" tab at least once so a response body exists. That body auto-joins the prompt.
A. Build & copy the prompt
- In the test result panel, click the highlighted 🪄 "AI Prompt" button (wand icon) at the top.
- The document type (HTML / JSON / XML) is auto-detected and the body is extracted and assembled into a prompt.
- The code editor panel just below the button fills with a markdown-formatted prompt. It includes:
- A task intro paragraph
- The HTML/JSON source sample
- Target definitions — the repeat delimiter, the detail-URL field, the unique key, and each column's label, variable name, type, split rules, and post-processing function
- A sample JSON and an explicit "Do not output any text other than JSON" instruction
- The prompt is multilingual-aware (8 languages: Korean · English · Japanese · Chinese · Russian · German · French · Spanish) — a Korean document produces Korean labels, a Chinese one produces Chinese labels, and so on.
- Click inside the panel → Ctrl+A → Ctrl+C to copy everything.
B. Paste into your AI of choice and run it
- Paste into an AI such as ChatGPT / Claude / Gemini and send.
- The AI responds with a rule JSON.
- Copy the response (or just the JSON portion).
C. Paste the response to auto-fill rule fields
- Back in the same panel, click the 📥 "Import Pattern" button (import icon) — a paste-in textarea opens (the expected format is hinted inside).
- Paste your JSON, then click [Apply Pattern].
- The repeat delimiter, selectors, unique key, and detail-URL field are mapped into the top of the rule automatically, and every column (label, variable name, type, split rules, post-processing function) is filled into the field list in one shot. Duplicate variable names get a different name automatically to prevent collisions.
- The editor auto-switches to the "fields" tab so you can verify immediately, and a summary toast like "Pattern applied: N fields" appears at the bottom.
With the selectors roughly in place, verify they extract what you want. Two entry points:
- The ⚗️ icon on a rule card
- Or the "Test" tab at the top of the rule editor
The Item Test modal opens with:
- Top status bar — "N items / M columns" summary. If N is 0, the Loop Splitter is wrong — fix it first.
- Export buttons — CSV · XLSX · JSON · HTML, handy for sharing a sample with the team.
- Result grid — Row# + column headers auto-derived from the first item, one row per extracted item.
- Cell hover — a "Copy" button appears on hover to grab the value to clipboard.
If results look wrong, close the modal, adjust selectors/functions, and test again — this loop is ~70% of parser work.
Once the test looks clean, confirm the save settings in the editor's "Save" section.
- Save type dropdown — set to "Database" (auto-set already if you picked a dataset in the wizard).
- Target table / collection name — where rows land. If it doesn't exist, the agent creates it on the first run, using columns detected in your test.
- DB mode — Dataset (linked) / Custom. Custom lets you type host · user · password · database directly (useful when writing into a different DB than the one in the wizard).
What happens on run
- You run the rule (the "Persist" button in the test, or the next step's schedule) and the docker agent hits the target URL.
- Items are extracted: Loop Splitter → XPath/JSON selectors → function processing.
- Extracted items are inserted into the target table. Duplicates (by URL hash or the key you pick) are skipped or updated automatically.
- Because this table lives in the same DB as the dataset card from Step 5, the API endpoint
/endpoint/...you built before now serves the freshest data.
The last step makes it run by itself. Click the ⏱ (clock) icon on a rule card to open the schedule modal. This feature is MAX-only — on other plans the icon shows a "Max" ribbon.
- Schedule fields:
- Start time — hour (0–23) + minute (0–59). e.g. 03:30 AM.
- Interval (minutes) —
60= hourly,1440= once a day. - Active — toggle. Off keeps the config but pauses runs.
- Run mode — Single URL mode (one target URL) or Batch mode (loop through a URL list, one per line).
- Click [Save] — the schedule is recorded in QuickStart and auto-synced to the selected docker agent, which is what actually runs it.
- From then on the agent fires the rule on your interval and pipes rows into the dataset. QuickStart only signals — it never sits in the traffic path, so there's no bandwidth overhead on it.
Chaining with a macro (optional) — in the editor's flow diagram, use the "Select macro" dropdown to pick a macro. Right after a scrape finishes, that macro runs. Example: compare newly scraped product prices to yesterday's; if dropped by N%, send a Slack alert.
60–1440 minute intervals are the realistic sweet spot between politeness and freshness.
Database Migration · B → A → C Replication
Build a three-stage replication pipeline that pulls data from an external source DB (B), stages it inside your own dataset (A · Docker), and then pushes it out to another external target DB (C). A single Migration button on the dataset list handles both the inbound and outbound half, while the A layer lets you clean columns, rewrite URLs, and aggregate in between.
Pushing straight from the production DB (B) to the analytics DB (C) looks simplest, but in practice column names differ, personal data is mixed in, and time zones diverge — you always end up needing a place to clean things up in between. That is exactly what a QuickStart dataset (A) is for.
- B (external source) — the live shop or ERP. Touching it risks the business, so we only read.
- A (your dataset · Docker) — your own workspace. All transformations happen here: rename columns, rewrite URLs, drop unwanted fields, add aggregates.
- C (external target) — the BI database, a partner DB, any destination. Only the already-clean data from A flows into C.
Why this shape:
- B and C can run different engines (MySQL ↔ PostgreSQL …) — A bridges them.
- Everything stays in A, so if C is wiped you simply re-push. Rollback is cheap.
- You can iterate and test transformations in A as much as needed, and only flip the switch to C when ready.
First create the dataset (A) that will hold the data pulled from B.
- Top nav → Data → Database. The list screen opens.
- Top-right [+ New Dataset]. Fill in:
- Name — e.g.
replication_staging - DB type —
MySQLorPostgreSQL. Matching B reduces conversion friction. - Host — defaults to the DB bundled with your Docker agent (auto-filled).
- Database name — e.g.
my_staging
- Name — e.g.
- Click [Save]. A new row appears with icon buttons alongside: 🔌 connect test · edit · migration · export.
- Click 🔌 first and confirm you see "Connection success". You must get this before moving on.
A is now the intermediate buffer where data imported from B and data to be exported to C will briefly live.
hard_sync will copy B's schema into A automatically. On the other hand, if you want a completely different structure in A, create the tables manually in the SQL editor now and plan to use append in step 5.
Find the row for A in the list and click the Migration icon. A large three-panel modal opens.
- Deck A (left) — your dataset (
replication_staging) is pre-bound; current tables and fields show immediately. - Center toolbar — direction indicator (A → B / B → A), [Flip] button, and the action list (⚡ hard_sync, 🔄 soft_sync, ➕ append …).
- Deck B (right) — a form for entering the remote DB connection.
The default direction is A → B (push out), but we want to pull from B, so click [Flip] in the center to switch to B → A. Deck B's badge turns to "source", Deck A's badge to "target".
Now enter the external production DB (B) connection on Deck B:
- Host — e.g.
origin.acme.comor10.0.1.23 - DB type —
MYSQL·POSTGRESQL·MONGODB·ELASTICSEARCH - Database name — e.g.
sales_db - Account / password — strongly prefer a read-only account with SELECT only. You cannot corrupt B with it.
- Click [Test Connection]. "Connection success" appears and the remote table list auto-loads.
Access denied for user 'xxx'@'1.2.3.4', forward that exact IP — it is what the target server sees.
After a successful connection Deck B shows the remote table list and a [Next] button appears. Clicking it flips Deck B from "connection" to "table selection" view.
- Select tables — check the tables to bring over. [All tables] toggles the whole list. Starting small (
orders · customers · products) is safer than pulling the entire schema on first run. - Filter (optional) — the WHERE textarea at the bottom of Deck B accepts conditions like
created_at > '2026-01-01'. LIMIT0, 1000pulls only 1000 rows as a sample. Always cap the first run. - Inspect fields (optional) — the icon next to a table opens the column list; uncheck any field you do not want copied (
password_hash,national_id…). - Run ⚡ hard_sync — in the center toolbar, click [hard_sync] (the lightning icon). A "Run hard_sync on {count} tables?" dialog appears; confirm. On the A side the tool does DROP → CREATE → INSERT per table. A progress bar shows current table / total tables plus row-level progress.
- When it finishes the bottom log reads "Success" and Deck A's table list refreshes, now showing the newly created tables.
Other options instead of hard_sync:
- 🔄 soft_sync — keyed UPDATE/INSERT/DELETE only; keeps rows already in A that were not in the source set. Good for periodic sync.
- ➕ append — insert rows whose id does not yet exist in A. Useful for incremental ingest.
- 🔀 merge — insert only rows whose id does not clash with A.
The raw data is now in A, but sending it straight to C usually breaks something. There are two ways to clean it up.
① Replacement inside the Migration modal — the center toolbar has a "Replacement setup" area that performs bulk string substitution. If B uses https://cdn-old.acme.com/ for images and C expects https://cdn.acme.com/:
- Pick [Text] mode (or [Regex] for patterns).
- Left textarea:
https://cdn-old.acme.com/ - Right textarea:
https://cdn.acme.com/ - On the next hard_sync / soft_sync the value is rewritten on the fly as rows move. The source never changes.
② Work directly in the SQL editor — back on the dataset list, click the editor icon for A and run SQL.
ALTER TABLE orders DROP COLUMN password_hash;— strip sensitive columnsUPDATE orders SET created_kst = CONVERT_TZ(created_at, 'UTC', 'Asia/Seoul');— time-zone conversionCREATE TABLE orders_summary AS SELECT product_id, COUNT(*) cnt, SUM(amount) total FROM orders GROUP BY product_id;— build an aggregate table
Verify with SELECT * FROM orders_summary LIMIT 20; in the editor before moving on to step 6.
Now push the cleaned data from A out to the external target (C). Open the Migration modal from A again.
- Check direction — the center toolbar must read A → B, where B in the UI is now our C. If step 3 left it on B → A, click [Flip] to reverse it: Deck A is now source, Deck B is target.
- Enter target connection on Deck B (= C) — host
warehouse.acme.com, DB typePOSTGRESQL, namereporting, and a writable account with INSERT/UPDATE. [Test Connection] → success. - Pick tables on Deck A — check
orders_summary · products · customers_clean— whichever tables you already prepared. - Choose the action.
- If C is brand new, use ⚡ hard_sync; missing tables are auto-created.
- If C already has data and this is periodic sync, use 🔄 soft_sync; keyed UPDATE/INSERT/DELETE against C.
- If C just accumulates history, use ➕ append; only new ids from A are inserted.
- Run — confirm and watch the progress bar. If the network hiccups, rows are chunked; re-running continues from where it stopped.
hard_sync DROPs the target table before re-creating it, so picking the wrong table wipes existing data. For production, make soft_sync or append the default and reserve hard_sync for first-time setup.
Once you have run the pipeline manually, wrap it in a macro for periodic execution. Service → Macro, create a new macro, and have the code invoke the migration.
- The macro body looks roughly like
fetch('/dataset/api/mig_run', { method: 'POST', body: JSON.stringify({ dataset_id: 123, action: 'soft_sync', deck_b: {host, db_name, user, password}, sel_tables: ['orders'] }) }). The exact parameter set is whatever the real button fires — inspect the network tab once to copy the request verbatim. - In the macro's Schedule tab, pick a cron. e.g. every day 3am
0 3 * * *. - Keep B → A and A → C as two separate macros so one side's failure does not freeze the other. Chain them by triggering the second one from the first one's
successresult.
Verification checklist:
- Run
SELECT COUNT(*) FROM orderson C and compare with A and B. - Pick a random recent id and compare column values across B · A · C.
- Deliberately insert one row into B and trace it reaching A then C within 5–10 minutes. If it does not, read the macro log and the migration result log.
Cell Editor · Paste-to-Insert from Excel into your dataset
A hands-on walkthrough of inserting hundreds or thousands of rows into a dataset table by simply copy-pasting from Excel / Google Sheets. One click on the Cell Editor button in the dataset list gives you a browser-side grid and lets you load rows without touching FTP or writing SQL.
Any of these is a clear win for paste-to-insert over hand-written SQL.
- A marketer hands you an Excel with 500 coupon codes that need to land in the service DB.
- A designer sends a Google Sheet of product names · prices · categories to be loaded in one go.
- A partner drops a CSV of members that needs to be imported as-is.
- You want to feed the AI wizard a table of 100 worked-out examples for later runs.
Cell Editor behaves exactly like Excel: a row × column grid where a Ctrl+C from Excel and a Ctrl+V in any cell auto-detects tab or comma delimiters and drops rows in place. No field-mapping dialog — columns fill left-to-right from the cell you started in.
Top nav → Data → Database. Your dataset list appears as cards or rows.
- Find the row of a dataset you own (your user_id). Shared datasets are read-only, editing is blocked.
- Click the Cell Editor icon in the row's action cluster. A full-screen modal opens.
- The layout: Options panel on the left (table selector · page step · sort · search · replace); the grid in the centre; the toolbar on the right (save · add/remove row · undo/redo · copy · CSV/SQL export · ✨ AI wizard).
- Pick the target table in the left dropdown. Its existing rows load into the grid. Empty table → empty grid.
Before pasting, confirm that the column order in Excel matches the table. A mismatch puts values into the wrong fields.
- Column headers — the first row of the grid shows column names and types. Your Excel columns, left to right, must line up with that order.
- Primary key — headers marked 🔑 are the PK. When
idis auto-increment, leave the id column out of your Excel selection; the DB assigns it on INSERT. - NOT NULL columns — red-marked headers cannot be empty. Make sure that column has a value in every row you paste.
- Too many / too few columns — extra columns on the right of your paste are ignored; missing columns on the right end up blank.
If the schema does not match, either regenerate the grid via Create Grid (X × Y) in the left options, or reorder your Excel columns before copying.
ALTER TABLE ... ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY; first.
The heart of the workflow. In Excel / Sheets, select the range you want (excluding the id column) and Ctrl+C. Then in Cell Editor:
- Click the starting cell. Usually the left-most column, one row below your last existing row, so new rows land after the current data.
- Ctrl+V. Cell Editor auto-detects tab (default Excel copy) or comma (CSV) and splits rows/columns accordingly.
- The grid expands and the new rows render with a lightly tinted background — marking them as "new, not yet saved".
- Paste again from a different start cell if you want to add more ranges.
Manual delimiter override — the Delimiter dropdown in the left options panel offers tab · comma · safe comma. Pick safe comma when your CSV has commas inside quoted strings — quoted segments stay in one cell.
Before saving, scan the grid. Cell Editor colour-codes three states.
- Tinted row — a just-pasted "new" row. Becomes an INSERT on save.
- Yellow corner dot on a cell — a modified cell in an existing row. Becomes an UPDATE on save.
- Greyed-out row — queued for deletion. The status bar shows "🗑 X records will be deleted on save" and a [Restore] button.
Common editing moves:
- Double-click a cell to type directly into it.
- Right-toolbar / — add an empty row at cursor / delete current row.
- Ctrl+Z · Ctrl+Y — undo/redo (up to 50 snapshots).
- Find & Replace — in the left options panel; text or regex mode, replaces across the whole grid.
The status bar shows ✏ X row(s), Y cell(s) edited. If that number is unexpected, fix it before saving.
Once it looks right, save either via the Save button in the right toolbar or Ctrl+S. Cell Editor assembles and runs:
- New rows →
INSERT INTO table (col1, col2, ...) VALUES (...). Auto-increment PKs get assigned by the DB. - Rows with modified cells →
UPDATE table SET col=val WHERE id=.... Only the changed columns are included. - Rows queued for deletion →
DELETE FROM table WHERE id=....
Success shows a "X rows saved" toast. The tinted background on new rows goes back to neutral and empty id cells fill with the numbers the DB assigned. Those rows are now indistinguishable from pre-existing data.
If it fails the memo panel shows the error — usually a NOT NULL breach, a type mismatch, or a unique-key collision. Fix the flagged row and save again.
AI Wizard · Bulk tasks with the "desired value / current value" pattern
Use Cell Editor's "desired value / current value" markers with the ✨ wizard button to run hundreds of AI tasks — translation, summarisation, classification, extraction, normalisation, outlier detection — from a single prompt. A few marked examples let the AI infer the pattern and apply it to the rest. This approach drops "repeated instruction typing" to almost zero in real work.
Most successful use cases
as if to be is a pattern-learning form of instruction: "If a correctly transformed result (Desired) looks like this, then transform the raw version (Current) the same way." Instead of writing the rule out in words, you show the AI a few of the rule's outputs and let it generalise to the rest.
Cell Editor ships two markers (colour 1 · colour 2) for exactly this.
- Marker 1 (Desired · teal) — example cells that show what the finished result should look like.
- Marker 2 (Current · coral) — raw cells the AI should fill in.
Why this is powerful:
- No need to write the rule in natural language. Examples teach the AI.
- It works for rules that are too subtle to articulate — tone, nuance, consistent voice.
- One prompt handles hundreds of cells. The copy-paste-per-cell grind disappears.
- Adding or editing examples lifts quality immediately. The tuning loop is seconds.
With the dataset open in Cell Editor, lay out this structure in advance.
- Input column — the raw text the AI will read. e.g.
ko_text,product_desc,address_raw. - Output column — empty column the AI will fill. e.g.
en_text,summary,city. Add one via SQL editor if missing:ALTER TABLE ... ADD COLUMN en_text TEXT;. - 2–5 example rows — fill the output column by hand. Three good examples decide the quality of 500 rows.
How to pick good examples:
- Diverse — include short, long, and edge cases. Similar examples leave the AI lost on outliers.
- Mix difficulties — one easy, one middle, one tricky.
- Make the style explicit — line breaks, capitalisation, formal/informal register should all be visible in the examples.
In the right-panel marker palette click the first swatch (teal · Desired Value) so it becomes the active marker. The selected swatch has an emphasised border.
- Click each of the hand-filled example cells in the output column. Each cell you click turns teal, meaning it is now marked as "Desired".
- Markers toggle, so clicking a marked cell again clears it.
- Drag to select a range, then click the swatch to mark the whole range at once.
Rename the label to match the task — click the pencil next to the label ("Desired Value" by default). Use something descriptive: "English translation" for translation, "One-line summary" for summarisation, "Category" for classification. The label is inserted into the prompt in step 5, which helps the AI understand the task more precisely.
Now activate the second swatch (coral · Current Value) in the marker palette.
- Drag-select the still-empty (or raw) output cells on the grid — e.g. rows 4 to last in
en_text. - Click the coral swatch once; every selected cell turns coral. These are the cells the AI will fill.
- The input column (
ko_text) does not need marking. The AI reads the input column of each marked row automatically. - Rename this marker too if useful: "To English", "Shorten", "Assign category" — a one-word instruction you want the AI to follow.
When done, the grid shows teal cells (example answers) + coral cells (empty targets) side by side. That is the "as if to be" pattern in its canonical shape.
Click the ✨ AI Wizard button in the right toolbar. Cell Editor reads the markers, assembles a structured prompt, and automatically copies it to your clipboard. A toast "AI prompt copied to clipboard" appears.
The prompt roughly looks like this (actual wording depends on your labels and examples):
- System line — "You are a data transformation assistant"
- Task statement — built from your labels. e.g. "Transform each 'Current Value' cell according to the pattern shown in 'Desired Value' examples."
- Example cells list — the (row, column, value) of each teal-marked cell. The AI learns the pattern here.
- Target cells list — the (row, column, raw input value) of each coral-marked cell.
- Output format contract — requires a JSON array only, in the shape
[{"pos":"row,col","return_txt":"value"}, ...].
Halting condition — with zero teal and zero coral markers a warning pops up. Go back to steps 3 and 4 and mark some cells.
Paste the clipboard into Claude · ChatGPT · Gemini and send. The AI replies with a single JSON array.
- Select just the JSON part of the reply and Ctrl+C. Explanations around it are fine — just grab the array itself.
- Back in Cell Editor, Ctrl+V into the Memo textarea in the lower right panel. Memo is the landing pad for AI output.
- Eyeball the text — shape should be
[{"pos":"3,5","return_txt":"Translated sentence"},{"pos":"4,5","return_txt":"Another"}, ...].
Stripping AI chit-chat — the assistant often prefaces the JSON with "Here is the JSON you asked for:". Take only the array that starts with [ and ends with ]. The apply button in step 7 parses strict JSON.
With JSON in Memo, click 📥 Apply AI Result in the right toolbar. Cell Editor parses the JSON and writes each return_txt into the cell at pos. A toast "X cell(s) applied" confirms success.
- Applied cells show the modified marker (yellow dot) — they are in the grid but not yet persisted to the DB.
- Unhappy with a cell? Ctrl+Z undoes, but undo drops the whole AI result. Usually it's faster to hand-correct just the bad cells.
- Satisfied → Ctrl+S. The same UPDATE path as Section 1 step 6.
Looping & batch strategy:
- Before applying the whole batch, eyeball 10 samples. If results drift, tweak examples/labels in steps 3–4 and regenerate the prompt.
- When quality is good, page through and mark the next batch, repeat steps 5–7.
- Keep a side column (like
batch_note) logging which examples produced each slice. It makes re-running a section trivial if the style changes later.
Fork → Customise → Publish · the menupan electronic menu story
Take the menupan (electronic menu board) solution from the marketplace, fork it into your own account, swap the logo for your company's, replace the demo menu with your actual products, dial in colours and fonts that match your brand, and ship it to your domain. Instead of building from zero, you branch a working project into your own copy and quickly make it yours — the most common real-world pattern.
Design iteration loop — inspect → try → ask AI → apply
Concrete scenario first. Café "Sodam" needs an electronic menu board on a tablet at the entrance. Building from scratch is slow; grabbing the marketplace's menupan solution and re-skinning it for the café is dramatically faster.
What we will finish in 30–45 min:
- Logo — replace the default menupan logo with our café "Sodam" logo
- Menu items — swap demo entries (Americano 4500 KRW, etc.) for our real menu
- Colour & font — switch the default blue tone to a warm beige + dark brown that matches the café, change body font to a Korean-friendly typeface
- Go live — publish at our own domain like
menu.sodam.kr
Why fork?
- Layout, DB schema and admin UI are already done — save 90% of build time.
- The fork lives under your account, your domain, your DB; the original solution stays untouched and only your copy is editable.
- If menupan upstream gets an update later, your fork is unaffected — your customisations stay yours.
Top nav → Community → Solution Market (or /solution). The marketplace shows solutions as cards.
- Use the top filter chips (All / Project / Macro / Community / Direct) — pick Project — or type menupan / electronic menu in the search box.
- Click the card to open its detail page with previews, feature description, and required resources (domain / DB).
- On the detail page click Fork to new project. The fork modal opens.
- Fill in:
- Domain — pick from your active domains, e.g.
menu.sodam.kr. Don't have one? Open Settings → Domains in a new tab and add one (a free~.apidealder.netsubdomain works) before continuing. - Dataset — the DB where menu data will live. New or existing one of yours.
- Project name & description — e.g. name
sodam_menu, description "Café Sodam in-store menu board". - Auto-deploy toggle — turn it on so the first build runs as soon as the fork finishes. Recommended on the first run.
- Domain — pick from your active domains, e.g.
- Click [Run fork]. A progress indicator appears, and after 30 sec to 2 min you get a completion toast. The new project shows up at the top of the My Projects sidebar and the workspace opens automatically.
Two halves: (a) upload the new logo via Remote management, (b) change the logo URL in the program editor.
(a) Upload the logo via Remote
- Top nav → Service → Remote. In the left server list, click your forked project's domain (
menu.sodam.kr). Make sure the indicator dot is green. - Type
/public/assetsin the path bar and press Enter to jump there. - Hit [Upload file] in the bottom action bar and pick your café logo (e.g.
sodam_logo.png). For a single file you don't need archive upload. - Open
https://menu.sodam.kr/assets/sodam_logo.pngdirectly in the browser to confirm a 200 OK and the image showing.
(b) Replace the logo URL in the program editor
- Back in the workspace, click the project's Programs. The list of programs appears (typically
main,menu_list, etc.). - Double-click the program that renders the logo (usually
main) to open the editor. - Open Find & Replace (Ctrl+H). Search for the existing logo path, often
/assets/menupan_logo.png. - In Find type
menupan_logo.png; in Replace typesodam_logo.png; Replace All. HTML and CSS get updated together. - Ctrl+S to save and verify the new logo in the right-hand preview pane.
/assets/sodam_logo.png. Relative paths (../assets/...) break with deeper routes.
menupan ships an admin page so staff can add/edit/remove menu items themselves. Two paths exist; strongly prefer the admin page.
(Recommended) Admin page
- Open
https://menu.sodam.kr/admin(or whatever path menupan defines) and sign in. Default admin credentials are listed in the solution's detail page README right after fork. - Click Menu management in the left sidebar. Categories (Coffee · Dessert · Non-coffee) and items (Americano · Latte · …) appear in tables/cards.
- Delete the demo entries, then add your real menu line by line:
- Name (
Americano) · Price (4500) · Description (...) · Category (Coffee) · Photo (a URL pointing at the photo you uploaded via Remote).
- Name (
- Day-to-day work — edits, ordering, show/hide toggles — all happens here. This is the screen your café staff can use too.
(Alternative) Direct DB edit
- For surgical bulk operations the admin doesn't cover (e.g. raise every coffee price by 500 at once), open Data → Database → the dataset you created at fork → Cell Editor.
- Pick
menu_itemand edit the rows directly, or use the SQL editor:UPDATE menu_item SET price = price + 500 WHERE category='Coffee';. (See Best Practices → Cell Editor paste-to-insert for grid usage.) - Caveat: editing columns the admin doesn't know about, or breaking PK/FK constraints, can break the admin page. That's why everyday edits stay in the admin.
/assets/menu/*.jpg) pays off later for backups and migrations.
Before touching code, find the colour you actually want by tweaking it in the browser. Changes are temporary — refresh wipes them — so experiment freely.
- Open the deployed menu (
https://menu.sodam.kr) in Chrome, press F12 for DevTools (or right-click → Inspect). - Click the arrow-in-square icon at the top-left of DevTools (Element Picker), then click the area you want to recolour (header, menu card background). The right-hand Styles panel shows the CSS rules applied.
- Hover over a colour value (
background-color: #2563eb;) — you'll see a tiny colour swatch. Click it to open a colour picker and either drag or type a new hex value. - Change
font-family: ...;the same way: type a new family ('Pretendard', 'Noto Sans KR', sans-serif). - Once you like the combination, jot down the hex codes and font names. You'll feed them to the AI in step 6 or apply them in step 7.
Useful tricks:
- Compare elements live — if a header tweak makes the body look off, edit both at once and see how the pair reads together.
- Computed tab — shows the final value (with inheritance). Helpful when you're wondering "where did this value come from?".
- Force :hover — the
:hovbutton at the top of Styles toggles:hover·:focusstates so you can vet hover colours too.
If your hand-picked colours from step 5 still feel off, ask Claude / ChatGPT for tone candidates and you'll get five to ten alternatives instantly. Send a prompt like:
I'm building an in-store electronic menu board for a café called "Sodam".
Vibe: warm and quiet Korean café.
Space: wood-tone interior, warm yellow lighting.
Current palette:
- Header bg: #2563eb (blue)
- Body bg: #ffffff
- Text: #1f2937
- Accent: #2563eb
Suggest 5 palette sets that fit this vibe better.
For each set give hex codes for header / body bg / text / accent
plus a one-line note explaining the feel.
Also recommend 3 Korean-friendly Google Fonts (or free Korean
fonts) that match this mood.The AI will respond with something like:
- Set 1 (warm beige · dark brown) — header
#6b4423, body bg#f5ecd9, text#3c2415, accent#c97a4a· blends naturally with wood tones and yellow lighting - Set 2 (modern minimal) — …
- …
Validating the suggestions:
- Back in step-5 F12 inspect, paste each hex into the live page and pick the set you like best.
- Mixing across sets is fine — "header from set 1, accent from set 3" often wins. Note that down too.
- For fonts, search
https://fonts.google.comfor the suggested names and check the actual letterforms on your menu.
Now turn the F12 + AI choices into real code. After this step the change survives a refresh and everyone else sees it too.
- Workspace → project → Programs → double-click the design program (typically
mainortheme) to open the editor. - Switch to the SCSS (or CSS) tab. Colour variables are usually grouped at the top of the file (
$primary-color,$bg-color, etc.). - Drop your hex values into those variables:
$header-bg: #6b4423;$body-bg: #f5ecd9;$text-main: #3c2415;$accent: #c97a4a; - For the Korean font, add at the very top of the SCSS:
@import url('https://fonts.googleapis.com/css2?family=Pretendard&display=swap');and set the body'sfont-familyto'Pretendard', sans-serif. - Ctrl+S to save. The bottom preview should reflect changes immediately.
Two ways to publish
- Option A — manual deploy (default): click 🚀 Deploy in the workspace toolbar. Build and push run for 1–2 min, then
menu.sodam.krshows the new design. Safe for the first time. - Option B — save-on-deploy (great for fast iteration): flip the "Save on deploy" toggle in the workspace toolbar. From now on every Ctrl+S automatically deploys. Perfect when you're sweeping through colour, font and menu tweaks live. Turn it off during business hours so customers don't see flicker mid-edit.
When deploy completes, open https://menu.sodam.kr on a phone and tablet for the final check. The same URL on the in-store tablet is what your customers see — that's your menu board.
Block Builder × Program Builder × Data binding · build a JSON-driven frontend
Design a reusable component (block) in the Block Builder, drop it into a slot in the Program Builder (a.k.a. Coder Builder) list step, then bind real rows from a dataset to that slot's variable. Once the pattern clicks, you can build screens where a single JSON spec becomes the whole frontend page. To keep the first lap simple, this guide narrows the scope to one "product list" page.
Anatomy at a glance — block library · frame slots · dataset
Think of the frame as a picture frame, the slots as the insert grooves inside it, a block as a designed photograph, and the dataset as the album that supplies the text printed on top — and the rest falls into place. Slide the photo into the frame, pour the album one row at a time into the empty spots on the photo, and that is the entire job for today.
Where the data flows — 4-stage pipeline
Instead of writing fetch() by hand and rolling your own v-for, there is a pattern: take a pre-designed component (block), drop it into a frame slot, wire a dataset, and the page is done. This guide walks the whole loop end to end.
Analogy refresher: an empty picture frame (frame) holds pre-designed photos (blocks); an album (dataset) supplies the text printed on those photos; hanging the frame on the wall is the deploy.
Today's page — "our shop's product list": a header on top, ten product cards in the middle (real rows from the dataset), a footer at the bottom. Plain one-screener.
- One step beyond: more advanced builds wire 8–10 dataset tables — quotes, news, rankings — into multiple variables at once (list / list3 ... list10) and render an entire page from a single JSON spec. This guide stays at the first stitch of that pattern: one variable (list) + one dataset (products).
- Why this approach — designers focus on the block's look, the data person owns the dataset, the page owner only matches slots in the Program Builder. Roles split cleanly. Data changes leave the design alone; design changes leave data alone.
Get the real data ready first. Building the screen on top of an empty table makes it impossible to verify anything. Data first, screen second.
- Top nav Data → Database. If you have no dataset of your own, click [+ New dataset]. e.g. name
shop, MySQL/PostgreSQL. - Open its SQL editor and create the table:
CREATE TABLE products (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), price INT, image_url TEXT); - Open the dataset's Cell Editor for
productsand add 5–10 rows. Pasting (Ctrl+V) from Excel is fastest — see Best Practices → Cell Editor paste-to-insert for details. - Quick check:
SELECT * FROM products LIMIT 3;. We'll wire this dataset to thelistvariable in step 6.
Columns to include — only those your block design needs. name · price · image_url is enough. Extras hurt nothing, but starting simple speeds debugging.
Now the block we'll plug into the slot. Top nav Design → Block (or /layout/block) opens the block library. Click [+ New block].
- Name — something memorable like
product_card_list. - HTML pane — paste a card-grid template. The trick: name your variable
list:<div class="card-grid">
<div class="card" v-for="item in list" :key="item.id">
<img :src="item.image_url">
<div class="name">@{{ item.name }}</div>
<div class="price">@{{ item.price }}</div>
</div>
</div> - CSS/SCSS pane — basic grid:
.card-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; }.card { padding:14px; border:1px solid #eee; border-radius:8px; } - sample_data — dummy preview data as JSON, keyed
list:{ "list": [
{"id":1,"name":"Sample A","price":1000,"image_url":"/assets/sample.jpg"},
{"id":2,"name":"Sample B","price":2000,"image_url":"/assets/sample.jpg"}
] } - Save. The Block Builder preview should auto-render two cards from sample_data. Getting that preview to render is the make-or-break check. If it doesn't, confirm the variable name in your HTML (
list) matches the key in sample_data (list).
list) matches the binding name or differs (with mapping) is the key decision in steps 5–6.
Now build the page. Service → Project → [your project] → + New program, or open an existing program in the Program Builder (Coder Builder) — same tool, two names. Eight tabs.
- Eight tabs — db · list · detail · search · hook · style · code · menu. Click the second tab, list.
- Layout mode toggle — at the top of the list tab there are two modes: "fields / slots". Default is fields (table-like). We want to plug in a designed block, so flip to slots. The UI changes to a 3-step slot config:
- 1) Frame select — which frame (with how many slots, how laid out)?
- 2) Slot config — which block goes into each slot, how data variables map.
- 3) Code preview — the synthesised result for review.
- If "frame / slot" still feels abstract, picture "a 3-row picture frame waiting for three photos". We pick the frame in step 5.
In the slot-mode UI's 1) Frame select, open the dropdown and pick something simple — "3-row (top / middle / bottom)" works well. Click [Apply] and the 2) Slot config auto-creates rows for slot 1, slot 2, slot 3 …
- For slot 2 (middle), open the block selector dropdown and pick the product_card_list from step 3. Options usually read
id - name - author. - The slot area immediately previews the block with its sample_data — two cards. If you see those, you've seated the block correctly.
- Slot 1 (top) and slot 3 (bottom) can take pre-built header/footer blocks the same way, or stay empty for now. For the first run, only slot 2 needs to be filled.
- Each slot row also exposes a data_placer (source selector) and data_selector (target selector) field. For now, leave both at
list. We unpack their meaning in step 6. - The block is in the slot, but it's still backed by sample data. We connect a real dataset next.
This is the most important step. We wire the variable list (used inside the block) to actual rows from the products table.
What the two fields mean:
- data_placer (source selector) — the variable name as written inside the block. Our block has
v-for="item in list", so this islist. - data_selector (target selector) — the variable name as used at the page level. If you have two card lists on the same page,
listwould collide; map one toproduct_list, another toreview_list. With a single list, leaving it aslistis fine.
For simplicity, we keep both as list and move on.
Wiring the actual dataset — open the data variables / data_vars section at the top of the Program Builder (or its sidebar). If empty, click + Add for one row.
- Var name:
list(must match the data_selector from step 5). - Dataset: pick
shopfrom step 2. - Table:
products. - WHERE (optional): empty = all. e.g.
price > 0. - LIMIT (optional):
0, 20for the first 20 rows. - ORDER BY (optional):
id descfor newest-first. - Save.
Internally this becomes a JSON record (you don't write it directly, but conceptually):
{"var_name":"list","dataset":{"id":42,"table_name":"products","str_limit":"0, 20","str_order":"id desc"}}
That JSON is the spec the page renderer follows: at request time it runs SELECT * FROM products ORDER BY id desc LIMIT 20, drops the rows into list, and the block's v-for takes over.
product_card_list with two different data_selectors (recommend_list, new_list) wired to two different WHERE filters on the same products table.
With everything wired, jump to 3) Code preview in slot mode (or the dedicated code tab) and let the system synthesise the result.
- Click Generate code (sync). The system stitches:
- The frame's HTML skeleton with
<[slot-1]>·<[slot-2]>·… filled by each slotted block's HTML. - Inside each block,
list→ step 5's data_selector (stilllisthere). - The data_vars definitions are added to the page's init code.
- The frame's HTML skeleton with
- Review the output. If
v-for="item in list"still appears intact and there's a top-of-pagelist = await fetch('/api/...')(or a server-side injection), you're good. - Ctrl+S or Save. The preview should now flow real products rows as cards. You should see 5–10 cards from the dataset, not 2 from sample_data.
- Finally, hit 🚀 Deploy in the workspace (or have "Save on deploy" enabled) and verify on the live domain.
Why the JSON spec is the frontend — at this point everything the page does boils down to three JSON records.
- slot_info — which frame, which slots, which blocks.
- data_vars — which variable maps to which dataset, table, filter.
- ui_info — extra UI options (mostly empty here).
You don't hand-write code anymore: tweak these three JSONs and the page redraws. After this it gets magical — making 10 screens approaches the cost of making 1, because each new screen is mostly a new combination of existing blocks and dataset bindings.
list?), ③ products table actually has rows, ④ WHERE isn't too strict (resulting in zero rows). Almost every blank-preview case hits one of these.
Parser Advanced · Bring a cURL Verbatim and Loop It Over a Dataset
For sites where a plain GET ?q=... URL is not enough — sites that need cookies, CSRF tokens, Authorization headers, and a POST JSON body — this guide walks you end-to-end through reproducing the exact browser request, marking the parts that should change per row, and looping it N times against a dataset to collect responses into a new table.
Pipeline at a glance — Browser request → cURL clone → Variable injection → Loop call
(F12)
the whole packet
in Postman
slots ${var}
+ loop over dataset
cURL line by line — URL · Cookies · Headers · Body
A single browser request usually packs four things together — URL/method, session cookies, auth/AJAX headers, and a POST body. Only the parts that change per row become ${variables}; everything else stays exactly as captured.
${name}.
The loop in one picture — Dataset rows → Variable substitution → Responses
A row from the left dataset is injected into the ${variable} slots of the cURL template in the middle, and the response lands as a new row in the right dataset. With 100 input rows you get 100 calls — no human button-press loop.
injected
stored
For a simple site, a single GET URL like https://site.com/search?q=hello is enough. But more than half of real-world sites are not that simple.
- Logged-in-only results — without a session cookie you get an empty page or a login screen.
- POST + JSON body — the search term is not in the URL, it lives inside the body:
{"q":"hello","page":1,"size":20}. - CSRF / Bearer tokens — every request needs an extra header or it returns blank.
- X-Requested-With · Referer · User-Agent — when these AJAX-marker headers are missing, the server often deliberately answers with nothing.
Re-typing every header by hand is a non-starter. The fastest path is to copy the actual browser request as a single cURL command, leave everything as captured, and replace only the per-row pieces with variables.
What we will build — a dataset of N keywords (e.g. keyword_list), then call the site's search API N times and stack the responses into a second dataset (e.g. search_results).
Open the target site in Chrome (or Edge) and search once the way you normally would.
- Press F12 to open DevTools, then move to the Network tab.
- Run the search. The list fills with requests. The one you want usually contains
search,list,query, orapiin its name and returns JSON. - Click the request and check the right-hand Response tab — confirm the body really is the data you want.
- Right-click the request line → Copy → Copy as cURL (bash). Even on Windows, the bash flavor has the cleanest quoting.
Your clipboard now holds a one-liner like curl 'https://...' -H 'Cookie: ...' -H 'Authorization: ...' --data-raw '{...}'. It looks long, but it contains URL · cookies · all headers · body in one shot.
Do not paste the cURL straight into the parser. First confirm in Postman (or Insomnia / Bruno) that one call works exactly. If it fails here, the parser rule will fail too.
- Open Postman → top-left Import → Raw text tab.
- Ctrl+V the cURL one-liner and click Continue → Import.
- A new request tab opens with all headers and body pre-filled. Click Send at the top right.
- If the status is 200 and the body matches what you saw in the browser, you are done. Empty body, 401, 403, or 302 means check the items below.
- Cookie expired — by far the most common cause. Re-confirm you are still logged in, then re-run F12 → Copy as cURL.
- Header missed during conversion — Postman occasionally drops 1–2 headers. Open the browser Network tab Headers panel and Postman Headers side by side and compare line by line.
- Referer / Origin — some sites return blank without these two. If the browser sends them, add them.
Looking at the working Postman request, mark the parts that will change on the next call. Common candidates:
- Search term in the POST body —
"q":"hello"→"q":"${query}" - Page / offset —
"page":1→"page":${page}(numbers without quotes) - Category / filter —
"cat":"food"→"cat":"${category}" - Date range —
"from":"2026-04-01"→"from":"${date_from}" - URL path variable —
/api/user/12345→/api/user/${user_id}
The trick is to name each variable identically to the dataset column you will create. If you are going to name your columns query · page · category, then write ${query} · ${page} · ${category} in the cURL too. Identical names mean automatic mapping in the next step — no manual wiring.
Format — the parser recognises the ${name} pattern. Use only ASCII letters, digits, and underscore (no spaces, no localised characters, no punctuation).
The parser reads the dataset row by row and feeds each row into the cURL's variable slots. So in this step you prepare the N input combinations as a dataset.
- Side menu Data > Datasets → top-right + New dataset.
- Name it something obvious like
keyword_list. Add columns whose names match the variables from Step 4 exactly — e.g.query (varchar) · page (int) · category (varchar). - Add rows in either of two ways — (a) type them in the UI one by one, or (b) prep them in Excel/Sheets and use the Cell Editor paste-to-insert flow.
- Resist the urge to start big. Add 3–5 rows only for now. Starting with 100 rows means one mistake produces 100 wrong calls.
It also helps to prepare the output dataset now. e.g. search_results with columns query, rank, title, url, snippet. You will point the parser at it in Step 6.
${variable} by even one character, automatic mapping breaks and you have to wire it manually. Copy the variable name from Step 4 and paste it as the column name verbatim — it is the safest habit.
Now build the parser rule and connect the cURL to the dataset.
- Side menu Data > Parser → top-right + New rule.
- Test-page (base URL) field — paste the endpoint from the start of the cURL, e.g.
https://example.com/api/search. If the URL itself contains a variable, write it the same way:${user_id}. - cURL field — Ctrl+V the variable-marked one-liner from Step 4. The parser auto-splits method, headers, cookies, body, and finds
${...}patterns to register them as variable candidates. - Pick the input dataset — choose
keyword_listfrom Step 5. Matching names auto-map; mismatches surface a mapping dropdown next to each. - Pick the response-storage dataset — choose
search_results. Tell the parser which JSON path of the response (e.g.data.items[*]) becomes one row. - Save. The rule is registered — no calls have been made yet.
Two run modes are available.
- ① One-shot direct override — on the rule page, beside the ▶ Run button, the variable input panel lets you type
query="best ramen", page=1and fire a single call. The response preview and the extracted rows appear side by side. Stay in this mode until the response shape is fully understood. - ② Loop over dataset — switch the variable panel to "From dataset", pick
keyword_listfrom Step 5, hit Run. A progress bar climbs from 0/N to N/N as responses are appended row by row tosearch_results.
While it runs, watch error count (empty/401/5xx), response sample, and rows stored. One or two failed rows is normal; if more than 50% fail, stop and re-check the cURL.
Schedule — under the rule's Schedule tab you can run it daily, hourly, or at any cron-style time. Drop a keyword list in the input dataset and a daily-fresh result table comes out the other end.
Remote Management · Basics
End-to-end walkthrough of taking a design asset bundle (images, logos, fonts, CSS) from the designer, uploading it to the deployed server, and referencing it from a single-file project so the assets actually render in the browser. No FTP client required — everything happens inside the browser.
Before uploading, pack everything the designer gave you into one zip archive. The way you zip it decides how the paths look on the server, so follow these rules.
- Wrap everything in a top-level folder — e.g. put images and css inside a
design_assets/folder and zip that folder itself. After extraction you will see/upload-path/design_assets/logo.png, keeping the folder name as one level. - Use only letters, digits, hyphens (-) and underscores (_) in names — spaces or non-ASCII characters tend to break URL references. Example:
main banner.png❌ →main-banner.png✅ - Supported formats — .zip · .tar · .tar.gz · .tgz. Most of the time .zip is enough. On Windows, right-click the folder → "Compress to ZIP file"; on macOS, right-click in Finder → "Compress".
- Example layout —
design_assets/
├─ images/logo.png
├─ images/hero.jpg
├─ fonts/pretendard.woff2
└─ css/theme.css
images/logo.png directly, build the zip without the outer wrapper and pack the sub-folders (images, fonts, css) at the top level. Pick one convention and stay consistent throughout the project.
From the top navigation or dashboard, go to Services → Remote Management. You should see a server list sidebar on the left, a four-column file explorer in the middle, and an action bar at the bottom.
- In the server list on the left, click the domain you want to upload to (e.g.
myshop.apidealder.net). The small circle next to each domain name shows its current state.- Green dot — ready; the file list opens immediately.
- Gray dot — offline. The container is stopped, or the server has not been deployed yet.
- White dot — checking status.
- If the list is empty, you will see a "Deploy a server first" prompt. In that case, deploy a single-file or project first and come back.
- Once selected, the middle area expands the root (
/) folder and reveals the real file tree.
Assets will be loaded by the browser through a URL, so they must live in a publicly accessible folder. On single-file-based servers the usual choice is public/assets.
- Path bar — the house icon at the top of the middle area jumps to root, and each slash-separated segment is clickable to jump there instantly.
- Path input — next to it, type
/public/assetsdirectly and press Enter to jump in one shot instead of clicking folder-by-folder. - If assets folder does not exist — use the bottom action bar's [New folder] button to create
assetsand enter it. Only letters, digits, dot (.), hyphen (-) and underscore (_) are allowed in the name. - After moving, confirm the path bar reads
/public/assets. This is the folder the archive will be extracted into, so a wrong location means you will have to delete and re-upload.
/) and system folders (/etc, /var/log) are not served over HTTP. Always mentally draw the mapping — is https://your-domain/assets/your-file reachable from this location? — before uploading.
With the path set to /public/assets (or any public folder you prefer), click [Upload archive] (cloud-up icon) in the bottom action bar. The upload modal opens with a three-phase flow.
- Dropzone — drag the zip file into the dashed box or click it to open a file picker. .zip · .tar · .tar.gz · .tgz are supported.
- Preview — the modal draws the folder/file tree inside the archive and shows the file name, size, and the extraction target (
/public/assets) at the top. Use this to verify the outer wrapper is correct and that no stray hidden files (macOS.DS_Store, for example) slipped in. The [x] on the upper right swaps the file if needed. - Send — click [Send]. The file is sent in 1 MB chunks with a live progress bar, so flaky networks resume cleanly and large files (hundreds of MB) upload reliably.
- When the transfer finishes, the server auto-extracts the archive, the current folder refreshes, and the newly uploaded
design_assetsfolder (or images/fonts/css folders) appears. A completion toast also shows up.
Need to upload a handful of loose files instead? Use the neighboring [Upload files] button to multi-select files — they will be copied into the current folder as-is with no extraction.
Uploaded files are served directly from the deployed domain. For example, if you uploaded to /public/assets/design_assets/images/logo.png on myshop.apidealder.net, the browser URL is https://myshop.apidealder.net/assets/design_assets/images/logo.png. (public is the web root, so it drops out of the URL.)
Now open the single-file editor (Services → Single File) and reference the assets you just uploaded.
- Insert images in the HTML tab —
<img src="/assets/design_assets/images/logo.png" alt="logo"><img src="/assets/design_assets/images/hero.jpg"> - Reference backgrounds and fonts in the SCSS tab —
.hero { background: url("/assets/design_assets/images/hero.jpg") center/cover; }@font-face { font-family: 'Pretendard'; src: url("/assets/design_assets/fonts/pretendard.woff2") format('woff2'); } - Key rule — always use an absolute path starting with
/. Relative paths (../assets/...) can behave differently between preview and production and are discouraged. - To include an external CSS file wholesale, add
@import url("/assets/design_assets/css/theme.css");at the very top of the SCSS tab.
After wiring the references, click [Run ▶] at the top right of the single-file editor to preview first. If the preview is fine, press [Deploy 📦] to push it to the live domain.
- Run preview — the right-hand pane renders the result in real time. Confirm images appear, fonts load, and the CSS is not broken.
- Deploy — the deploy button starts a step-by-step deployment and usually finishes in one to two minutes. A domain link shows up in the result box when it is done.
- Verify on the live domain — open the link in a new tab, or visit
https://your-domain/directly. Do a hard reload (Ctrl+F5 or Cmd+Shift+R) to skip cached content. - If an image does not appear, jump back to Remote Management and double-check the path. When the extracted folder structure does not match what you expected, deleting that folder and re-uploading from Step 4 is usually faster than hand-patching paths.
logo.png → logo_v2.png) and update the reference accordingly.
Remote Management · Advanced
A practical debugging walkthrough for when something on the deployed server is not behaving. You will use the terminal panel — right inside the browser — to run CLI tools like grep, cat, and tail against the log files under storage/logs. No SSH client, no desktop tools — just the remote tool.
On the surface symptoms look similar, but the root cause varies. If any of these apply, reading the server-side logs is the shortest path.
- 500 / 502 / 504 server errors — the browser only shows "An error occurred"; the real cause lives in the server log.
- Blank white page — usually a PHP fatal error silenced the output. The log will almost certainly contain a Fatal Error or Parse Error line.
- API returning 400/422 with unclear cause — the exact validation rule that tripped is recorded in the controller log.
- Background work (queue, schedule, macro) "seems to run but produces no result" — silent failures leave traces only in the logs.
Key log files to look for:
storage/logs/laravel.log— the main PHP/Laravel log. Your most-visited file.storage/logs/laravel-YYYY-MM-DD.log— if daily log rotation is enabled.storage/logs/worker.logand feature-specific logs (macros, parsers) when those subsystems keep their own files.
Head to Services → Remote Management in the browser.
- In the server list on the left, click the domain that has the issue. A green dot means the container is reachable. A gray/white dot means the container is asleep — wait a minute and click again.
- Click the terminal icon (▷_) in the toolbar at the top of the middle area. A terminal panel slides up from the bottom. Clicking the same icon again collapses it.
- The panel header shows the current working directory (e.g.
/var/www/html) and the cursor starts blinking in the input. This cursor is wired to the selected server's shell, so commands run on that server directly. - Before doing anything, sanity-check where you are:
pwdls
You usually land at the project root (/var/www/html).
/bin/sh, not bash. Bash-only syntax (such as [[ ... ]] or arrays) may not work. Simple commands — cd · ls · cat · grep · tail · head — are all fine.
In a Laravel project, logs live under storage/logs. Jump there from the terminal.
cd storage/logs— relative to the current folder; one line is enough if you are already in/var/www/html.cd /var/www/html/storage/logs— absolute path; works no matter where you started.pwd— confirm you ended up in/var/www/html/storage/logs.
The terminal remembers the working directory, so every subsequent command runs relative to this folder without retyping the path.
Alternative: navigate to /storage/logs in the file explorer first, then open the terminal — the path follows you automatically. Handy when you dislike typing paths.
cd ..) and ls around to find the real log location (log/, logs/, /var/log/nginx/, etc.).
Once inside the folder, first check which files exist and which were touched most recently, then peek at the contents.
ls -lhrt— file listing sorted by modification time ascending; the most recent file sits at the bottom.-hprints human-readable sizes (KB/MB).cat laravel.log— dump the whole file. Only safe for small files; multi-MB files will flood the terminal.tail -n 100 laravel.log— last 100 lines. The fastest way to see the most recent error. Tune the number as needed.tail -f laravel.log— live follow. New log lines appear as they are written; reproduce the bug in the browser and watch entries stream in. Ctrl+C to stop.head -n 50 laravel.log— first 50 lines; useful for boot-time entries that sit at the top.wc -l laravel.log— total line count. If a file is hundreds of thousands of lines, skip togrepright away.
mv laravel.log laravel.log.old and let a fresh file be created. Reproducing the bug against an empty file gives you a clean signal without losing the old log.
When the file is long, tail alone is not enough. grep prints only the lines that contain a given pattern — the workhorse of log debugging.
grep -i error laravel.log— all lines containing "error";-imakes it case-insensitive so "Error", "ERROR", and "error" all match.grep -in "fatal\|exception" laravel.log— lines with "fatal" or "exception", with line numbers (-n). Multiple patterns are OR-combined with\|.grep -A 5 -B 2 "SQLSTATE" laravel.log— find lines containingSQLSTATEand print 2 lines of context before (-B 2) and 5 after (-A 5). Ideal when you want the stack trace next to the exception.grep "2026-04-25 15:4" laravel.log— scope to a specific time window (3:40 PM range). Combined with the window you noted in Step 1, this narrows things down fast.grep -c "production.ERROR" laravel.log— prints only the count of matches. Good for "how often does this happen".tail -f laravel.log | grep -i error— live follow with filter. Only error lines make it to the screen.
Typical search flow — grep -i error to see the shape → pick a conspicuous message and re-run grep -A 10 "that message" for surrounding context → note the file paths and line numbers that fall out.
less (grep ... | less) for paged navigation, or write to a file (grep ... > /tmp/out.txt) and open it in the remote code editor. less is available on Alpine out of the box.
Error lines caught by grep usually carry a file path and line number (e.g. /var/www/html/app/Services/Order.php:127). Use that to jump straight to the fix.
- Collapse the terminal, paste
/var/www/html/app/Servicesinto the file explorer's path input, and hit Enter. - Double-click the target file to open it in the syntax-highlighted code editor. Fix the line and press [Save] — changes apply instantly, no redeploy needed.
- Re-open the terminal, start a live follow with
tail -f /var/www/html/storage/logs/laravel.log, then reproduce the bug in the browser. - If the same error does not appear, press Ctrl+C and you are done. If a different error shows up, loop back to Step 5 and narrow it down again.
When you need temporary debug logging — drop a single line into the suspect code: \Log::info('[debug] ' . json_encode($variable));, save, reproduce, and run grep "[debug]" laravel.log to read back the value. Remove the line once the issue is understood.
Log::info, dd(), and var_dump() when you are finished. Leaving them in bloats the log with every real user request, and a stray dd() turns the affected feature into a blank white page.
Final Challenge · Work via VS Code + AI (Claude/Codex via MCP), Deploy Local → Stage → Production
The capstone guide where every feature you have learned so far comes together. Ask Claude or Codex (connected via MCP) for changes in plain language inside VS Code, see them on your local test server first. Once happy, one button push syncs code and DB to a stage server for verification on a near-production environment, and finally deploys to production — the industry-standard workflow, walked end to end.
One work cycle — VS Code editor ⇄ Claude/Codex (MCP) ⇄ Local preview
In an era where AI writes the code, the human role becomes "ask precisely, verify carefully". Type your request in the VS Code chat panel, Claude/Codex reads and edits project files directly through MCP, and the change shows up instantly in the browser via the already-running vite dev / php artisan serve. You only need to confirm intent and queue the next request.
You ask in plain language (e.g. "add a phone column to the users table and a row to the signup form"). You verify the result in the browser and chain the next request.
(natural language) code change
applied
Reads and edits project files directly via MCP — SQL migrations, blade/vue/scss changes, build commands, all in one shot. You watch the result, not the keystrokes.
3-stage deploy pipeline — Local → Stage → Production
You do not throw a local change straight at production. A stage environment in the middle — same domain/DB/traffic shape as prod — catches the regressions that "worked on my machine". A single click of [SRC → DST] in the QS DEPLOY tab moves one stage forward, and it carries code + assets + DB together.
- vite dev + php artisan serve running on your PC
- Save → browser refresh in seconds
- Fastest place to verify what AI just changed
- Same domain/DB shape as prod (different host)
- Regression-test against real-shaped data
- Share the link for review
- The main server real users hit
- Save on Deploy guards against unsaved files
- Watch logs after deploy → SWITCH lets you roll back fast
Almost every working dev team follows this flow. Small changes, verified at every stage. Throwing a change straight at production breaks production all at once.
- Local is fast — save and refresh in 1 second. The first place you confirm the change matches your intent.
- Stage mirrors prod's domain, DB, and traffic shape. The last net for "worked on my machine, not on the server" surprises.
- Prod is what real users see. A problem first found here arrives as a customer complaint.
Today we walk all three stages end to end. The actual work happens by asking Claude or Codex inside VS Code in plain language. Your job is no longer to type code line by line — it is to state intent clearly, verify the result, and decide whether it is safe to send forward.
Five minutes once, and the rest of the day is faster.
- From QuickStart web, open Download package for your project, unzip, then File > Open Folder in VS Code.
- The bottom QUICKSTART panel appears automatically. Auth is silent — the
.env's fingerprint connects to the server with no login form. - UTIL tab → bottom-row [🚀 SMART SETUP]. Runs
composer dump-autoload → npm install → vite buildin one go. When it finishes, vite dev and the PHP built-in server are both up.
Open http://localhost:<port> — your project is live. This is the starting line.
Two paths, usually used together.
- ① VS Code chat panel + MCP — point Claude (or Cursor / Copilot Chat / Codex CLI) at an MCP server for the project. Then in chat: "add a phone column to the users table and a row in the signup form". The AI writes the SQL, edits blade/vue/scss, and runs the build — all of it.
- ② UTIL tab AI buttons — select code and click UTIL → AI group → [CODE REVIEW] · [REFACTOR] · [EXPLAIN] · [i18n TS]. Each one builds a project-context-rich prompt you paste into Claude/Codex for a sharper answer.
Writing a good request — be specific about what, where, in what form. Example: "On /admin/users, show the phone column right after email; render \"-\" when empty." That kind of phrasing keeps the AI on track.
The moment AI saves a file, vite dev hot-reloads the browser. Almost any .blade.php · .scss · .vue · .js file refreshes on save; PHP backend changes are picked up by php artisan serve.
- Look at the actual screen — right place, right behaviour, right shape?
- Quick scan of the F12 console — no red errors before sending forward.
- UTIL → SYSTEM → [CLEAN CACHE] clears Laravel's view/route cache so config or template tweaks land cleanly.
If the result is off, just ask the AI again briefly — "move that phone column above the postcode" — refresh. One round of this should fit in under a minute when you are in the groove.
Local passed → push to stage.
- Switch to the QS DEPLOY tab in the bottom panel.
- In the left sidebar set Source = L (Local), check Destination = stage.
- Click each node's [CONNECT] and [TEST CONFIG] once — confirm a real connection. Red dots → check that node's .env (host, port, DB account).
- Click [SRC → DST]. Glance at the right-side [Save on Deploy] toggle — when ON, every open editor is saved before deploy starts.
- The log viewer streams the move in real time — code + assets (images / build outputs) + DB schema & data flow to stage in one pass.
Once it finishes, open the stage domain in a browser and verify both the code change and the new phone column landed in the stage DB.
Stage is a mirror of production. Only the domain is different — code and DB are exactly what is about to ship.
- Visit the real stage domain and use the change yourself. Caching, CDN, and session issues that hide on localhost surface here.
- Share the link with someone else. They see what you cannot see because you wrote it.
- QS DEPLOY → [DIFF] compares stage ↔ local. Differences mean someone touched stage manually — clean those up before prod.
- [BROWSER] opens the stage server's real file tree to inspect anything suspicious.
Regression caught? Back to local, ask the AI again → step 4 → step 5. One extra loop here is dramatically cheaper than one production incident.
Stage passed → final push. Same buttons as step 5; the difference is real users see it immediately.
- QS DEPLOY → Source = stage (or L, same code), Destination = main (the production node).
- Confirm [Save on Deploy] is ON. Habitual ON is the safer default.
- Click [SRC → DST]. Stay on the log viewer until it finishes — any 5xx or red line, abort.
- Open the production domain. Use the new feature, then walk through the core flows you did not change (login, checkout, etc.) — make sure they still work.
- If something is wrong, [SWITCH] source/destination and ship the previous stage state back to prod — your fast-rollback path.
One full lap done — VS Code → Claude/Codex(MCP) → Local → Stage → Prod. From here, every future change rides the same rail, just faster.