Software studio and electronics workshop · Costa Adeje, Tenerife

Systems that don’t go down. Devices that work again.

We build software for businesses and repair electronics, right down to soldering the board. Over 15 years in IT, 4 of them here in Tenerife.

What do you need?

Systems in production

We designed and built everything you see here ourselves, and all of it is up and running.

Engineering

The code this very site runs on

Excerpts exactly as they sit in the repository: the request form, contract signing, repair status and workshop hours. Anything we cut is marked “// …”.

Cloudflare Workerssrc/worker.js
if (form.company) return json({ ok: true });

const name = String(form.name ?? '').trim().slice(0, 200);
const contact = String(form.contact ?? '').trim().slice(0, 200);
const about = String(form.about ?? '').trim().slice(0, MAX_LEN);

if (!name || !contact || !about || form.consent !== true) {
  return json({ error: 'validation' }, 400);
}

if (env.TURNSTILE_SECRET) {
  const ip = request.headers.get('cf-connecting-ip');
  const ok = await verifyTurnstile(env.TURNSTILE_SECRET, form.turnstile, ip);
  if (!ok) return json({ error: 'captcha' }, 400);
}

A bot trap plus a Turnstile check: your inbox gets requests from people, and spam is dropped silently.

Cloudflare Workerssrc/contracts.js
export async function sha256Hex(text) {
  return toHex(await crypto.subtle.digest('SHA-256', enc.encode(text)));
}
// …
const now = new Date().toISOString();
await env.DB.prepare(
  `update contracts
      set status = 'signed', signed_at = ?, signer_name = ?, signer_image = ?,
          signer_ip = ?, signer_ua = ?, signed_hash = ?,
          signer_phone = ?, signer_address = ?
    where id = ? and status <> 'signed'`,
)
  .bind(
    // …
    await sha256Hex(row.body),
    // …
  )
  .run();

We record the time, IP, device and a SHA-256 of the text the person saw when signing: the signature can be proven and the document can’t be swapped.

Cloudflare Workerssrc/orders.js
const status = ALL_STATUSES.includes(b.status) ? b.status : row.status;
const now = new Date().toISOString();
// …
if (status !== row.status || clean(b.comment, 500)) {
  await addEvent(env, id, status, clean(b.comment, 500), now);
}

let mailed = false;
if (status === 'ready' && row.status !== 'ready') {
  mailed = await mailOrder(env, 'ready', {
    email: row.client_email,
    lang: row.lang,
    number: row.number,
    device: row.device,
    url: new URL(`/o/${id}`, SITE.url).href,
  });
}

Every status change goes into the history the client sees on their link, and the email goes out once — when the repair is ready.

browsersrc/scripts/shop-status.js
function canary(d) {
  const f = new Intl.DateTimeFormat('en-CA', {
    timeZone: 'Atlantic/Canary', year: 'numeric', month: '2-digit', day: '2-digit',
    hour: '2-digit', minute: '2-digit', hourCycle: 'h23', weekday: 'short',
  });
  const p = Object.fromEntries(f.formatToParts(d).map((x) => [x.type, x.value]));
  const dow = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 }[p.weekday];
  return { date: `${p.year}-${p.month}-${p.day}`, dow, mins: Number(p.hour) * 60 + Number(p.minute) };
}
const toMins = (hhmm) => Number(hhmm.slice(0, 2)) * 60 + Number(hhmm.slice(3, 5));
const workday = (c) => (HOURS[c.dow] && !HOLIDAYS.has(c.date) ? HOURS[c.dow] : null);

export function shopStatus(now = new Date()) {
  const c = canary(now);
  const h = workday(c);
  if (h && c.mins >= toMins(h[0]) && c.mins < toMins(h[1])) return { open: true, closes: h[1] };
  // …
}

The site knows on its own whether the workshop is open: Tenerife time, daylight saving and holidays, from the same source as the data Google reads.

The stack behind our products

Only what HostBase, Hourgrid, Mansaria and this site actually run on. Nothing listed for show.

  • Astro, Web
  • Next.js, Web
  • TypeScript, Web
  • Tailwind CSS, Web
  • Canvas, Web
  • React Native, Mobile
  • Expo, Mobile
  • PostgreSQL, Data
  • Supabase, Data
  • Cloudflare D1, Data
  • Cloudflare R2, Data
  • Workers KV, Data
  • Cloudflare Workers, Server
  • Cron Triggers, Server
  • Netlify, Server
  • Row Level Security, Security
  • Turnstile, Security
  • Web Crypto, Security
  • Stripe, Payments
  • Verifactu, Tax
  • Brevo, Email
  • Anthropic, AI
  • Groq, AI
  • Sentry, Monitoring

Already know what you need? Tick the tasks, the stack and how you want to work — the request builds itself.

Build your project in the configurator

Workshop

How the workshop works

  1. Message us with a photo

    We give you a rough price before you even leave home.

  2. Diagnosis

    A fixed price before we start. If a repair isn’t worth it, we tell you.

  3. Repair

    You follow every step through a link, with before-and-after photos.

  4. Pickup

    3-⁠month warranty on the repair.

Studio

How we work with businesses

The problem first

Before writing a single line, we work out which process is eating your time or money. Sometimes the answer isn’t an app, and we say so.

Parts that already work

We don’t reinvent login, payments or notifications. We spend the time on what is unique to your business.

Everything stays in your name

Code, domain, hosting and database are yours. You can take it all to another team whenever you want.

Measured now, on your device

This page is built the way we build systems: light, fast and free of trackers. Your browser measured these figures as the page loaded.

Page weight
—
Full load
—
Third-party scripts
—
Cookies
—

Visit us

Calle Gran Bretaña, 238660 Costa Adeje · Tenerife

In San Eugenio. If you are coming from far away, message us first so we can make sure we have the part.

28.076 N · 16.733 W

Opening hours

  • Monday to FridayToday10:00–18:00
  • SaturdayToday11:00–17:00
  • Sunday and public holidaysTodayclosed

Tenerife ·

Phone and WhatsApp
+34 624 85 01 60
Telegram
@ifnew
Contact
WhatsApp