Rendering these values. This takes a few seconds.
Download STL
Read this model as text

A MagSafe card wallet that prints as one flat sheet, a few layers high, and folds into shape like a paper kit. It has a pocket for cards, a second pocket for folded bank notes, a seat for a stick-on magnet ring, and an outer flap that pops into a triangle so the wallet doubles as a phone stand and a finger grip. No glue, no loose parts, every function comes from a fold or a cut.

The image shows the solid OpenSCAD renders at cards 4 · cash_room 1 · magnet_diameter 56 · panel_thickness 0.6 · fold_thickness 0.4 · card_play 1 · fold 0 · stand 0 · color_wallet SteelBlue.

MIT

Origami MagSafe wallet and phone stand, folded from one flat print

mick/origami-magsafe-wallet@0.3.0

Remix this
Report

For a legal or policy problem: a license violation, personal data, somebody else’s work republished as their own. A model that prints badly is a comment, not a report.

Sign in to report

0reused0 remixes · 0 imports1downloads1.0.0latest

Parameters

from source
25, steps of 1
02, steps of 0.5
5060, steps of 0.5
0.41, steps of 0.1
0.20.6, steps of 0.02
0.52, steps of 0.25
0100, steps of 5
0100, steps of 10

Showing the render for these values.

Description

What is this

A MagSafe card wallet that prints as one flat sheet, a few layers high, and folds into shape like a paper kit. It has a pocket for cards, a second pocket for folded bank notes, a seat for a stick-on magnet ring, and an outer flap that pops into a triangle so the wallet doubles as a phone stand and a finger grip. No glue, no loose parts, every function comes from a fold or a cut.

What you use it for

Carrying three to five cards and a few notes on the back of a phone with a magnet ring, MagSafe or an Android phone with a ring, propping the phone up on a desk and holding it with two fingers through the flap. Sized to print in one piece on a 180 mm bed (Bambu A1 mini). Print flat with fold = 0. Then fold, always toward the top of the print: the divider up onto the front panel, the front panel over the back, the side flap over the front with both arrow tabs pushed through their slits (one barb first, like a button), and last the stand flap around the bottom with its hook tucked into the top slit. Stick the magnet ring into the shallow groove on the outside of the back panel. For the stand, pull the hook out and tuck it into one of the two lowest slits. The slit just below the top one gives a low loop for your fingers.

Design notes

The bed side becomes the outside, so the wallet shows the plate texture all round and the thin fold layers sit on the outer surface. Folds are bands as wide as what they wrap, not sharp creases, so they bend in a gentle curve.

The back panel faces the phone. A groove one layer deep on its bed side centres the magnet ring. Only the ring is used, no alignment magnet, so it also fits phones that carry just a ring. A slot inside the ring lets your thumb slide the cards up when the wallet is off the phone. Two spring tongues are cut into the lower part of the back panel, each with a low bump on the card side. They press on the stack so cards stay in when the wallet is upside down, and their root points up so a card slides onto them, never against them.

The front panel hangs on one long side of the back and is locked on the other side by a flap with two barbed tabs. Its top edge is a crown: a narrow post in the middle stays at full height, because it carries the slit that holds the stand flap closed, and the edge drops 18 mm on both sides of it. Notes folded in thirds stand about 12 mm proud of those lowered corners, so you take them between thumb and finger with the wallet still on the phone, and a thumb in a corner slides the front card up. The side flap and the fold to the back stop below the lowered edge so the corners stay free. Closed, the top of the stand flap lines up with the lowered edge.

The divider hangs on the bottom of the front panel and folds up inside: cards sit between back and divider, notes between divider and front, both open at the top. Its fold is the floor of the note pocket. The hook of the stand flap lies flat on the notes and works as a light money clip.

The stand flap hangs on the bottom of the back panel and wraps around the bottom of the whole stack, which closes the card pocket. It has one wide crease in the middle and ends in a hook that is folded back, so it enters a slit pointing down, the same way cards go in. Four slits from the top down: closed, finger grip, and two stand angles. Under load the legs want to spread and the hook pulls against the upper edge of its slit, which is what keeps the triangle up. Ribs on the legs stiffen them and hide in the gap the side flap leaves between stand flap and front panel. The crease and the hook bend every day, so they are a single layer and wide. Expect roughly 40 degrees of screen angle upright and a steep 75 to 80 degrees in landscape, where the phone leans on the end of the triangle. The flap length is what the 180 mm bed allows.

Print tips: PETG, 0.2 mm layers, so panels are three layers and folds are two. Set the bottom and top infill pattern to lines at 45 degrees so the lines cross every fold, never run along it. The preview at fold above 0 uses stiff bands with square corners, the real bands curve.

Parameters

cards and cash_room set how thick the two pockets are, and with that the width of every fold band. magnet_diameter is the outer diameter of your stick-on ring, the groove assumes a ring 5 mm wide. panel_thickness and fold_thickness are the two heights in the sheet, keep them multiples of your layer height. card_play is the room around a card. fold and stand are preview only: fold 0 is what you print and 100 shows it folded, stand pops the flap into its triangle once fold is 100 and shows the phone. color_wallet is the display colour.

Use with your agent
{
  "mcpServers": {
    "remixcad": {
      "type": "http",
      "url": "https://remix-cad.vercel.app/api/mcp"
    }
  }
}
get_model("mick/origami-magsafe-wallet@0.3.0")

Returns the manifest, the source, the import closure and the license obligations. Full MCP setup.

Parameter table

Parsed from the Customizer annotations in main.scad
Parameters of Origami MagSafe wallet and phone stand, folded from one flat print, with the ranges the source declares
NameDefaultRangeUnitDescription
cards42 to 5 step 1
cash_room10 to 2 step 0.5
magnet_diameter5650 to 60 step 0.5
panel_thickness0.60.4 to 1 step 0.1
fold_thickness0.40.2 to 0.6 step 0.02
card_play10.5 to 2 step 0.25
fold00 to 100 step 5
stand00 to 100 step 10
color_wallet"SteelBlue"SteelBlue, Silver, Gainsboro, White, DimGray, Black, SlateGray, FireBrick, ForestGreen, Goldenrod

Lineage

0 models depend on this one

Only what this model came from and what came from it.

Remix, the code changed Import, used unchanged and pinned The version you are on Withdrawn, still recorded

License

Whoever downloads this takes these obligations along
  • mick/origami-magsafe-wallet@0.3.0 is MIT

Source

main.scad is the entrypoint
main.scad
// A MagSafe card wallet printed as one flat sheet a few layers high and folded like a
// paper kit: a card pocket, a note pocket, a seat for a magnet ring and an outer flap
// that pops into a triangle as a phone stand and finger grip. Every fold goes toward the
// top of the print, so the bed side becomes the outside. No glue, no loose parts.

/* [Wallet] */
// Number of cards it should hold.
cards = 4; // [2:1:5]
// Room for folded bank notes, in mm.
cash_room = 1; // [0:0.5:2]
// Outer diameter of the stick-on magnet ring.
magnet_diameter = 56; // [50:0.5:60]

/* [Print] */
// Thickness of the panels. Three layers of 0.2.
panel_thickness = 0.6; // [0.4:0.1:1]
// Thickness of the fold lines. Two layers of 0.2.
fold_thickness = 0.4; // [0.2:0.02:0.6]
// Room around a card, per side.
card_play = 1; // [0.5:0.25:2]

/* [Preview] */
// 0 is the flat sheet you print. 100 shows it folded.
fold = 0; // [0:5:100]
// Pops the flap into a phone stand. Works when fold is 100.
stand = 0; // [0:10:100]

/* [Colour] */
// Display only, the STL carries no colour.
color_wallet = "SteelBlue"; // [SteelBlue, Silver, Gainsboro, White, DimGray, Black, SlateGray, FireBrick, ForestGreen, Goldenrod]

/* [Hidden] */
$fn = 64;
card_long = 85.6;
card_short = 54;
card_t = 0.76;
bed = 174;                 // what we allow ourselves of a 180 mm bed

t = panel_thickness;
ft = min(fold_thickness, t);
flex = min(0.2, ft);       // folds that bend every day: one layer

W = max(card_short + 2 * card_play, magnet_diameter + 2);   // back panel, upright
H = card_long + 1;
Wc = W - 1.5;              // front panel, clear of the side fold
inner = cards * card_t + cash_room + 2 * t;   // cards, divider, notes, tab heads
s_bc = inner + 2 * t;      // fold between back and front
s_left = s_bc + t;         // side flap, around the front panel as well
s_bot = s_bc + 2 * t + 0.3;   // stand flap, around the side flap too
s_cd = cash_room + 3 * t;  // fold between front and divider, around the notes
divider_h = 55;

r = 3;                     // corner radius of the panels
edge = r + 1;              // folds stop this far from a corner
flap_w = 10;
neck_w = 12;
neck_l = 2.5;
head_l = 7;
barb = 2;
tip_w = 4;
slit = t + 0.6;

// Crown on the top edge of the front panel: a post in the middle at full height, the
// edge lowered on both sides so notes and cards can be taken at the corners.
front_top = H - 2;
crown_drop = 18;
crown_post_w = 24;
side_top = front_top - crown_drop;

// Stand flap: leg, crease, leg, hook band, hook.
crease_w = 8;
hook_band = 4;
hook_l = 9;
hook_w = 16;
hook_slit = t + 0.8;
flap_len = min(68, bed - H - s_bot - hook_band - hook_l);
leg = (flap_len - crease_w) / 2;
leg_half_w = 26;
// Slit heights on the front panel: closed, then two stand angles and a low finger grip.
y_closed = flap_len + hook_band / 2;
y_stand = [0.58 * flap_len, 0.72 * flap_len, 0.86 * flap_len];

// Magnet ring, high on the back so the wallet hangs low on the phone.
ring_w = 5;
ring_cy = H - magnet_diameter / 2 - 2.5;

// Spring tongues in the back panel that press on the cards, below the ring.
tongue_x = 16;
tongue_w = 8;
tongue_y0 = 10;             // free tip
tongue_y1 = 25;             // root, toward the card opening so cards slide onto it
kerf = 0.8;
bump_h = 0.8;

// Triangle of the stand, for the preview.
l1 = leg + crease_w / 2;
l2 = leg + crease_w / 2 + hook_band / 2;
base = y_stand[0];
alpha = acos((l1 * l1 + base * base - l2 * l2) / (2 * l1 * base));
beta = acos((l2 * l2 + base * base - l1 * l1) / (2 * l2 * base));

f = fold / 100;
k = fold >= 100 ? stand / 100 : 0;
A = 90 * f;                 // each fold band turns 90 degrees at both of its edges
D = 20 * f;                 // tabs dive through their slit
hook_turn = (165 + (10 - beta) * k) * f;

xc0 = W / 2 + s_bc;         // where the front panel starts in the flat sheet

echo(str("Flat sheet: ", W + s_left + flap_w + neck_l + head_l + s_bc + Wc, " x ",
  H + s_bot + flap_len + hook_band + hook_l, " mm"));

// ---- 2D helpers ----
module rounded(rad) { offset(r = rad) offset(delta = -rad) children(); }
// Rounds the inside corners.
module fillet(rad) { offset(r = -rad) offset(delta = rad) children(); }

// A slot with round ends, long side along x.
module slot(l, w) {
  hull() for (s = [-1, 1]) translate([s * (l - w) / 2, 0]) circle(d = w);
}

// The U-shaped cut that frees one spring tongue, root at the top.
module tongue_cut2d(x) {
  difference() {
    translate([x - tongue_w / 2 - kerf, tongue_y0 - kerf]) square([tongue_w + 2 * kerf, tongue_y1 - tongue_y0 + kerf]);
    translate([x - tongue_w / 2, tongue_y0]) square([tongue_w, tongue_y1 - tongue_y0 + 1]);
  }
}

// ---- Back panel: phone side ----
module back3d() {
  difference() {
    linear_extrude(height = t)
      difference() {
        rounded(r) translate([-W / 2, 0]) square([W, H]);
        // thumb slot inside the ring, to slide the cards up
        translate([0, ring_cy]) rotate(90) slot(36, 16);
        for (s = [-1, 1]) tongue_cut2d(s * tongue_x);
      }
    // groove one layer deep on the bed side that centres the magnet ring
    translate([0, ring_cy, -0.01])
      linear_extrude(height = 0.21)
        difference() {
          circle(d = magnet_diameter + 0.6);
          circle(d = magnet_diameter - 2 * ring_w - 0.6);
        }
  }
  // low bump near the tip of each tongue, on the card side
  for (s = [-1, 1])
    translate([s * tongue_x, tongue_y0 + 3.5, t - 0.01]) cylinder(h = bump_h, d1 = 6.5, d2 = 3);
}

// ---- Front panel and divider, to the right of the back in the flat sheet ----
// A point that ends up at folded x sits at xc0 + W/2 - x in the sheet.
module front2d() {
  difference() {
    fillet(3) rounded(r) {
      translate([xc0, 1]) square([Wc, side_top - 1]);
      translate([xc0 + W / 2 - crown_post_w / 2, 1]) square([crown_post_w, front_top - 1]);
    }
    // slits for the two barbed tabs of the side flap
    for (y = tab_y())
      translate([xc0 + W - flap_w - 0.2 - slit / 2, y]) rotate(90) slot(neck_w + 1.5, slit);
    // slits for the hook of the stand flap
    for (y = concat([y_closed], y_stand))
      translate([xc0 + W / 2, y]) slot(hook_w + 1, hook_slit);
  }
}

module band_bc2d() { translate([W / 2 - 0.05, edge + 1]) square([s_bc + 0.1, side_top - 2 * edge - 1]); }

module band_cd2d() { translate([xc0 + edge, 1 - s_cd - 0.05]) square([Wc - 2 * edge, s_cd + 0.1]); }

module divider2d() {
  difference() {
    rounded(r) translate([xc0 + 1, 1 - s_cd - divider_h]) square([Wc - 2, divider_h]);
    // scoop in what becomes the top edge of the divider
    translate([xc0 + W / 2, 1 - s_cd - divider_h - 3]) circle(r = 10);
  }
}

// ---- Side flap, drawn on the right and mirrored to the left ----
// It stops below the lowered edge of the front panel, so that corner stays free.
flap_top = side_top - 2;
function tab_y() = [edge + 0.24 * (flap_top - edge), edge + 0.76 * (flap_top - edge)];

module band_side2d() { translate([W / 2 - 0.05, edge]) square([s_left + 0.1, flap_top - edge]); }

module flap2d() {
  x0 = W / 2 + s_left;
  hull() {
    translate([x0 - 0.01, edge]) square([0.02, flap_top - edge]);
    for (y = [edge + 5, flap_top - 5]) translate([x0 + flap_w - 2, y]) circle(r = 2);
  }
}

module tab2d(yc) {
  x1 = W / 2 + s_left + flap_w;
  hw = neck_w + 2 * barb;
  translate([x1 - 0.01, yc - neck_w / 2]) square([neck_l + 1, neck_w]);
  hull() {
    for (s = [-1, 1]) translate([x1 + neck_l + 0.75, yc + s * (hw / 2 - 0.75)]) circle(d = 1.5);
    translate([x1 + neck_l + head_l - tip_w / 2, yc]) circle(d = tip_w);
  }
}

// ---- Stand flap, below the back panel ----
module band_bot2d() { translate([-(W / 2 - edge), -s_bot - 0.05]) square([W - 2 * edge, s_bot + 0.1]); }

// One leg between y0 and y0 + len, with two ribs on the print top.
module leg3d(y0, len) {
  linear_extrude(height = t) rounded(2) translate([-leg_half_w, y0]) square([2 * leg_half_w, len]);
  for (x = [-12, 12]) translate([x - 0.8, y0 + 2, t - 0.01]) cube([1.6, len - 4, t]);
}

module strip2d(half_w, y0, len) { translate([-half_w, y0 - 0.05]) square([2 * half_w, len + 0.1]); }

module hook2d(y_top) {
  hull() {
    translate([-hook_w / 2, y_top - 0.02]) square([hook_w, 0.02]);
    for (s = [-1, 1]) translate([s * (hook_w / 2 - 3), y_top - hook_l + 3]) circle(r = 3);
  }
}

// ---- Folding ----
module ext(h) { linear_extrude(height = h) children(); }
// Turn the children around a fold line on the bed: along x at height y, or along y at x.
module hinge_x(y, a) { translate([0, y, 0]) rotate(a = a, v = [1, 0, 0]) translate([0, -y, 0]) children(); }
module hinge_y(x, a) { translate([x, 0, 0]) rotate(a = a, v = [0, 1, 0]) translate([-x, 0, 0]) children(); }

module front_chain() {
  hinge_y(W / 2, -A) {
    ext(ft) band_bc2d();
    hinge_y(xc0, -A) {
      ext(t) front2d();
      hinge_x(1, -A) {
        ext(ft) band_cd2d();
        hinge_x(1 - s_cd, -A) ext(t) divider2d();
      }
    }
  }
}

module side_chain() {
  hinge_y(W / 2, -A) {
    ext(ft) band_side2d();
    hinge_y(W / 2 + s_left, -A) {
      ext(t) flap2d();
      for (y = tab_y()) hinge_y(W / 2 + s_left + flap_w, -D) ext(t) tab2d(y);
    }
  }
}

module stand_chain() {
  y1 = -s_bot;                 // start of the first leg
  y2 = y1 - leg;               // start of the crease
  y3 = y2 - crease_w;          // start of the second leg
  y4 = y1 - flap_len;          // start of the hook band
  y5 = y4 - hook_band;         // start of the hook
  turn = (alpha + beta) * k / 2;
  hinge_x(0, -A) {
    ext(ft) band_bot2d();
    hinge_x(y1, -(A - alpha * k)) {
      leg3d(y2, leg);
      hinge_x(y2, -turn) {
        ext(flex) strip2d(22, y3, crease_w);
        hinge_x(y3, -turn) {
          leg3d(y4, leg);
          hinge_x(y4, -hook_turn / 2) {
            ext(flex) strip2d(hook_w / 2, y5, hook_band);
            hinge_x(y5, -hook_turn / 2) ext(t) hook2d(y5);
          }
        }
      }
    }
  }
}

module wallet() {
  back3d();
  front_chain();
  mirror([1, 0, 0]) side_chain();
  stand_chain();
}

color(color_wallet) wallet();

// Preview only: the magnet ring once folded, the phone once the stand is out.
if (fold > 0)
  color("Goldenrod") translate([0, ring_cy, -0.8])
    linear_extrude(height = 1) difference() {
      circle(d = magnet_diameter);
      circle(d = magnet_diameter - 2 * ring_w);
    }
if (k > 0)
  color("DimGray") translate([-35.5, ring_cy - 80, -8.8])
    linear_extrude(height = 8) rounded(8) square([71, 147]);

Comments

Context, not a score. Comments never move a model up or down the results.

No comments yet

Printed it? A note about your material and the clearance you landed on saves the next person a failed print.

Sign in to comment