Skip to content

Step 2: Your First Block

Now let's create a block! By the end of this page, you'll understand the .lego file format and have a working home page.

Create Your First .lego File

Create src/blocks/home-page.lego:

html
<template>
  <div class="hero">
    <h1>[[ title ]]</h1>
    <p>[[ subtitle ]]</p>
    <button @click="handleClick()">[[ buttonText ]]</button>
  </div>
  
  <div class="features">
    <div class="feature" b-for="feature in features">
      <span class="icon">[[ feature.icon ]]</span>
      <h3>[[ feature.title ]]</h3>
      <p>[[ feature.description ]]</p>
    </div>
  </div>
</template>

<style>
  self {
    display: block;
    min-height: 100vh;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    padding: 4rem 2rem;
  }
  
  .hero {
    text-align: center;
    max-width: 600px;
    margin: 0 auto 4rem;
  }
  
  .hero h1 {
    font-size: 3rem;
    margin-bottom: 1rem;
  }
  
  .hero p {
    font-size: 1.25rem;
    opacity: 0.9;
    margin-bottom: 2rem;
  }
  
  .hero button {
    background: white;
    color: #667eea;
    border: none;
    padding: 1rem 2.5rem;
    font-size: 1.1rem;
    font-weight: 600;
    border-radius: 50px;
    cursor: pointer;
    transition: transform 0.2s, box-shadow 0.2s;
  }
  
  .hero button:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 20px rgba(0,0,0,0.2);
  }
  
  .features {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 2rem;
    max-width: 900px;
    margin: 0 auto;
  }
  
  .feature {
    background: rgba(255,255,255,0.1);
    padding: 2rem;
    border-radius: 16px;
    text-align: center;
    backdrop-filter: blur(10px);
  }
  
  .feature .icon {
    font-size: 3rem;
    display: block;
    margin-bottom: 1rem;
  }
  
  .feature h3 {
    margin-bottom: 0.5rem;
  }
  
  .feature p {
    opacity: 0.8;
    font-size: 0.9rem;
  }
</style>

<script>
export default {
  title: 'Welcome to My App',
  subtitle: 'Built with LegoDOM – the tiny framework that loves developers',
  buttonText: 'Get Started',
  
  features: [
    { icon: '⚡', title: 'Lightning Fast', description: 'No virtual DOM overhead' },
    { icon: '🧩', title: 'Block-Based', description: 'Reusable building blocks' },
    { icon: '🎨', title: 'Scoped Styles', description: 'CSS that never leaks' }
  ],
  
  handleClick() {
    // We'll wire this up to navigation soon!
    alert('Clicked! Next: we\'ll navigate to /login');
  },
  
  mounted() {
    console.log('Home page mounted!');
  }
}
</script>

Understanding the Structure

Every .lego file has three sections:

1. <template> – Your HTML

html
<template>
  <h1>[[ title ]]</h1>           <!-- Reactive text -->
  <button @click="doSomething()"> <!-- Event binding -->
  <div b-for="item in items">     <!-- Loop directive -->
</template>

2. <style> – Scoped CSS

html
<style>
  self {
    /* 'self' targets the block root (like :host) */
    display: block;
  }
  
  button {
    /* These styles ONLY affect this block */
  }
</style>

3. <script> – Logic & State

html
<script>
export default {
  // Reactive properties
  title: 'Hello',
  count: 0,
  items: [],
  
  // Methods
  doSomething() {
    this.count++;  // Mutation triggers re-render!
  },
  
  // Lifecycle
  mounted() {
    console.log('Block is ready');
  }
}
</script>

Register the Route

Now update src/app.js to show your block:

javascript
import { Lego } from 'lego-dom';
import registerBlocks from 'virtual:lego-blocks';

registerBlocks();

// Add this line:
Lego.route('/', 'home-page');

await Lego.init();

See It Live

bash
npm run dev

Open http://localhost:5173 and you'll see your beautiful home page!

What You've Learned

✅ The three-section .lego file structure
✅ Template syntax: [[ ]] for data, @click for events, b-for for loops
✅ The self keyword for block root styling
✅ How to export state and methods from <script>
✅ Connecting a block to a route

Key Pattern: Block → Route → Display

home-page.lego  →  Lego.route('/', 'home-page')  →  <lego-router> shows it

The filename (minus .lego) becomes the block name. Routes map URLs to block names. The router displays the matched block.


Released under the MIT License.