Nanc es un nuevo tipo de CMS para aplicaciones Flutter y no solo para ellas. Es un CMS independiente del backend que no extrae su propio backend. Y te permite actualizar las aplicaciones de Flutter sin volver a publicarlas en las tiendas. ¡Y aquí puedes jugar con aplicaciones de demostración!
¡Hola! Hoy quiero presentarles el fruto de mis meses de trabajo por las noches y los fines de semana, diseñado para mejorar la experiencia de administración de contenido y brindar funciones adicionales al mundo del desarrollo de aplicaciones Flutter: un nuevo tipo de CMS.
Estamos hablando de Nanc, que no es unCMSnormal . Por qué "no es normal" y qué puede hacer con él, lo descubrirá después de leer este artículo.
El artículo contendrá no solo teoría sino también "práctica": podrá jugar en el entorno limitado de Nanc. Para mostrar al público las capacidades de Nanc, se crearon dos aplicaciones de demostración: una aplicación de cliente que imita cualquier aplicación Flutter y otra que da una idea de lo que puede hacer una aplicación Nanc basada en Flutter: Nanc CMS precompilado. Y la aplicación Nanc CMS, que es un CMS preconfigurado con una capa adicional de lógica implementada para sincronizar la aplicación cliente con el CMS.
Al final de la mayoría de los bloques lógicos del texto, encontrará un video de YouTube con un ejemplo de cómo usar/demostrar algún aspecto de Nanc.
Tabla de contenido
Introducción
Acerca de CMS
tipos de modelos
Recopilación
Solo
Editor
Descripción general
Código primero
Interfaz primero
Modo híbrido
Campos
bool
Color
Fecha
Dinámica
enumeración
Encabezamiento
Icono
Identificación
multiselector
Número
Selector
Cadena
Estructura
Pantalla
Aplicaciones dinámicas de aleteo
Documentación interactiva
Extensibilidad
Sencillez
El poder
Conveniencia
Actuación
Aplicaciones de demostración de Nanc
General
Cliente
Administración
Administrador de conexión
Lo que sigue / Epílogos
Acerca de Nanc CMS
Entonces. Nanc es un CMS independiente del backend que no extrae su propio backend. ¿Como funciona? Nanc ofrece implementar interfaces de servicio de red, que en este momento tienen 6 métodos pero tendrán alrededor de 10 para el momento del lanzamiento. ¿Esto es mucho o poco? Por ejemplo, se necesitaron 170 líneas de código para implementar la API para la aplicación de demostración. Estos métodos son responsables de todo el trabajo de Nanc con su backend existente. La implementación debe estar escrita en Dart (el lenguaje de desarrollo para Flutter también). En el futuro, Nanc vendrá con implementaciones listas de estas interfaces para ciertas opciones de back-end: Firebase, Supabase, SQLite local/de red e implementaciones genéricas de REST y GraphQL (¿quizás algo más?) y no tendrá que pensar en esta implementación en todo o tendrá que hacerlo, pero sólo un poco.
tipos de modelos
Un modelo en Nanc es una descripción estructural de una entidad que desea controlar con Nanc. Un modelo contiene un nombre de entidad, varios parámetros visuales y una descripción de los campos.
Recopilación
Una colección es una entidad que puede tener muchas instancias. Una lista de usuarios, libros y reseñas son buenos ejemplos de modelos de tipo Colección en Nanc.
Si está familiarizado con las bases de datos relacionales, un ejemplo de una Colección en Nanc sería casi cualquier tabla de su base de datos.
Solo
Un solo (modelo) es una entidad que existe en una sola instancia. Por ejemplo: Cambios de función o una configuración de algo, o... "La pantalla principal de una aplicación móvil". En términos generales, los modelos Solo están diseñados para aumentar la usabilidad, siendo solo una proyección de su base de datos. Y un modelo Solo podría ser fácilmente cualquier tabla en su base de datos con un solo registro. Pero por el momento, la implementación de esta clase de modelos requiere que el registro de este modelo (fila en la base de datos) tenga un id igual al id del propio modelo.
final Model landingPage = Model( name: 'Landing page', /// ? id in format [toSnakeCase(name)] will be set automatically, if omitted // id: 'landing_page', isCollection: false, icon: IconPackNames.flu_document_page_break_regular, fields: [ ...
Editor
Descripción general
Nanc se puede configurar de varias maneras: por código, a través de la propia interfaz de Nanc y una combinación de estas opciones.
Configuración de código primero
Cuando digo "configuración", me refiero, en primer lugar, a describir la estructura de sus modelos. Tomemos un ejemplo simple, el modelo de características, que es una entidad que describe las características de un producto. Esta entidad contiene los siguientes campos:
identificación
título
imagen
descripción
Y la implementación como una configuración de código primero será la siguiente:
Al describir dicho modelo y usarlo en Nanc CMS, todas las operaciones CRUD de ese modelo estarán disponibles para usted.
Primera configuración de la interfaz
Podríamos crear exactamente el mismo modelo de características (llamémoslo Variante de características) a través de la interfaz de Nanc. Y (teniendo en cuenta que todo el trabajo preparatorio para usar Nanc ya está hecho), cuando crea un modelo en Nanc, inmediatamente creará una tabla en la base de datos, y todo el CRUD también estará disponible para usted de inmediato.
Además, puede tomar la forma más segura de no crear nada en la base de datos cuando crea un modelo a través de la interfaz de Nanc. Y cree de forma independiente una tabla en su base de datos y luego, debajo de ella, cree un modelo en Nanc. Por cierto, esto es lo que debe hacer si describe la configuración en el código: las nuevas tablas no aparecerán en su base de datos.
Configuración híbrida
Esta opción está disponible para usted cuando tiene una configuración Code-first y decide cambiarla a través de la interfaz de Nanc. En este caso, todos los cambios posteriores a este modelo solo serán posibles a través de la interfaz y los cambios realizados en el modelo de código original se ignorarán. La única forma de volver a Code-first es "restablecer" el modelo, en cuyo caso se borrarán todos los cambios en la estructura del modelo realizados a través de la interfaz y se volverá a utilizar la configuración de Code-first. Ningún dato se ve afectado por este restablecimiento. Sólo afecta a la estructura del modelo.
Campos
Ahora veamos qué tipos de campos admite actualmente Nanc.
booleano
BoolField le permite controlar el tipo de datos bool y personalizar el valor predeterminado.
Color
ColorField le proporciona un práctico selector de color que le permite elegir un color inmediatamente en Nanc. También le brinda la posibilidad de realizar cambios manualmente, editando el código AHEX. AHEX es un HEX-Color clásico (por ejemplo, #10A0CF ), pero con un valor de transparencia adicional especificado primero. En este caso, este color sería similar al color #FF10A0CF ( FF es 100% de opacidad - el color es completamente opaco). Y así es como se vería el mismo color con un 50 % de opacidad: #7F10A0CF .
Fecha
DateField es responsable de controlar la fecha y la hora (ambos valores a la vez, se implementarán los separados para la fecha y la hora más adelante). DateField contiene dos parámetros booleanos que le permiten modificar el comportamiento de este campo convirtiéndolo en una marca de tiempo de creación de entidad y una marca de tiempo de cambio.
Dinámica
DynamicField, por un lado, es un campo muy simple, pero por otro lado, incluye toda la complejidad de los otros campos. Inicialmente, puede configurar solo la apariencia de este campo (cómo se verá en la interfaz de Nanc: el color y el ícono que lo acompaña). Después de eso, este campo puede contener cualquier valor disponible en Nanc, incluido él mismo. ¿Qué quiere decir esto? Esencialmente, DynamicField es un JSON escrito con la capacidad de colocar campos en orden dentro de sí mismo.
enumeración
EnumField es un campo para seleccionar un valor de múltiples valores. La regla a seguir al seleccionar un EnumField es que si tiene una lista final de valores para seleccionar que no está almacenada en una tabla de base de datos separada, elija Enum. De lo contrario, elija SelectorField, que se analiza con más detalle a continuación. TODO: Por el momento este campo solo se puede configurar a través de CodeConfig, la configuración a través de la interfaz no se resuelve.
Encabezamiento
HeaderField no es realmente un campo, sino un potenciador visual para su modelo en Nanc. Puede usar este no campo para establecer un encabezado común para un grupo de campos relacionados, o para distinguir los campos del modelo entre sí usando HeaderField como delimitador.
Icono
IconField le brinda la posibilidad de seleccionar un ícono (clase IconData ) de un conjunto predefinido de íconos. Actualmente hay alrededor de 25,000 de ellos, y este conjunto incluye los siguientes íconos:
Si es necesario, se pueden agregar otros íconos al conjunto básico de entrega y, en un futuro no muy lejano, también habrá una opción para usar sus propios íconos.
Uno podría preguntarse: "Los íconos están ahí, los colores están ahí, ¿pero las fuentes?" Si lo hizo, puede encontrar la respuesta en la documentación del widget de texto . La respuesta corta es que todas las fuentes de están disponibles para usted.
Identificación
IdField es un campo tan simple pero tan importante. Todo modelo gestionado por Nanc debe tener al menos un campo de tipo Id. Actualmente, solo se admite el tipo de ID de cadena (puede ser cualquier cadena única dentro de una entidad). También hay planes para agregar soporte para el tipo numérico, que, sin embargo, se puede implementar incluso ahora simplemente convirtiendo los datos de campo en el tipo numérico en la implementación de la API.
Multiselector
MultiSelectorField es un campo bastante complejo que es responsable de implementar una relación relacional de muchos a muchos o de muchos a uno. Hay tres modos de usar este campo. Repasemos cada uno de ellos con más detalle. TODO: Por el momento este campo solo se puede configurar a través de CodeConfig, no se trabaja la configuración a través de la interfaz.
matriz de identificaciones
Este modo le brinda la capacidad de almacenar la id de entidades relacionadas en la entidad principal directamente. Por ejemplo, tenemos dos modelos: Reader y Book. En este modo, los libros tomados por el lector se contabilizarán como identificadores almacenados en el campo Modelo del lector. Por ejemplo como este:
Arriba hay una estructura de tabla de ejemplo expresada usando la sintaxis JSON5.
La desventaja de este modo es la integridad limitada de los datos. Si no implementa la eliminación automática de ID de libros obsoletos (eliminados) del campo Lector books , obtendrá errores.
Tercera mesa
El modo clásico de proporcionar relaciones del mundo SQL. Al usar este modo, almacena las relaciones entre entidades en una tabla separada y garantiza la integridad de los datos al 100 %. La siguiente estructura es un ejemplo de este modo:
En el séptimo segundo, puede ver una ligera contracción y, si observa detenidamente, puede notar que la URL de la página ha cambiado; así es como traté de ocultar el error: en el modo de tercera tabla, los datos se guardan en la página principal solo si ya se ha guardado 🤷🏼
Matriz de objetos
Generalmente similar a Array of ids, excepto que el registro principal no almacena identificadores, sino el objeto completo (como una estructura plana, sin posibles entidades asociadas del registro anidado). Tiene la misma desventaja que Array of ids, pero tiene una adicional: mayor uso del almacenamiento. Sin embargo, hay (al menos por el momento) un área de aplicación de este modo, y es muy importante. Pero hablaremos de esto un poco más tarde.
Me estoy adelantando en el video, mostrando ScreenField, volveremos a esto
En general, existe la idea de hacer que los modos "no canónicos" sean virtuales, para que de alguna manera funcionen a través de la Tercera tabla, y los datos necesarios se carguen al editar la página (si es necesario).
Número
NumberField almacena números, así de simple.
Selector
SelectorField es similar a MultiSelectorField (como puede adivinar por sus nombres), pero un poco más simple: la relación aquí es de uno a uno o de uno a muchos, y hay dos modos. TODO: Por el momento este campo solo se puede configurar a través de CodeConfig, la configuración a través de la interfaz no se resuelve.
Identificación
Una forma común de provisión de enlace SQL, donde el campo de registro principal almacena la ID del registro vinculado. Tomemos el Reader como ejemplo. ¿Quién es? En primer lugar, es una persona, y ¿qué tiene una persona? ¡Así es! La ciudad de nacimiento (que nuestra Biblioteca, por alguna razón, también quería saber).
Muy similar al Array de objetos de MultiSelectorField, pero almacenaremos un único valor asociado en el campo del registro padre. Las desventajas son las mismas, las ventajas también se describirán un poco más abajo.
Cadena
StringField almacena cadenas. Este campo tiene una configuración personal responsable de la conveniencia de editar en Nanc: el parámetro que limita la altura máxima del campo editable. Si su texto será grande, tiene sentido no especificarlo en absoluto, entonces el campo se ajustará a la altura del texto. Si se limita a grande, puede especificar una altura de campo explícita (en líneas) y siempre será así. Y finalmente, para cadenas cortas, puede configurarlo en una línea, y luego el campo no se expandirá sin importar cuánto escriba después.
Estructura
StructureField le permite almacenar una matriz de estructuras tipeadas en registros modelo. Usted especifica el tipo de datos que se almacenarán y puede administrarlos de manera fácil y sencilla. Los tipos disponibles para los campos de estructura son absolutamente todo. Por lo tanto, puede crear fácilmente una "Repetición de campo de estructura dinámica". TAREAS: Solo se pueden agregar campos "planos" a StructureField dentro de la demostración.
Pantalla
ScreenField es un campo que te permite escribir una aplicación completa en Flutter, ¡directamente en Nanc! Con ScreenField puede describir la interfaz de una sola... pantalla, actualizarla como desee y hacerlo en cualquier momento en minutos, sin la tediosa y estresante espera de las revisiones de Apple y Google.
Analicemos este tipo de campo (y en realidad una rama funcional completamente separada de Nanc) con un poco más de detalle.
Aplicaciones dinámicas de aleteo
Con ScreenField, realmente puede crear una interfaz de casi cualquier complejidad directamente en su navegador (y su IDE) y luego, sin hacer una publicación en stock, actualizar la pantalla correspondiente en su aplicación. Si necesita verificar hipótesis rápidamente, esta es una gran característica. Esta funcionalidad es excelente para páginas relativamente simples (en términos de lógica) en su aplicación, que, sin embargo, deben cambiar con bastante frecuencia. En el futuro, esta funcionalidad se expandirá a un estado en el que realmente puede crear lo que quiera sin restricciones. Ahora veamos todos los aspectos de la creación de pantallas dinámicas con Nanc.
Documentación interactiva
Hay muchos widgets en Flutter. Muchos de ellos. ¿Qué es un widget? Es un bloque de funcionalidad a partir del cual ensambla su aplicación. Puede ser solo visual o puede ser lógico, con algún comportamiento interno. Nanc proporciona una extensa lista de widgets implementados que puede usar para crear su interfaz de usuario. Pero cuantas más posibilidades, más difícil es aprender sobre ellas... Así que el editor de pantalla en Nanc le da acceso a una documentación interactiva donde puede averiguar qué widgets están implementados actualmente, qué parámetros y propiedades configurables tienen, y, directamente en la documentación, vea cómo afectan la apariencia de la interfaz que crea.
Sencillez
Nanc le permite crear una interfaz en tiempo real, pero lo más importante: le permite hacerlo de manera muy fácil y rápida (tomó un poco más de 2 horas para crear una interfaz con una aplicación de demostración). Pero surge la pregunta: ¿cómo crear la interfaz de usuario en sí? No existe una sintaxis exótica para describir la interfaz de usuario en Nanc, ni soluciones "demasiado" simples, como JSON largo, que te harán odiar la creación de interfaces en Nanc.
El resultado de encontrar la mejor solución es una sintaxis XML simple y directa. Todos los widgets estándar de Flutter tienen exactamente los mismos nombres, pero en formato XML. Por ejemplo, el widget SizedBox en Nanc sería <sizedBox>...</sizedBox> , y esta regla se aplica a todos los widgets sin excepción. Si el widget tiene alguna propiedad compleja, tendrá el mismo nombre (o más simple) que XML, con el prefijo prop . Por ejemplo, el widget Container tiene una propiedad compleja boxDecoration , que tiene sus propias propiedades internas. Entonces, esta propiedad en Nanc tendrá el siguiente aspecto: <prop:decoration>...</prop:decoration> . Esta regla se aplica a todas las propiedades complejas. Y el último aspecto es que los argumentos que son relativamente simples son parámetros de etiquetas XML. Tomemos el mismo SizedBox como ejemplo:
<sizedBox width="50" height="50"> ... </sizedBox>
Para algunos widgets, se implementan argumentos adicionales para simplificar la escritura de código, y para SizedBox es el argumento ize el que establece tanto width como height .
Todo lo escrito aquí está en la documentación en línea, por lo que si olvida algo o quiere saber algo, consúltelo y encuentre respuestas a todas sus preguntas allí.
Extensibilidad
Implemente el soporte para el nuevo widget: una cuestión de 10 minutos a unas pocas horas. En este punto, casi todos los widgets básicos están implementados, de los cuales puede crear una interfaz compleja con lógica. Con el tiempo, todos los widgets disponibles en Flutter se implementarán en Nanc y realmente puedes hacer todo. Pero eso no es todo. Puede implementar fácil y simplemente sus propios widgets y usarlos en Nanc con una o dos líneas de código XML. Por ejemplo, no hay ningún widget en la biblioteca estándar de Flutter que le permita mostrar fácilmente el Control deslizante de carrusel con imágenes. Tendrá que escribir una implementación usted mismo o usar alguna solución de código abierto como . Y, habiendo implementado lo que necesita, puede integrar fácilmente su widget en Nanc y usarlo.
El poder
Nanc proporciona más que solo la capacidad de convertir código XML en una interfaz en Flutter. Nanc proporciona capacidades de creación de plantillas y escritura lógica. Representación de elementos condicionales, dibujo de bucles, manejo de toques: esto ya está en la versión actual 0.0.1 de Nanc.
Hasta ahora, la parte de la lógica es bastante sencilla: admite la interacción a través de toques y el manejo de eventos en su código '.dart' escrito con anticipación, pero eventualmente esta parte de Nanc se expandirá considerablemente, permitiéndole escribir la lógica en Dart directamente en el navegador. y haz que funcione en tu aplicación también.
El enfoque para manejar los clics de los usuarios es el siguiente: puede definir una lista de "acciones" que el usuario puede realizar en su aplicación. Por ejemplo: abra la pantalla de la aplicación interna, haga clic en el enlace externo, muestre SnackBar, abra una ventana modal y muchas otras cosas, y cree un controlador para tales acciones por adelantado. Y luego usa esa acción de la forma que quieras en Nanc. Para obtener más información sobre el manejo de eventos, consulte la documentación del widget InkWell en Nanc.
Conveniencia
Nanc tiene un editor XML incorporado, pero no es muy útil. No se puede buscar (todavía), no es muy rápido con mucho código y no tiene autocompletado. ¿Cómo vivir con eso? Por ejemplo, deje que el usuario use su IDE favorito y vea los cambios en Nanc en tiempo real. Déjame enseñarte como. Y esta es la Web (que es con lo que hay que jugar):
En el futuro se agregará soporte de autocompletar, quizás en un futuro lejano... Intenté profundizar en XML Schema, pasé varios días, pero hasta ahora no pude 🤷🏼
Actuación
Por separado, me gustaría mencionar el rendimiento (interfaz de dibujo de XML en dispositivos móviles). En resumen, es idéntico al rendimiento de Flutter, sin sobrecarga. Por el momento, la "pantalla" es una lista de widgets renderizada perezosamente (SliverList), creada de forma asíncrona. Más tarde, esta implementación se refinará para comenzar a representar los widgets de forma asíncrona, pero a su vez, el tiempo necesario para mostrar el contenido será igual al tiempo que se tarda en representar el primer widget descrito en el XML.
Aplicaciones de demostración de Nanc
General
Para demostrar las capacidades, se ha creado un conjunto público de aplicaciones de demostración para mostrar lo que se puede lograr con Nanc en este momento. Esta es una aplicación de cliente en Android y la Web (esta última también desempeña temporalmente el papel de una aplicación de iOS). Así como la aplicación Nanc CMS. Lea más sobre ellos a continuación.
Enlaces
Cliente
Client es una aplicación de demostración de cliente que utiliza una sola biblioteca del ecosistema nanc. Esta biblioteca le permite convertir XML en una interfaz de aplicación en Flutter. Esta aplicación tiene una sola pantalla, creada íntegramente en Nanc, y puede actualizarse cuando se desee y en cualquier momento sin necesidad de almacenes. En la parte inferior derecha hay un botón con un ícono de conexión: es responsable de conectarse a . Más sobre lo que será esta "conexión" a continuación.
Administración
Admin es una aplicación de demostración de Nanc-CMS, con una capa de lógica implementada adicionalmente, que brinda la capacidad de sincronizar con los clientes (más información sobre la conexión a continuación). En la aplicación de demostración de Nanc-CMS, el propio navegador del usuario y su almacenamiento local actúan como "backend". Todo lo que agrega o cambia se almacena solo en su navegador. En Nanc-CMS puedes modificar/crear/eliminar datos relacionados con los modelos existentes (los verás), y - puedes crear tus propios modelos a través de la interfaz y hacer lo mismo con ellos.
Como representación SQL de los modelos de datos utilizados en la creación de esta demostración, puede guiarse por la siguiente captura de pantalla:
Administrador de conexión / "Conexión"
Esta sección se relaciona únicamente con la lógica de la "demostración" en las aplicaciones cliente y CMS. Y se implementó para simular la experiencia de interactuar con Nanc y el proceso de actualización del cliente. Pero primero lo primero.
En un proyecto de producción real, podría usar Nanc de la siguiente manera: implemente una aplicación CMS Nanc estática en algún lugar, con los servicios API implementados. Se comunicaría con su backend y usaría Nanc a su gusto. Su aplicación contiene una biblioteca del ecosistema nanc que le permite renderizar la interfaz. Hizo una actualización: la aplicación cargó un código nuevo desde su backend, actualizó: todos están contentos y satisfechos.
Para mostrar este modelo en acción, se implementa lo mismo, pero de forma simplificada: Nanc CMS existe como estático, se encuentra en las páginas de github y puede usarlo como "en la vida real", pero su navegador actúa como backend. Es decir, las API se implementaron de tal manera que "van a la red", en el almacenamiento local del navegador. Con esta parte hemos terminado, pero todavía queda una aplicación móvil, que de alguna manera debe mostrarte el proceso de "actualización".
Bueno, ahí es donde entra en juego la "conexión". En resumen, puede establecer una conexión directa entre cualquier aplicación de demostración de cliente de Nanc y cualquier aplicación de demostración de Nanc CMS. Para hacer esto, debe hacer clic en el botón inferior derecho con el icono del código QR en el CMS. En la ventana modal que aparece, verá el código QR. A continuación, tiene dos sillas: puede escanear este código con la aplicación de cliente móvil (o navegador) presionando el botón similar en la parte inferior derecha, luego la conexión se establecerá automáticamente. O puede hacer clic en el código QR y los datos necesarios para la conexión se copiarán en el portapapeles. Luego tendrás que pegar estos datos en el campo de entrada de la aplicación móvil y conectarte presionando el botón. Cuando se establezca la conexión, te comprenderás a ti mismo. Después de eso, puede hacer lo que quiera con la página de destino existente y ver los cambios en tiempo real (después de guardar), en la aplicación móvil.
Pero no está limitado a la página de destino . Puede crear cualquier modelo nuevo directamente en el navegador, llenarlo con contenido y, si sus modelos tendrán un campo para la descripción de la interfaz (escriba Pantalla), cuando guarde dichas entidades, también verá el resultado en la aplicación: el La pantalla del nuevo modelo reemplazará la pantalla de la aplicación existente. El único punto es que, dado que la aplicación cliente no sabe qué tipo de campo es su registro recién creado, tiene prescritos posibles identificadores, que se espera que sean ScreenFields.
Entonces, si desea crear una pantalla completamente desde cero y mostrarla en la aplicación, use algo de la siguiente lista como valor de IdField:
pantalla
interfaz de usuario
página
interfaz
margen
vista
Si rompe algo, simplemente reinicie los datos (Chrome: F12 -> Aplicación -> Aplicación -> Almacenamiento -> Borrar datos del sitio), bueno, cuando vuelva a abrir la aplicación cliente, siempre cargará el código de pantalla real creado para esta demostración. (El código de su navegador se cargará solo si se conecta)
Y finalmente, un pequeño ejemplo de cómo crear una nueva página de un nuevo modelo que contiene un ScreenField y representarlo en la aplicación:
¿Que sigue?
La demostración pública está lista. Se escribe el artículo introductorio. Planes futuros para Nanc: completar la integridad funcional del enfoque de interfaz para la creación de modelos, haciendo posible configurar todos los campos: Enum, Selector y MultiSelector. Solucione errores conocidos, como cambiar la posición de los elementos en StructureField. Luego "bla, bla, bla", y luego "fulano de tal". La acumulación será suficiente para el próximo medio año al menos, pero el modelo adicional de expansión de la funcionalidad se basará en las necesidades del cliente, por lo que si tiene ideas/críticas/errores encontrados (y hay muchos de ellos) /cualquier otra cosa: complete el formulario, cuyo enlace está disponible en la aplicación de demostración del cliente.
Si está interesado en las características de Nanc y está interesado en la cooperación, complete el formulario también y definitivamente hablaremos.