ABOUT US

We are a small house of Programmers with focus on delivering high quality software. We believe that successful software projects are made by small teams of capable individuals with high-productivity tools.

Our customers vary from large enterprises and IT service providers to lean product development organizations. We focus on solving customers' challenges together and with the best possible tools. We use lean & agile methods with modern software development tools including, but not limited to Clojure, ClojureScript, JavaScript, Scala, PostgreSQL and MongoDB.

Besides working with customer projects, we do inhouse product, service development, develop and maintain Open Source libraries organize community events (such as ClojuTRE), give out Tech Talks, work with Universities and offer Clojure trainings in Finland. Also have had fun playing with gadgets and some nice Brews

Our world headquarters is located at Tampere Central Square, Aleksis Kiven katu 24 B 37, Tampere. We also have southern Finland branch at Bulevardi 14, 5th floor, Helsinki.

Current status: mostly Clojure & Clojurescript.

SERVICES

  • Consulting
  • Software development
  • Clojure training

OPEN SOURCE

Here are few selected libraries we have open-sourced on GitHub

compojure-api

Sweet web apis with Compojure & Swagger

ring-swagger

Swagger Spec for Clojure Web Apps

schema-tools

Common Clojure(Script) utilities for working with Prismatic Schemas

TAMPERE

TOMMI REIMAN

Programmer

Worked over 17 years as a programmer and hands-on architect, mostly in the telco sector. Architected large SOA, integration and self-service systems and rammed up lean development teams & processes. Into clean, lean and functional - mostly in Clojure & Clojurescript.

MIKKO HEIKKILÄ

Programmer, CEO

Over 16 years of professional software development and consulting, headed large-scale system integration & web projects, programmed, coached development teams and knows all that Agile jazz.

JARPPE LÄNSIÖ

Programmer

When not plotting for world domination with quadrocopters he helps Finnish industry and government organisations to adopt Clojure. 23 years of professional experience in developing business-critical software.

JUHO TEPERI

Programmer

Despite the young age, has solid attitude and awesome skills on fp, web, mobile and Linux.

TUUKKA KATAJA

Programmer

A well-mannered programmer with exquisite skills in web development with JavaScript, ClojureScript and Clojure.

MATTI NIEMINEN

Programmer

Programming jack-of-all-trades with background in developing mission-critical systems for defence and health care. Also in Clojure.

JARI VASELL

Consultant

Jari helps our customers with discovery of new services and revitalization of old ones. He has vast experience in business process digitalization, especially in field service management, smart city and IoT contexts.

PETRI TUOMINEN

UX virtuoso

Petri has extensive knowledge of how to create engaging and smooth user experience for real end-users, be it complex enterprise systems or lean start-up apps.

HELSINKI

MIIKA PIHLAJA

Programmer

With background from both academia and industry, knows his applied maths, data-analysis, statistics & machine learning, but is also proficient full-stack web-app developer.

LASSI IMMONEN

Programmer

Pragmatic problem solver and digital craftsman with over 16 years of software development experience. Likes to use good and productive development tools from backend to user interfaces but most importantly, loves to create something useful for the end users.

MIIKKA KOSKINEN

Programmer

Miikka believes that the judicious use of functional programming, code review, and careful thinking can salvage any codebase. Even in Python.

JOIN US?

If you are looking for new challenges and programming is your thing, check out our open positions.

(defn- destructure-compojure-api-request
  "Returns a vector of four elements:
   - pruned path string
   - new lets list
   - bindings form for compojure route
   - symbol to which request will be bound"
  [path lets arg]
  (let [path-string (if (vector? path) (first path) path)]
    (cond
      ;; GET "/route" []
      (vector? arg) [path-string lets (into arg [:as +compojure-api-request+]) +compojure-api-request+]
      ;; GET "/route" {:as req}
      (map? arg) (if-let [as (:as arg)]
                   [path-string (conj lets +compojure-api-request+ as) arg as]
                   [path-string lets (merge arg [:as +compojure-api-request+]) +compojure-api-request+])
      ;; GET "/route" req
      (symbol? arg) [path-string (conj lets +compojure-api-request+ arg) arg arg]
      :else (throw
              (RuntimeException.
                (str "unknown compojure destruction syntax: " arg))))))

(defn restructure [method [path arg & args] {:keys [routes]}]
  (let [method-symbol (symbol (str (-> method meta :ns) "/" (-> method meta :name)))
        method-kw (if routes :any (-> method meta :name str str/lower-case keyword))
        [parameters body] (extract-parameters args)

        wrap (or routes 'do)

        [lets letks responses middlewares] [[] [] nil nil]
        [path-string lets arg-with-request arg] (destructure-compojure-api-request path lets arg)

        {:keys [lets
                letks
                responses
                middlewares
                parameters
                body]}
        (reduce
          (fn [acc [k v]]
            (restructure-param k v (update-in acc [:parameters] dissoc k)))
          (map-of lets letks responses middlewares parameters body)
          parameters)

        pre-lets [+compojure-api-coercer+ `(memoized-coercer)]

        form `(~wrap ~@body)
        form (if (seq letks) `(letk ~letks ~form) form)
        form (if (seq lets) `(let ~lets ~form) form)
        form (if (seq middlewares) `(route-middlewares ~middlewares ~form ~arg) form)
        form `(~method-symbol ~path ~arg-with-request ~form)
        form (if responses `(body-coercer-middleware ~form ~+compojure-api-coercer+ ~responses) form)
        form (if (seq pre-lets) `(let ~pre-lets ~form) form)

        ;; for routes, create a separate lookup-function to find the inner routes
        child-form (if routes
                     (let [form `(~wrap ~@body)
                           form (if (seq letks) `(dummy-letk ~letks ~form) form)
                           form (if (seq lets) `(dummy-let ~lets ~form) form)
                           form `(fn [~'+compojure-api-request+] ~form)
                           form (if (seq pre-lets) `(let ~pre-lets ~form) form)]
                       form))]

    `(let [childs# ~(if routes [`(~child-form {})] [])]
       (routes/create ~path-string ~method-kw ~parameters childs# ~form))))