# Mailbox

> A mailbox in two styles: a US rural mailbox with a rounded tunnel body on a wooden post, a front door with handle and a side flag that can be raised or lowered, or a round pillar post box with a domed cap, letter slot, door panel and collection plaque. Pick the color for suburban streets, farms, villages and city sidewalks.

![Mailbox preview](https://codels.download/m/mailbox.png)

Multi-view sheet (3/4, front, side, top): https://codels.download/m/mailbox.sheet.png

## Facts

- Category: Urban & Street › Street Furniture
- Size (W × H × D): 0.28 × 1.42 × 0.58 m — units are meters, +Y up, front faces +Z
- Origin: center of the base (y = 0)
- Triangles: 348 · Meshes: 13 · Materials: 4
- License: CC0-1.0 (Codels built-in)
- Tags: mailbox, cartoon, low-poly, stylized, farm, modern, city, road, village, city-builder, decoration, interactable, prop, street-furniture, metal, wood, mobile-friendly, parametric, color-brown, color-red, size-medium, poly-low
- Page: https://codels.download/models/mailbox

## Files

| Format | URL |
|---|---|
| three.js ES module (`createMailbox()`) | https://codels.download/m/mailbox.js |
| React Three Fiber component (`<Mailbox />`) | https://codels.download/m/mailbox.jsx |
| Instancing module (`createMailboxInstances(count, place)`, one draw call per material) | https://codels.download/m/mailbox.instanced.js |
| Standalone HTML demo | https://codels.download/m/mailbox.html |
| glTF binary | https://codels.download/m/mailbox.glb |
| glTF binary, Meshopt-compressed (2–3× smaller; GLTFLoader needs `setMeshoptDecoder(MeshoptDecoder)`) | https://codels.download/m/mailbox.glb?compress=meshopt |
| glTF JSON | https://codels.download/m/mailbox.gltf |
| OBJ (vertex colors) + MTL | https://codels.download/m/mailbox.obj · https://codels.download/m/mailbox.mtl |
| STL | https://codels.download/m/mailbox.stl |
| CodelSpec JSON | https://codels.download/m/mailbox.json |

## Parameters

Append them as query parameters to any URL above to get a customized variant (e.g. `?style=...`).

| Param | Type | Range / options | Default | Current |
|---|---|---|---|---|
| `style` | select | us \| postbox | us | us |
| `color` | color | #rrggbb | #c23a2e | #c23a2e |
| `flag` | boolean | true \| false | true | true |

## Parts

- post (box · wood)
- postCap (box · wood)
- board (box · wood)
- brace (box · wood)
- body (extrude · body)
- rib (extrude · body)
- rib (extrude · body)
- door (extrude · body)
- backCap (extrude · dark)
- doorHandle (box · dark)
- flag (group)
  - flagArm (box · flag)
  - flagPlate (box · flag)
  - flagPivot (cylinder · dark)

## How to use

Save the code below as `mailbox.js`, then:

```js
import { createMailbox } from './mailbox.js';
const model = createMailbox();
scene.add(model);
```

## Code

```js
/**
 * Mailbox — Codels 3D model library (https://codels.download/models/mailbox)
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 348 · Size (W × H × D): 0.28 × 1.42 × 0.58 m
 *
 * Usage:
 *   import { createMailbox } from './mailbox.js';
 *   
 *   const model = createMailbox();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
  const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
  for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
  const options = bevel
    ? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
    : { depth, bevelEnabled: false };
  return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}

export function createMailbox() {
  const root = new THREE.Group();
  root.name = 'Mailbox';

  // Materials
  const bodyMat = new THREE.MeshStandardMaterial({ name: 'body', color: 0xc23a2e, roughness: 0.5, metalness: 0.3, flatShading: true });
  const woodMat = new THREE.MeshStandardMaterial({ name: 'wood', color: 0x8a6845, roughness: 0.9, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x24282c, roughness: 0.6, metalness: 0.3, flatShading: true });
  const flagMat = new THREE.MeshStandardMaterial({ name: 'flag', color: 0xf2c230, roughness: 0.6, flatShading: true });

  // Shared geometries
  const extrudeGeo = extrude([[-0.128, -0.008], [0.128, -0.008], [0.128, 0.13], [0.1217, 0.1696], [0.1036, 0.2052], [0.0752, 0.2336], [0.0396, 0.2517], [0, 0.258], [-0.0396, 0.2517], [-0.0752, 0.2336], [-0.1036, 0.2052], [-0.1217, 0.1696], [-0.128, 0.13]], 0.025);

  // Parts
  const post = new THREE.Mesh(new THREE.BoxGeometry(0.1, 1.02, 0.1), woodMat);
  post.name = 'post';
  post.position.set(0, 0.51, -0.02);
  root.add(post);
  const postCap = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.04, 0.16), woodMat);
  postCap.name = 'postCap';
  postCap.position.set(0, 1.03, -0.02);
  root.add(postCap);
  const board = new THREE.Mesh(new THREE.BoxGeometry(0.2, 0.04, 0.5), woodMat);
  board.name = 'board';
  board.position.set(0, 1.07, 0);
  root.add(board);
  const brace = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.3, 0.05), woodMat);
  brace.name = 'brace';
  brace.position.set(0, 0.885, 0.125);
  brace.rotation.set(deg(40), 0, 0);
  root.add(brace);
  const body = new THREE.Mesh(extrude([[-0.12, 0], [0.12, 0], [0.12, 0.13], [0.1141, 0.1671], [0.0971, 0.2005], [0.0705, 0.2271], [0.0371, 0.2441], [0, 0.25], [-0.0371, 0.2441], [-0.0705, 0.2271], [-0.0971, 0.2005], [-0.1141, 0.1671], [-0.12, 0.13]], 0.48), bodyMat);
  body.name = 'body';
  body.position.set(0, 1.09, 0);
  root.add(body);
  const rib = new THREE.Mesh(extrudeGeo, bodyMat);
  rib.name = 'rib';
  rib.position.set(0, 1.09, -0.19);
  root.add(rib);
  const rib2 = new THREE.Mesh(extrudeGeo, bodyMat);
  rib2.name = 'rib';
  rib2.position.set(0, 1.09, 0.12);
  root.add(rib2);
  const door = new THREE.Mesh(extrude([[-0.132, -0.012], [0.132, -0.012], [0.132, 0.13], [0.1255, 0.1708], [0.1068, 0.2076], [0.0776, 0.2368], [0.0408, 0.2555], [0, 0.262], [-0.0408, 0.2555], [-0.0776, 0.2368], [-0.1068, 0.2076], [-0.1255, 0.1708], [-0.132, 0.13]], 0.025), bodyMat);
  door.name = 'door';
  door.position.set(0, 1.09, 0.25);
  root.add(door);
  const backCap = new THREE.Mesh(extrude([[-0.126, -0.006], [0.126, -0.006], [0.126, 0.13], [0.1198, 0.1689], [0.1019, 0.2041], [0.0741, 0.2319], [0.0389, 0.2498], [0, 0.256], [-0.0389, 0.2498], [-0.0741, 0.2319], [-0.1019, 0.2041], [-0.1198, 0.1689], [-0.126, 0.13]], 0.02), darkMat);
  backCap.name = 'backCap';
  backCap.position.set(0, 1.09, -0.245);
  root.add(backCap);
  const doorHandle = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.03, 0.05), darkMat);
  doorHandle.name = 'doorHandle';
  doorHandle.position.set(0, 1.32, 0.28);
  root.add(doorHandle);
  const flag = new THREE.Group();
  flag.name = 'flag';
  flag.position.set(0.14, 1.16, -0.14);
  root.add(flag);
  const flagArm = new THREE.Mesh(new THREE.BoxGeometry(0.018, 0.26, 0.03), flagMat);
  flagArm.name = 'flagArm';
  flagArm.position.set(0, 0.13, 0);
  flag.add(flagArm);
  const flagPlate = new THREE.Mesh(new THREE.BoxGeometry(0.018, 0.1, 0.14), flagMat);
  flagPlate.name = 'flagPlate';
  flagPlate.position.set(0, 0.21, -0.07);
  flag.add(flagPlate);
  const flagPivot = new THREE.Mesh(new THREE.CylinderGeometry(0.02, 0.02, 0.03, 6), darkMat);
  flagPivot.name = 'flagPivot';
  flagPivot.position.set(-0.012, 0, 0);
  flagPivot.rotation.set(0, 0, deg(90));
  flag.add(flagPivot);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createMailbox;
```

---
Codels — 3D models as code for three.js. Search more: https://codels.download/api/v1/models?q=<query> · Guide: https://codels.download/llms.txt
